1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00
occt/src/Interface/Interface_Graph.cxx
2012-03-05 19:23:40 +04:00

693 lines
22 KiB
C++
Executable File

#include <Interface_Graph.ixx>
#include <Interface_GeneralModule.hxx>
#include <Interface_ReportEntity.hxx>
#include <Standard_DomainError.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Interface_ShareTool.hxx>
// Flags : 0 = Presence, 1 = Sharing Error
#define Graph_Present 0
#define Graph_ShareError 1
// ###########################################################################
// .... CONSTRUCTEURS ....
// .... Construction a partir de la connaissance des Entites ....
Interface_Graph::Interface_Graph
(const Handle(Interface_InterfaceModel)& amodel,
const Interface_GeneralLib& lib)
: themodel (amodel), thepresents ("") , thestats (0,amodel->NbEntities()) ,
theflags (amodel->NbEntities(),2) ,
theshareds (amodel->NbEntities()) , /*thesharnews(amodel->NbEntities()) , */
thesharings (amodel->NbEntities())
{
Handle(Interface_GTool) gtool; // null
theflags.AddFlag ("ShareError"); // -> flag n0 1
Evaluate(lib,gtool);
}
Interface_Graph::Interface_Graph
(const Handle(Interface_InterfaceModel)& amodel,
const Handle(Interface_Protocol)& protocol)
: themodel (amodel) , thepresents ("") ,
thestats (0,amodel->NbEntities()) , theflags (amodel->NbEntities(),2) ,
theshareds (amodel->NbEntities()) , /*thesharnews(amodel->NbEntities()) ,*/
thesharings (amodel->NbEntities())
{
Handle(Interface_GTool) gtool; // null
theflags.AddFlag ("ShareError"); // -> flag n0 1
Evaluate(Interface_GeneralLib(protocol),gtool);
}
Interface_Graph::Interface_Graph
(const Handle(Interface_InterfaceModel)& amodel,
const Handle(Interface_GTool)& gtool)
: themodel (amodel) , thepresents ("") ,
thestats (0,amodel->NbEntities()) , theflags (amodel->NbEntities(),2) ,
theshareds (amodel->NbEntities()) , /*thesharnews(amodel->NbEntities()) , */
thesharings (amodel->NbEntities())
{
theflags.AddFlag ("ShareError"); // -> flag n0 1
Evaluate(gtool->Lib(),gtool);
}
Interface_Graph::Interface_Graph
(const Handle(Interface_InterfaceModel)& amodel)
: themodel (amodel) , thepresents ("") ,
thestats (0,amodel->NbEntities()) , theflags (amodel->NbEntities(),2) ,
theshareds (amodel->NbEntities()) ,
/*thesharnews(amodel->NbEntities()) ,*/ thesharings (amodel->NbEntities())
{
theflags.AddFlag ("ShareError"); // -> flag n0 1
Handle(Interface_GTool) gtool = amodel->GTool();
if (gtool.IsNull()) return;
gtool->Reservate(amodel->NbEntities());
Evaluate (gtool->Lib(),gtool);
}
void Interface_Graph::Evaluate
(const Interface_GeneralLib& lib, const Handle(Interface_GTool)& gtool)
{
// Evaluation d un Graphe de dependances : sur chaque Entite, on prend sa
// liste "Shared". On en deduit les "Sharing" directement
Standard_Boolean patool = gtool.IsNull();
Standard_Integer n = Size(), total = 0;
theshareds.Clear();
thesharings.Clear();
TColStd_Array1OfInteger counts (0,n); counts.Init(0);
TColStd_Array1OfInteger lasts (0,n); lasts.Init(0);
Standard_Integer i; // svv Jan11 2000 : porting on DEC
for (i = 1; i <= n; i ++) {
theshareds.SetNumber (i);
// ATTENTION : Si Entite non chargee donc illisible, basculer sur son
// "Contenu" equivalent
Handle(Standard_Transient) ent = themodel->Value(i);
if (themodel->IsRedefinedContent(i)) ent = themodel->ReportEntity(i)->Content();
// Resultat obtenu via GeneralLib
Interface_EntityIterator iter;
Handle(Interface_GeneralModule) module;
Standard_Integer CN;
if (patool) {
if (lib.Select(ent,module,CN)) module->FillShared(themodel,CN,ent,iter);
} else {
if (gtool->Select(ent,module,CN)) module->FillShared(themodel,CN,ent,iter);
}
theshareds.Reservate (iter.NbEntities());
// Mise en forme : liste d entiers
for (iter.Start(); iter.More(); iter.Next()) {
// num = 0 -> on sort du Model de depart, le noter "Error" et passer
Standard_Integer num = EntityNumber(iter.Value());
if (num == 0) theflags.SetTrue (i,Graph_ShareError);
else {
// controle d unicite de couple (pere-fils)
if (lasts(num) == i) continue;
total ++;
lasts.ChangeValue(num) = i;
theshareds.Add (num);
counts.ChangeValue(num) ++;
// References inverses : plus tard
}
}
}
// Les references inverses : preallocation (pour compte > 1 seulement)
thesharings.SetNumber(0); thesharings.Reservate (total);
for (i = 1; i <= n; i ++) {
if (counts(i) < 2) continue;
thesharings.SetNumber(i);
thesharings.Reservate (-counts(i));
}
// Enregistrement par inversion
for (i = 1; i <= n; i ++) {
theshareds.SetNumber (i);
Standard_Integer j,num, nb = theshareds.Length();
for (j = 1; j <= nb; j ++) {
num = theshareds.Value(j);
thesharings.SetNumber(-num);
thesharings.Add(-i);
}
}
}
void Interface_Graph::EvalSharings ()
{
thesharings.Clear();
Standard_Integer n = thesharings.NbEntities();
// Difference avec Evaluate : SharedNums prend les Redefinis si necessaire
for (Standard_Integer i = 1; i <= n; i ++) {
Standard_Integer nb, num;
if (thesharnews.IsRedefined(i)) {
thesharnews.SetNumber(i);
nb = thesharnews.Length();
for (Standard_Integer j = 1; j <= nb; j ++) {
num = thesharnews.Value (j);
thesharings.SetNumber (num);
thesharings.Reservate (thesharings.Length()+1);
thesharings.Add (i);
}
} else {
theshareds.SetNumber(i);
nb = theshareds.Length();
for (Standard_Integer j = 1; j <= nb; j ++) {
num = theshareds.Value (j);
thesharings.SetNumber (num);
thesharings.Reservate (thesharings.Length()+1);
thesharings.Add (i);
}
}
}
}
// .... Construction depuis un autre Graph ....
Interface_Graph::Interface_Graph
(const Interface_Graph& agraph, const Standard_Boolean /*copied*/)
: themodel (agraph.Model()), thepresents ("") ,
thestats (0,agraph.Size()) ,
theflags (agraph.BitMap(),Standard_True) ,
theshareds (agraph.BasicSharedTable(),Standard_True) ,
thesharnews (agraph.RedefinedSharedTable(),Standard_True) ,
thesharings (agraph.SharingTable(),Standard_True)
{
Standard_Integer nb = Size();
for (Standard_Integer i = 1; i <= nb; i ++)
thestats.SetValue (i,agraph.Status(i));
}
Interface_IntList Interface_Graph::BasicSharedTable () const
{ return theshareds; }
Interface_IntList Interface_Graph::RedefinedSharedTable () const
{ return thesharnews; }
Interface_IntList Interface_Graph::SharingTable () const
{ return thesharings; }
// ###########################################################################
// .... ACCES UNITAIRES AUX DONNEES DE BASE ....
void Interface_Graph::Reset ()
{
thestats.Init(0);
theflags.Init (Standard_False, Graph_Present);
thesharnews.Clear();
EvalSharings();
}
void Interface_Graph::ResetStatus ()
{ thestats.Init(0); theflags.Init (Standard_False, Graph_Present); }
Standard_Integer Interface_Graph::Size () const
{ return thestats.Upper(); }
Standard_Integer Interface_Graph::EntityNumber
(const Handle(Standard_Transient)& ent) const
{ return themodel->Number(ent); }
Standard_Boolean Interface_Graph::IsPresent
(const Standard_Integer num) const
{
if (num <= 0 || num > Size()) return Standard_False;
return theflags.Value (num,Graph_Present);
}
Standard_Boolean Interface_Graph::IsPresent
(const Handle(Standard_Transient)& ent) const
{ return IsPresent(EntityNumber(ent)); }
const Handle(Standard_Transient)& Interface_Graph::Entity
(const Standard_Integer num) const
{ return themodel->Value(num); }
Standard_Integer Interface_Graph::Status (const Standard_Integer num) const
{ return thestats.Value(num); }
Standard_Integer& Interface_Graph::CStatus (const Standard_Integer num)
{ return thestats.ChangeValue(num); }
void Interface_Graph::SetStatus
(const Standard_Integer num, const Standard_Integer stat)
{ thestats.SetValue(num,stat); }
void Interface_Graph::RemoveItem(const Standard_Integer num)
{
thestats.SetValue(num,0); theflags.SetFalse (num,Graph_Present);
}
void Interface_Graph::ChangeStatus
(const Standard_Integer oldstat, const Standard_Integer newstat)
{
Standard_Integer nb = thestats.Upper();
for (Standard_Integer i = 1; i <= nb; i ++) {
if (thestats.Value(i) == oldstat) thestats.SetValue(i,newstat);
}
}
void Interface_Graph::RemoveStatus(const Standard_Integer stat)
{
Standard_Integer nb = thestats.Upper();
for (Standard_Integer i = 1; i <= nb; i ++) {
if (thestats.Value(i) == stat) RemoveItem(i);
}
}
const Interface_BitMap& Interface_Graph::BitMap () const
{ return theflags; }
Interface_BitMap& Interface_Graph::CBitMap ()
{ return theflags; }
// ###########################################################################
// .... Chargements Elementaires avec Propagation de "Share" .... //
const Handle(Interface_InterfaceModel)& Interface_Graph::Model() const
{ return themodel; }
void Interface_Graph::GetFromModel ()
{
if (themodel.IsNull()) return; // no model ... (-> on n ira pas loin)
theflags.Init (Standard_True,Graph_Present);
thestats.Init (0);
}
void Interface_Graph::GetFromEntity
(const Handle(Standard_Transient)& ent, const Standard_Boolean shared,
const Standard_Integer newstat)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
if (theflags.CTrue(num,Graph_Present)) return; // deja pris : on passe
thestats.SetValue(num,newstat);
if (!shared) return;
// Attention a la redefinition !
Interface_IntList list = thesharnews;
if (!list.IsRedefined(num)) list = theshareds;
list.SetNumber (num);
Standard_Integer nb = list.Length();
for (Standard_Integer i = 1; i <= nb; i ++) GetFromEntity
(themodel->Value (list.Value(i)),Standard_True,newstat);
}
void Interface_Graph::GetFromEntity
(const Handle(Standard_Transient)& ent, const Standard_Boolean shared,
const Standard_Integer newstat, const Standard_Integer overlapstat,
const Standard_Boolean cumul)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
Standard_Boolean pasla = !theflags.CTrue (num,Graph_Present);
Standard_Integer stat = thestats.Value(num);
if (pasla) {
/// theflags.SetTrue (num, Graph_Present); // nouveau : noter avec newstat
thestats.SetValue(num,newstat);
} else {
Standard_Integer overstat = stat;
if (stat != newstat) { // deja pris, meme statut : passer
if (cumul) overstat += overlapstat; // nouveau statut : avec cumul ...
else overstat = overlapstat; // ... ou sans (statut force)
if (stat != overstat) // si repasse deja faite, passer
thestats.SetValue(num,overstat);
}
}
if (!shared) return;
// Attention a la redefinition !
Interface_IntList list = thesharnews;
if (!list.IsRedefined(num)) list = theshareds;
list.SetNumber (num);
Standard_Integer nb = list.Length();
for (Standard_Integer i = 1; i <= nb; i ++) GetFromEntity
(themodel->Value (list.Value(i)),Standard_True,newstat);
}
void Interface_Graph::GetFromIter
(const Interface_EntityIterator& iter, const Standard_Integer newstat)
{
for (iter.Start(); iter.More(); iter.Next()) {
Handle(Standard_Transient) ent = iter.Value();
Standard_Integer num = EntityNumber(ent);
if (num == 0) continue;
if (theflags.CTrue(num,Graph_Present)) continue;
thestats.SetValue(num,newstat);
}
}
void Interface_Graph::GetFromIter
(const Interface_EntityIterator& iter,
const Standard_Integer newstat, const Standard_Integer overlapstat,
const Standard_Boolean cumul)
{
for (iter.Start(); iter.More(); iter.Next()) {
Handle(Standard_Transient) ent = iter.Value();
Standard_Integer num = EntityNumber(ent);
if (num == 0) continue;
/*Standard_Boolean pasla = !*/theflags.Value(num,Graph_Present);
/*Standard_Integer stat = */thestats.Value(num);
GetFromEntity (ent,Standard_False,newstat,overlapstat,cumul);
}
}
void Interface_Graph::GetFromGraph (const Interface_Graph& agraph)
{
if (Model() != agraph.Model()) Standard_DomainError::Raise
("Graph from Interface : GetFromGraph");
Standard_Integer nb = Size();
for (Standard_Integer i = 1; i <= nb; i ++) {
if (agraph.IsPresent(i))
GetFromEntity (agraph.Entity(i),Standard_False,agraph.Status(i));
}
}
void Interface_Graph::GetFromGraph
(const Interface_Graph& agraph, const Standard_Integer stat)
{
if (Model() != agraph.Model()) Standard_DomainError::Raise
("Graph from Interface : GetFromGraph");
Standard_Integer nb = Size();
for (Standard_Integer i = 1; i <= nb; i ++) {
if (agraph.IsPresent(i) && agraph.Status(i) == stat)
GetFromEntity (agraph.Entity(i),Standard_False,stat);
}
}
// #####################################################################
// .... Listage des Entites Partagees ....
Standard_Boolean Interface_Graph::HasShareErrors
(const Handle(Standard_Transient)& ent) const
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return Standard_True;
return theflags.Value (num,Graph_ShareError);
}
// A chaque entite, on peut attacher une Liste de numeros d entites partagees
// Si elle est nulle, BasicShareds convient, sinon on prend RedefinedShareds
Standard_Boolean Interface_Graph::HasRedefinedShareds
(const Handle(Standard_Transient)& ent) const
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return Standard_False;
return thesharnews.IsRedefined (num);
}
Interface_EntityIterator Interface_Graph::Shareds
(const Handle(Standard_Transient)& ent) const
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) Standard_DomainError::Raise ("Interface : Shareds");
Interface_EntityIterator iter;
Interface_IntList list = thesharnews;
if (!list.IsRedefined(num)) list = theshareds;
list.SetNumber (num);
Standard_Integer nb = list.Length();
for (Standard_Integer i = 1; i <= nb; i ++)
iter.GetOneItem (themodel->Value (list.Value(i) ));
return iter;
}
Interface_IntList Interface_Graph::SharedNums
(const Standard_Integer num) const
{
Interface_IntList list = thesharnews;
if (!list.IsRedefined(num)) list = theshareds;
list.SetNumber (num);
return list;
}
Interface_EntityIterator Interface_Graph::Sharings
(const Handle(Standard_Transient)& ent) const
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) Standard_DomainError::Raise ("Interface : Sharings");
Interface_EntityIterator iter;
Interface_IntList list = thesharings; list.SetNumber (num);
Standard_Integer nb = list.Length();
for (Standard_Integer i = 1; i <= nb; i ++)
iter.GetOneItem (themodel->Value(list.Value(i)));
return iter;
}
Interface_IntList Interface_Graph::SharingNums
(const Standard_Integer num) const
{
Interface_IntList list = thesharings;
if (num > 0) list.SetNumber (num);
return list;
}
static void AddTypedSharings
(const Handle(Standard_Transient)& ent, const Handle(Standard_Type)& type,
Interface_EntityIterator& iter, const Standard_Integer n,
const Interface_Graph& G)
{
if (ent.IsNull()) return;
if (ent->IsKind(type)) { iter.AddItem (ent); return; }
if (iter.NbEntities() > n) return;
Interface_IntList list = G.SharingNums(G.EntityNumber(ent));
Standard_Integer nb = list.Length();
for (Standard_Integer i = 1; i <= nb; i ++)
AddTypedSharings (G.Entity(list.Value(i)) ,type,iter,nb,G);
}
Interface_EntityIterator Interface_Graph::TypedSharings
(const Handle(Standard_Transient)& ent, const Handle(Standard_Type)& type) const
{
Interface_EntityIterator iter;
Standard_Integer n = Size();
AddTypedSharings (ent,type,iter,n,*this);
return iter;
}
Interface_EntityIterator Interface_Graph::RootEntities () const
{
Interface_EntityIterator iter;
Standard_Integer nb = Size();
Interface_IntList list (thesharings);
for (Standard_Integer i = 1; i <= nb; i ++) {
list.SetNumber (i);
if (list.Length() == 0) iter.GetOneItem (themodel->Value(i));
}
return iter;
}
// ######################################################################
// .... Redefinition des listes Shared-Sharing ....
void Interface_Graph::SetShare
(const Handle(Standard_Transient)& ent)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
SetShare (ent,SharedNums(num));
}
void Interface_Graph::SetShare
(const Handle(Standard_Transient)& ent,
const Interface_EntityIterator& list)
{
if(!thesharnews.NbEntities())
thesharnews.Initialize(themodel->NbEntities());
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
thesharnews.SetNumber (num);
thesharnews.SetRedefined (Standard_True);
thesharnews.Reservate (list.NbEntities());
for (list.Start(); list.More(); list.Next()) {
Standard_Integer nsh = EntityNumber(list.Value());
if (nsh != 0) thesharnews.Add (nsh);
}
}
void Interface_Graph::SetShare
(const Handle(Standard_Transient)& ent, const Interface_IntList& list)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
if(!thesharnews.NbEntities())
thesharnews.Initialize(themodel->NbEntities());
Standard_Integer i, n = list.Length();
thesharnews.SetNumber (num);
thesharnews.SetRedefined (Standard_True);
thesharnews.Reservate (n);
for (i = 1; i <= n; i ++) {
Standard_Integer nsh = list.Value(i);
if (nsh != 0) thesharnews.Add (nsh);
}
}
void Interface_Graph::SetNoShare
(const Handle(Standard_Transient)& ent)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
if(!thesharnews.NbEntities()) return;
thesharnews.SetNumber (num);
thesharnews.SetRedefined (Standard_False);
}
void Interface_Graph::SetNoShare (const Interface_EntityIterator& list)
{
for (list.Start(); list.More(); list.Next()) SetNoShare(list.Value());
}
void Interface_Graph::AddShared
(const Handle(Standard_Transient)& ent,
const Handle(Standard_Transient)& shared)
{
//Standard_Integer i, nb; svv Feb21 2000 : porting on SIL
Standard_Integer num = EntityNumber(ent);
Standard_Integer nsh = EntityNumber(shared);
if (!thesharnews.IsRedefined(num) || num == 0 || nsh == 0) Standard_DomainError::Raise
("Interface Graph : AddShared, cannot be applied");
if(!thesharnews.NbEntities())
thesharnews.Initialize(themodel->NbEntities());
// Liste Shared(ent)
thesharnews.SetNumber (num);
thesharnews.Reservate (thesharnews.Length()+1);
thesharnews.Add (nsh);
// Liste Sharing(shared)
thesharings.SetNumber (nsh);
thesharings.Reservate (thesharings.Length()+1);
thesharings.Add (num);
}
void Interface_Graph::RemoveShared
(const Handle(Standard_Transient)& ent,
const Handle(Standard_Transient)& shared)
{
Standard_Integer num = EntityNumber(ent);
Standard_Integer nsh = EntityNumber(shared);
if (!thesharnews.IsRedefined(num) || num == 0 || nsh == 0) Standard_DomainError::Raise
("Interface Graph : RemoveShared, cannot be applied");
// Liste Shared (ent)
if(!thesharnews.NbEntities())
thesharnews.Initialize(themodel->NbEntities());
thesharnews.SetNumber (num);
Standard_Integer i,nbsh = thesharnews.Length();
for (i = nbsh; i > 0; i --)
if (thesharnews.Value(i) == nsh) thesharnews.Remove(i);
// Liste Sharing (shared)
thesharings.SetNumber (nsh);
nbsh = thesharings.Length();
for (i = nbsh; i > 0; i --)
if (thesharings.Value(i) == num) thesharings.Remove(i);
}
void Interface_Graph::ResetShare
(const Handle(Standard_Transient)& ent)
{
Standard_Integer num = EntityNumber(ent);
if (num == 0) return;
Interface_IntList snew(thesharnews);
if (!thesharnews.NbEntities() || !snew.IsRedefined(num)) return;
snew.SetNumber (num);
Interface_IntList sold(theshareds);
sold.SetNumber (num);
// Attention aux Sharings ... Il va falloir ajouter, supprimer ... laisser !
// Tableau // Entites : 0 hors jeu 1 reapparait 2 disparait 3 reste
Standard_Integer n = Size();
TColStd_Array1OfInteger oldnew(1,n); oldnew.Init(0);
Standard_Integer ns = sold.Length();
Standard_Integer i; // svv Jan11 2000 : porting on DEC
for (i = 1; i <= ns; i ++)
oldnew.SetValue(sold.Value(i),1); // pourra passer en 3 plus tard ...
ns = snew.Length();
for (i = 1; i <= ns; i ++) {
Standard_Integer oldstat = oldnew.Value(snew.Value(i));
oldnew.SetValue(snew.Value(i),oldstat+2); // 0 -> 2, 1 -> 3
}
// Muni de ces donnees, on pourra modifier les listes Sharings impliquees
for (i = 1; i <= n; i ++) {
Standard_Integer oldstat = oldnew.Value(snew.Value(i));
if (oldstat == 0 || oldstat == 2) continue;
thesharings.SetNumber(i);
if (oldstat == 1) {
thesharings.Reservate (thesharings.Length()+1);
thesharings.Add (num);
} else if (oldstat == 3) {
Standard_Integer j,nbsh = thesharings.Length();
for (j = nbsh; j > 0; j --)
if (thesharings.Value(j) == num) thesharings.Remove(j);
}
}
// Shared : beaucoup plus simple, ANNULER Redefined
thesharnews.SetRedefined (Standard_False);
}
void Interface_Graph::ResetAllShare ()
{
thesharnews.Clear();
EvalSharings();
}
Handle(TCollection_HAsciiString) Interface_Graph::Name
(const Handle(Standard_Transient)& ent) const
{
Handle(TCollection_HAsciiString) str;
if (themodel.IsNull()) return str;
if (themodel->Number(ent)) return str;
Handle(Interface_GTool) gtool = themodel->GTool();
if (gtool.IsNull()) return str;
Handle(Interface_GeneralModule) module;
Standard_Integer CN;
if (!gtool->Select(ent,module,CN)) return str;
Interface_ShareTool sht (*this);
return module->Name (CN,ent,sht);
}