0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[occt.git] / src / Interface / Interface_Graph.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Interface_BitMap.hxx>
16 #include <Interface_EntityIterator.hxx>
17 #include <Interface_GeneralLib.hxx>
18 #include <Interface_GeneralModule.hxx>
19 #include <Interface_Graph.hxx>
20 #include <Interface_GTool.hxx>
21 #include <Interface_InterfaceModel.hxx>
22 #include <Interface_Protocol.hxx>
23 #include <Interface_ReportEntity.hxx>
24 #include <Interface_ShareTool.hxx>
25 #include <Standard_DomainError.hxx>
26 #include <Standard_Transient.hxx>
27 #include <TCollection_HAsciiString.hxx>
28 #include <TColStd_Array1OfInteger.hxx>
29 #include <TColStd_HSequenceOfTransient.hxx>
30 #include <TColStd_ListIteratorOfListOfInteger.hxx>
31
32 // Flags : 0 = Presence, 1 = Sharing Error
33 #define Graph_Present 0
34 #define Graph_ShareError 1
35
36
37 //  ###########################################################################
38
39 //  ....                           CONSTRUCTEURS                           ....
40
41 //  ....       Construction a partir de la connaissance des Entites        ....
42
43
44 Interface_Graph::Interface_Graph
45 (const Handle(Interface_InterfaceModel)& amodel,
46  const Interface_GeneralLib& /*lib*/,
47  Standard_Boolean theModeStat)
48  : themodel   (amodel), thepresents ("") 
49 {
50   if(theModeStat)
51     InitStats();
52   Evaluate();
53 }
54
55 Interface_Graph::Interface_Graph
56 (const Handle(Interface_InterfaceModel)& amodel,
57  const Handle(Interface_Protocol)& /*protocol*/,
58  Standard_Boolean theModeStat)
59  : themodel   (amodel) , thepresents ("")    
60
61 {
62  if(theModeStat)
63     InitStats();  
64   Evaluate();
65 }
66
67 Interface_Graph::Interface_Graph
68 (const Handle(Interface_InterfaceModel)& amodel,
69  const Handle(Interface_GTool)& /*gtool*/,
70  Standard_Boolean theModeStat)
71  : themodel   (amodel) , thepresents ("") 
72 {
73   if(theModeStat)
74     InitStats();
75   Evaluate();
76 }
77
78 Interface_Graph::Interface_Graph
79 (const Handle(Interface_InterfaceModel)& amodel,
80  Standard_Boolean theModeStat)
81 : themodel   (amodel) , thepresents ("")  
82 {
83   if(theModeStat)
84     InitStats();
85   Evaluate ();
86 }
87
88 //  ....                Construction depuis un autre Graph                ....
89
90 Interface_Graph::Interface_Graph
91 (const Interface_Graph& agraph, const Standard_Boolean /*copied*/)
92 : themodel   (agraph.Model()), thepresents ("") 
93 {
94   thesharings = agraph.SharingTable();
95   Standard_Integer nb = agraph.NbStatuses();
96   if(!nb)
97     return;
98   if(thestats.IsNull())
99     thestats = new TColStd_HArray1OfInteger(1,nb);
100   for (Standard_Integer i = 1; i <= nb; i ++)
101     thestats->SetValue (i,agraph.Status(i));
102   theflags.Initialize(agraph.BitMap(),Standard_True);
103 }
104
105 Interface_Graph& Interface_Graph::operator= (const Interface_Graph& theOther)
106 {
107   themodel = theOther.Model();
108   thepresents = theOther.thepresents;
109   thesharings = theOther.SharingTable();
110   thestats.Nullify();
111
112   const Standard_Integer nb = theOther.NbStatuses();
113   if (nb != 0)
114   {
115     thestats = new TColStd_HArray1OfInteger(1, nb);
116     for (Standard_Integer i = 1; i <= nb; ++i)
117     {
118       thestats->SetValue (i, theOther.Status(i));
119     }
120     theflags.Initialize (theOther.BitMap(), Standard_True);
121   }
122   return *this;
123 }
124
125 void Interface_Graph::InitStats()
126 {
127   thestats = new TColStd_HArray1OfInteger(1,themodel->NbEntities()) , 
128     theflags.Initialize(themodel->NbEntities(),2);
129   theflags.AddFlag ("ShareError");
130 }
131
132 Standard_Integer Interface_Graph::NbStatuses() const
133 {
134   return (thestats.IsNull() ? 0 : thestats->Length());
135 }
136
137 const Handle(TColStd_HArray1OfListOfInteger)& Interface_Graph::SharingTable () const
138 {  return thesharings;  }
139
140 void Interface_Graph::Evaluate()
141 {
142   //  Evaluation d un Graphe de dependances : sur chaque Entite, on prend sa
143   //  liste "Shared". On en deduit les "Sharing"  directement
144   Standard_Integer n = Size();
145   thesharings = new TColStd_HArray1OfListOfInteger(1,n);//TColStd_HArray1OfTransient(1,n);//Clear();
146   if(themodel->GTool().IsNull())
147     return;
148   
149
150   Standard_Integer i; // svv Jan11 2000 : porting on DEC
151   for (i = 1; i <= n; i ++) {
152      //    ATTENTION : Si Entite non chargee donc illisible, basculer sur son
153     //    "Contenu" equivalent
154     Handle(Standard_Transient) ent = themodel->Value(i);
155   
156
157     //    Resultat obtenu via GeneralLib
158     Interface_EntityIterator iter = GetShareds(ent);
159
160     //    Mise en forme : liste d entiers
161     for (iter.Start(); iter.More(); iter.Next()) {
162       //    num = 0 -> on sort du Model de depart, le noter "Error" et passer
163       Handle(Standard_Transient) entshare = iter.Value();
164       if(entshare == ent)
165         continue;
166
167       Standard_Integer num = EntityNumber(entshare);
168
169       if (!num )  
170       {
171         if(!thestats.IsNull())
172           theflags.SetTrue (i,Graph_ShareError);
173         continue;
174       }
175       thesharings->ChangeValue(num).Append(i);
176     }
177   }
178 }
179
180 //  ....                Construction depuis un autre Graph                ....
181
182
183 //  ###########################################################################
184
185 //  ....                ACCES UNITAIRES AUX DONNEES DE BASE                ....
186
187 void  Interface_Graph::Reset ()
188 {
189   if(!thestats.IsNull())
190   {
191     thestats.Nullify();
192     theflags.Init (Standard_False, Graph_Present);
193   }
194
195 }
196
197 void  Interface_Graph::ResetStatus ()
198
199   if(!thestats.IsNull())
200   {
201     thestats->Init(0);  
202     theflags.Init (Standard_False, Graph_Present);
203   }
204 }
205
206
207 Standard_Integer  Interface_Graph::Size () const 
208 {  return themodel->NbEntities(); }//thestats.Upper();  }
209
210 Standard_Integer  Interface_Graph::EntityNumber
211 (const Handle(Standard_Transient)& ent) const 
212 {  return themodel->Number(ent);  }
213
214 Standard_Boolean  Interface_Graph::IsPresent
215 (const Standard_Integer num) const 
216 {
217   if (num <= 0 || num > Size()) 
218     return Standard_False;
219   return (!thestats.IsNull() ? theflags.Value (num,Graph_Present) : Standard_False);
220 }
221
222 Standard_Boolean  Interface_Graph::IsPresent
223 (const Handle(Standard_Transient)& ent) const 
224 {  return IsPresent(EntityNumber(ent));  }
225
226 const Handle(Standard_Transient)&  Interface_Graph::Entity
227 (const Standard_Integer num) const 
228 {  
229   return themodel->Value(num);  
230 }
231
232
233 Standard_Integer  Interface_Graph::Status (const Standard_Integer num) const
234 {  
235   return (!thestats.IsNull() ? thestats->Value(num) : 0);  
236 }
237
238 void  Interface_Graph::SetStatus
239 (const Standard_Integer num, const Standard_Integer stat)
240 {  
241   if(!thestats.IsNull())
242     thestats->SetValue(num,stat);  
243 }
244
245 void  Interface_Graph::RemoveItem(const Standard_Integer num)
246 {
247   if(!thestats.IsNull())
248   {
249     thestats->SetValue(num,0);  
250     theflags.SetFalse (num,Graph_Present);
251   }
252 }
253
254 void  Interface_Graph::ChangeStatus
255 (const Standard_Integer oldstat, const Standard_Integer newstat)
256 {
257   if(thestats.IsNull())
258     return;
259   Standard_Integer nb = thestats->Upper();
260   for (Standard_Integer i = 1; i <= nb; i ++) {
261     if (thestats->Value(i) == oldstat) 
262       thestats->SetValue(i,newstat);
263   }
264 }
265
266 void  Interface_Graph::RemoveStatus(const Standard_Integer stat)
267 {
268   if(thestats.IsNull())
269     return;
270   Standard_Integer nb = thestats->Upper();
271   for (Standard_Integer i = 1; i <= nb; i ++) {
272     if (thestats->Value(i) == stat) RemoveItem(i);
273   }
274 }
275
276 const Interface_BitMap&  Interface_Graph::BitMap () const
277 {  return theflags;  }
278
279 Interface_BitMap&  Interface_Graph::CBitMap ()
280 {  return theflags;  }
281
282 //  ###########################################################################
283
284 //  ....      Chargements Elementaires avec Propagation de "Share"      .... //
285
286 const Handle(Interface_InterfaceModel)&  Interface_Graph::Model() const 
287 {  return themodel;  }
288
289 void  Interface_Graph::GetFromModel ()
290 {
291   if (themodel.IsNull() || thestats.IsNull()) 
292     return;    // no model ... (-> on n ira pas loin)
293   theflags.Init (Standard_True,Graph_Present);
294   thestats->Init (0);
295 }
296
297 void  Interface_Graph::GetFromEntity
298 (const Handle(Standard_Transient)& ent, const Standard_Boolean shared,
299  const Standard_Integer newstat)
300 {
301   if(thestats.IsNull())
302     return;
303   Standard_Integer num = EntityNumber(ent);
304   if (!num ) 
305     return;
306   if (theflags.CTrue(num,Graph_Present)) return;  // deja pris : on passe
307   thestats->SetValue(num,newstat);
308   if (!shared) return;
309   //  Attention a la redefinition !
310   Interface_EntityIterator aIter = GetShareds(ent);
311
312   for ( ; aIter.More() ; aIter.Next())    
313     GetFromEntity(aIter.Value(),Standard_True,newstat);
314 }
315
316 void  Interface_Graph::GetFromEntity
317 (const Handle(Standard_Transient)& ent, const Standard_Boolean shared,
318  const Standard_Integer newstat, const Standard_Integer overlapstat,
319  const Standard_Boolean cumul)
320 {
321   if(thestats.IsNull())
322     return;
323   Standard_Integer num   = EntityNumber(ent);
324   if (!num ) return;
325   Standard_Boolean pasla = !theflags.CTrue (num,Graph_Present);
326   Standard_Integer stat  = thestats->Value(num); 
327
328   if (pasla) {
329     ///    theflags.SetTrue (num, Graph_Present);   // nouveau : noter avec newstat
330     thestats->SetValue(num,newstat);
331   } else {
332     Standard_Integer overstat = stat;
333     if (stat != newstat) {                   // deja pris, meme statut : passer
334       if (cumul) overstat += overlapstat;    // nouveau statut : avec cumul ...
335       else       overstat  = overlapstat;    // ... ou sans (statut force)
336       if (stat != overstat)                  // si repasse deja faite, passer
337         thestats->SetValue(num,overstat);
338     }
339   }
340   if (!shared) return;
341   //  Attention a la redefinition !
342   Interface_EntityIterator aIter = GetShareds(ent);
343
344   for ( ; aIter.More() ; aIter.Next())    
345     GetFromEntity(aIter.Value(),Standard_True,newstat);
346 }
347
348 void  Interface_Graph::GetFromIter
349 (const Interface_EntityIterator& iter, const Standard_Integer newstat)
350 {
351    if(thestats.IsNull())
352     return;
353   for (iter.Start(); iter.More(); iter.Next()) {
354     Handle(Standard_Transient) ent = iter.Value();
355     Standard_Integer num = EntityNumber(ent);
356     if (!num) 
357       continue;
358     if (theflags.CTrue(num,Graph_Present)) 
359       continue;
360     thestats->SetValue(num,newstat);
361   }
362 }
363
364
365 void  Interface_Graph::GetFromIter
366 (const Interface_EntityIterator& iter,
367  const Standard_Integer newstat, const Standard_Integer overlapstat,
368  const Standard_Boolean cumul)
369 {
370   if(thestats.IsNull())
371     return;
372   for (iter.Start(); iter.More(); iter.Next()) {
373     Handle(Standard_Transient) ent = iter.Value();
374     Standard_Integer num   = EntityNumber(ent);
375     if (!num) 
376       continue;
377     /*Standard_Boolean pasla = !*/theflags.Value(num,Graph_Present);
378     /*Standard_Integer stat  = */thestats->Value(num); 
379     GetFromEntity (ent,Standard_False,newstat,overlapstat,cumul);
380   }
381 }
382
383
384 void Interface_Graph::GetFromGraph (const Interface_Graph& agraph)
385 {
386   if (Model() != agraph.Model()) throw Standard_DomainError("Graph from Interface : GetFromGraph");
387   Standard_Integer nb = Size();
388   for (Standard_Integer i = 1; i <= nb; i ++) {
389     if (agraph.IsPresent(i))
390       GetFromEntity (agraph.Entity(i),Standard_False,agraph.Status(i));
391   }
392 }
393
394 void Interface_Graph::GetFromGraph
395 (const Interface_Graph& agraph, const Standard_Integer stat)
396 {
397   if (Model() != agraph.Model()) throw Standard_DomainError("Graph from Interface : GetFromGraph");
398   Standard_Integer nb = Size();
399   for (Standard_Integer i = 1; i <= nb; i ++) {
400     if (agraph.IsPresent(i) && agraph.Status(i) == stat)
401       GetFromEntity (agraph.Entity(i),Standard_False,stat);
402   }
403 }
404
405 //  #####################################################################
406
407 //  ....                Listage des Entites Partagees                ....
408
409 Standard_Boolean Interface_Graph::HasShareErrors
410 (const Handle(Standard_Transient)& ent) const
411 {
412   if(thestats.IsNull())
413     return Standard_False;
414   Standard_Integer num   = EntityNumber(ent);
415   if (num == 0) return Standard_True;
416   return theflags.Value (num,Graph_ShareError);
417 }
418
419 Interface_EntityIterator Interface_Graph::Shareds
420 (const Handle(Standard_Transient)& ent) const
421 {
422   Interface_EntityIterator iter;
423   Standard_Integer num   = EntityNumber(ent);
424   if(!num)
425     return iter;
426
427   Handle(Standard_Transient) aCurEnt =  ent;
428   if (themodel->IsRedefinedContent(num)) 
429      aCurEnt = themodel->ReportEntity(num)->Content();
430
431   //if (num == 0)  throw Standard_DomainError("Interface : Shareds");
432   Handle(Interface_GeneralModule) module;
433   Standard_Integer CN;
434   if (themodel->GTool()->Select(aCurEnt,module,CN))  
435     module->FillShared(themodel,CN,aCurEnt,iter);
436   return iter;
437 }
438
439 Handle(TColStd_HSequenceOfTransient) Interface_Graph::GetShareds(const Handle(Standard_Transient)& ent) const
440 {
441   Handle(TColStd_HSequenceOfTransient) aseq = new TColStd_HSequenceOfTransient;
442   Interface_EntityIterator iter = Shareds(ent);
443   for( ; iter.More(); iter.Next())
444     aseq->Append(iter.Value());
445   return aseq;
446 }
447
448 Handle(TColStd_HSequenceOfTransient) Interface_Graph::GetSharings(const Handle(Standard_Transient)& ent) const
449 {
450   Standard_Integer num   = EntityNumber(ent);
451   if(!num)
452     return 0;
453   //return Handle(TColStd_HSequenceOfTransient)::DownCast(thesharings->Value(num));
454   const TColStd_ListOfInteger& alist = thesharings->Value(num);
455   Handle(TColStd_HSequenceOfTransient) aSharings = new TColStd_HSequenceOfTransient;
456   TColStd_ListIteratorOfListOfInteger aIt(alist);
457   for( ; aIt.More() ; aIt.Next())
458     aSharings->Append(Entity(aIt.Value()));
459   return aSharings;
460 }
461
462 Interface_EntityIterator Interface_Graph::Sharings
463 (const Handle(Standard_Transient)& ent) const
464 {
465   Interface_EntityIterator iter;
466   iter.AddList(GetSharings(ent));
467   return iter;
468
469 }
470
471 static void AddTypedSharings
472 (const Handle(Standard_Transient)& ent, const Handle(Standard_Type)& type,
473  Interface_EntityIterator& iter, const Standard_Integer n,
474  const Interface_Graph& G)
475 {
476   if (ent.IsNull()) return;
477   if (ent->IsKind(type))  {  iter.AddItem (ent);  return;  }
478   if (iter.NbEntities() > n) return;
479
480   Handle(TColStd_HSequenceOfTransient) list = G.GetSharings(ent);
481   if(list.IsNull())
482     return;
483
484   Standard_Integer nb = list->Length();
485   for (Standard_Integer i = 1; i <= nb; i ++)
486     AddTypedSharings (list->Value(i) ,type,iter,nb,G);
487 }
488
489 Interface_EntityIterator Interface_Graph::TypedSharings
490 (const Handle(Standard_Transient)& ent, const Handle(Standard_Type)& type) const
491 {
492   Interface_EntityIterator iter;
493   Standard_Integer n = Size();
494   AddTypedSharings (ent,type,iter,n,*this);
495   return iter;
496 }
497
498
499 Interface_EntityIterator Interface_Graph::RootEntities () const
500 {
501   Interface_EntityIterator iter;
502   Standard_Integer nb = thesharings->Length();
503   for (Standard_Integer i = 1; i <= nb; i ++) {
504     if(!thesharings->Value(i).IsEmpty())
505       continue;
506     iter.AddItem(Entity(i));
507   }
508   return iter;
509 }
510
511 Handle(TCollection_HAsciiString)  Interface_Graph::Name(const Handle(Standard_Transient)& ent) const
512 {
513   Handle(TCollection_HAsciiString) str;
514   if (themodel.IsNull()) return str;
515   if (themodel->Number(ent)) return str;
516
517   Handle(Interface_GTool) gtool = themodel->GTool();
518   if (gtool.IsNull()) return str;
519
520   Handle(Interface_GeneralModule) module;
521   Standard_Integer CN;
522   if (!gtool->Select(ent,module,CN)) return str;
523
524   Interface_ShareTool sht (*this);
525   return module->Name (CN,ent,sht);
526 }
527
528 Standard_Boolean Interface_Graph::ModeStat() const
529 {
530   return (!thestats.IsNull());
531 }