0022904: Clean up sccsid variables
[occt.git] / src / QANewModTopOpe / QANewModTopOpe.cxx
1 // File:        QANewModTopOpe.cxx
2 // Created:     Mon Jan  28 14:24:19 2002
3 // Author:      Igor FEOKTISTOV <ifv@nnov.matra-dtv.fr>
4 // Copyright:    SAMTECH S.A. 2002
5
6 // Lastly modified by :
7 // +---------------------------------------------------------------------------+
8 // !       pat ! Optimise IsConnected()                  !  04/16/03!    4.0-2!
9 // +---------------------------------------------------------------------------+
10
11
12 #include <QANewModTopOpe.ixx>
13 #include <TopAbs.hxx>
14 #include <TopoDS_Iterator.hxx>
15 #include <BRepCheck_Analyzer.hxx>
16 #include <TopoDS_Shape.hxx>
17 #include <TopoDS_Shell.hxx>
18 #include <TopoDS.hxx>
19 #include <TopExp_Explorer.hxx>
20 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
21 #include <TopTools_ListOfShape.hxx>
22 #include <TopoDS_Edge.hxx>
23 #include <TopoDS_Face.hxx>
24 #include <TopExp.hxx>
25 #include <TopTools_DataMapOfShapeInteger.hxx>
26 #include <math_Matrix.hxx>
27 #include <TopTools_ListIteratorOfListOfShape.hxx>
28 #include <BRepTools_Substitution.hxx>
29 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
30 #include <BRepCheck_Result.hxx>
31 #include <BRepCheck.hxx>
32 #include <BRepCheck_Shell.hxx>
33 #include <BRepCheck_Wire.hxx>
34 #include <TopTools_MapIteratorOfMapOfShape.hxx>
35 #include <TopTools_MapOfShape.hxx>
36
37 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS);
38 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS);
39
40 static TopoDS_Shape RemoveIntExtEdges(const TopoDS_Shape& TheS) 
41 {
42
43   TopoDS_Shape aCopy = TheS;
44   BRepTools_Substitution aSubst;
45   TopTools_ListOfShape anEmptyList;
46   TopAbs_Orientation anOr;
47
48   TopExp_Explorer anExp(aCopy, TopAbs_EDGE);
49   for(; anExp.More(); anExp.Next()) {
50     anOr = anExp.Current().Orientation();
51     if(anOr == TopAbs_INTERNAL || anOr == TopAbs_EXTERNAL) {
52       if(!aSubst.IsCopied(anExp.Current())) {
53         aSubst.Substitute(anExp.Current(), anEmptyList);
54       }
55     }
56   }
57
58   aSubst.Build(aCopy);
59
60   if(aSubst.IsCopied(aCopy)) {
61     aCopy = aSubst.Copy(aCopy).First();
62   }
63
64   return aCopy;
65 }
66
67 Standard_Boolean QANewModTopOpe::IsValid(const TopoDS_Shape& TheS, const Standard_Boolean GeomControls)
68 {
69
70   TopExp_Explorer anExp, anExp1;  
71   TopoDS_Shape aCopy;
72
73   anExp.Init(TheS, TopAbs_SOLID);
74   for(; anExp.More(); anExp.Next()) {
75
76     aCopy = RemoveIntExtEdges(anExp.Current());
77
78     BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
79
80     if(anAnlz.IsValid()) continue;
81     else return Standard_False;
82
83   }
84
85   anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
86   for(; anExp.More(); anExp.Next()) {
87
88     aCopy = RemoveIntExtEdges(anExp.Current());
89
90     Handle(BRepCheck_Shell) aChkSh = new BRepCheck_Shell(TopoDS::Shell(aCopy));
91     aChkSh->Minimum();
92     aChkSh->Closed(Standard_True);
93     aChkSh->Orientation(Standard_True);
94     BRepCheck_ListIteratorOfListOfStatus anItl(aChkSh->Status());
95     for (;anItl.More(); anItl.Next()) {
96       if((anItl.Value() == BRepCheck_NoError) ||
97          (anItl.Value() == BRepCheck_InvalidMultiConnexity) ||
98          (anItl.Value() == BRepCheck_NotClosed) ||
99          (anItl.Value() == BRepCheck_BadOrientationOfSubshape)) continue;
100       return Standard_False;
101     }
102
103     anExp1.Init(anExp.Current(), TopAbs_FACE);
104     for(; anExp1.More(); anExp1.Next()) {
105       if(IsValid(anExp1.Current())) continue;
106       else return Standard_False;
107     }
108   }
109
110   anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
111   for(; anExp.More(); anExp.Next()) {
112
113     aCopy = RemoveIntExtEdges(anExp.Current());
114
115     BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
116
117     if(anAnlz.IsValid()) continue;
118     else return Standard_False;
119
120   }
121
122   anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
123   for(; anExp.More(); anExp.Next()) {
124
125     BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
126
127     Handle(BRepCheck_Result) aChkWr = anAnlz.Result(anExp.Current());
128     BRepCheck_ListIteratorOfListOfStatus anItl(aChkWr->Status());
129     for (;anItl.More(); anItl.Next()) {
130
131       if(anItl.Value() == BRepCheck_NoError || 
132          anItl.Value() == BRepCheck_BadOrientationOfSubshape) continue;
133
134       return Standard_False;
135
136     }
137
138   }
139
140   anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
141   for(; anExp.More(); anExp.Next()) {
142
143     BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
144
145     if(anAnlz.IsValid()) continue;
146     else return Standard_False;
147
148   }
149
150   return Standard_True;
151 }
152
153 Standard_Boolean QANewModTopOpe::IsManifold(const TopoDS_Shape& TheS)
154 {
155
156   Standard_Boolean aRes = Standard_False;
157
158   if(TheS.IsNull()) return aRes;
159
160   TopAbs_ShapeEnum aType = TheS.ShapeType();
161   
162   switch (aType) {
163
164   case TopAbs_COMPOUND :
165     {
166       TopoDS_Iterator anIter(TheS);
167       if(!anIter.More()) return aRes;
168       const TopoDS_Shape& aS = anIter.Value();
169       anIter.Next();
170       if(anIter.More()) aRes = IsCompoundManifold(TopoDS::Compound(TheS));
171       else aRes = IsManifold(aS);
172     }
173     break;
174   case TopAbs_COMPSOLID :
175     aRes = Standard_False;
176     break;
177   case TopAbs_SOLID :
178     {
179       aRes = NoInternalVertices(TheS);
180     }
181     break;
182   case TopAbs_SHELL :
183     {
184       aRes = NoInternalVertices(TheS);
185       if(aRes) aRes = CorrectOrientation(TopoDS::Shell(TheS));
186     }
187     break;
188   case TopAbs_FACE :
189     {
190       aRes = NoInternalVertices(TheS);
191     }
192     break;
193   case TopAbs_WIRE :
194     {
195       aRes = NoInternalVertices(TheS);
196     }
197     break;
198   case TopAbs_EDGE :
199     aRes = NoInternalVertices(TheS);
200     break;
201   case TopAbs_VERTEX :
202     aRes = Standard_True;
203     break;
204   case TopAbs_SHAPE :
205   default :
206     ;
207   }
208       
209
210   return aRes;
211
212 }
213
214 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS)
215 {
216
217   TopAbs_Orientation anOrnt;
218   TopExp_Explorer anExp(TheS, TopAbs_VERTEX);
219   for(; anExp.More(); anExp.Next()) {
220
221     anOrnt = anExp.Current().Orientation();
222
223     if(anOrnt == TopAbs_FORWARD) continue; 
224     if(anOrnt == TopAbs_REVERSED) continue;
225
226     return Standard_False;
227
228   }
229     
230   return Standard_True;
231
232 }
233
234 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS)
235 {
236
237   TopoDS_Iterator anIter(TheS);
238
239   if(!anIter.More()) return Standard_False; //Empty shell;
240   anIter.Next();
241   if(!anIter.More()) return Standard_True; // only one face
242
243
244   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFace;
245   TopExp::MapShapesAndAncestors(TheS, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFace);
246
247   Standard_Integer i, nbEdgs = aMapEdgeFace.Extent();
248   TopExp_Explorer anExp;
249   TopAbs_Orientation anOrnt;
250
251   for(i = 1; i <= nbEdgs; i++) {
252
253     const TopTools_ListOfShape& aL = aMapEdgeFace(i);
254
255     if(aL.Extent() > 2) return Standard_False;
256     if(aL.Extent() == 1) continue;
257
258     const TopoDS_Shape& anE = aMapEdgeFace.FindKey(i);
259     
260     anExp.Init(aL.First(), TopAbs_EDGE);
261     for(; anExp.More(); anExp.Next()) {
262       if(anE.IsSame(anExp.Current())) {
263         anOrnt = anExp.Current().Orientation();
264         break;
265       }
266     }
267
268     anExp.Init(aL.Last(), TopAbs_EDGE);
269     for(; anExp.More(); anExp.Next()) {
270       if(anE.IsSame(anExp.Current())) {
271         if(anOrnt == anExp.Current().Orientation()) return Standard_False;
272         break;
273       }
274     }
275
276   }
277     
278   return Standard_True;
279
280 }
281
282 Standard_Boolean QANewModTopOpe::IsCompoundManifold(const TopoDS_Compound& TheS)
283 {
284   Standard_Boolean aRes = Standard_True;
285
286   TopExp_Explorer anExp;
287
288   anExp.Init(TheS, TopAbs_COMPSOLID);
289   if(anExp.More()) {
290
291     aRes = Standard_False;
292     return aRes;
293
294   }
295
296   TopTools_ListOfShape aList;
297   TopExp_Explorer anExp1;
298   TopTools_DataMapOfShapeInteger aMap;
299   Standard_Integer n = 0, connect;
300
301   anExp.Init(TheS, TopAbs_SOLID);
302   for(; anExp.More(); anExp.Next()) {
303     aRes = IsManifold(anExp.Current());
304     if(!aRes) return aRes;
305     ++n;
306     anExp1.Init(anExp.Current(), TopAbs_FACE);
307     for(; anExp1.More(); anExp1.Next()) {
308       if(aMap.IsBound(anExp1.Current())) {
309         connect = aMap(anExp1.Current());
310         if(n != connect) {
311           aRes = Standard_False;
312           return aRes;
313         }
314       }
315       else {
316         aMap.Bind(anExp1.Current(), n);
317       }
318     }
319
320     anExp1.Init(anExp.Current(), TopAbs_EDGE);
321     for(; anExp1.More(); anExp1.Next()) {
322       if(aMap.IsBound(anExp1.Current())) {
323         connect = aMap(anExp1.Current());
324         if(n != connect) {
325           aRes = Standard_False;
326           return aRes;
327         }
328       }
329       else {
330         aMap.Bind(anExp1.Current(), n);
331       }
332     }
333
334     anExp1.Init(anExp.Current(), TopAbs_VERTEX);
335     for(; anExp1.More(); anExp1.Next()) {
336       if(aMap.IsBound(anExp1.Current())) {
337         connect = aMap(anExp1.Current());
338         if(n != connect) {
339           aRes = Standard_False;
340           return aRes;
341         }
342       }
343       else {
344         aMap.Bind(anExp1.Current(), n);
345       }
346     }
347   }
348
349   anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
350   for(; anExp.More(); anExp.Next()) {
351     aRes = IsManifold(anExp.Current());
352     if(!aRes) return aRes;
353     ++n;
354     anExp1.Init(anExp.Current(), TopAbs_FACE);
355     for(; anExp1.More(); anExp1.Next()) {
356       if(aMap.IsBound(anExp1.Current())) {
357         connect = aMap(anExp1.Current());
358         if(n != connect) {
359           aRes = Standard_False;
360           return aRes;
361         }
362       }
363       else {
364         aMap.Bind(anExp1.Current(), n);
365       }
366     }
367
368     anExp1.Init(anExp.Current(), TopAbs_EDGE);
369     for(; anExp1.More(); anExp1.Next()) {
370       if(aMap.IsBound(anExp1.Current())) {
371         connect = aMap(anExp1.Current());
372         if(n != connect) {
373           aRes = Standard_False;
374           return aRes;
375         }
376       }
377       else {
378         aMap.Bind(anExp1.Current(), n);
379       }
380     }
381
382     anExp1.Init(anExp.Current(), TopAbs_VERTEX);
383     for(; anExp1.More(); anExp1.Next()) {
384       if(aMap.IsBound(anExp1.Current())) {
385         connect = aMap(anExp1.Current());
386         if(n != connect) {
387           aRes = Standard_False;
388           return aRes;
389         }
390       }
391       else {
392         aMap.Bind(anExp1.Current(), n);
393       }
394     }
395   }
396
397   anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
398   for(; anExp.More(); anExp.Next()) {
399     aRes = IsManifold(anExp.Current());
400     if(!aRes) return aRes;
401     ++n;
402
403     anExp1.Init(anExp.Current(), TopAbs_EDGE);
404     for(; anExp1.More(); anExp1.Next()) {
405       if(aMap.IsBound(anExp1.Current())) {
406         connect = aMap(anExp1.Current());
407         if(n != connect) {
408           aRes = Standard_False;
409           return aRes;
410         }
411       }
412       else {
413         aMap.Bind(anExp1.Current(), n);
414       }
415     }
416
417     anExp1.Init(anExp.Current(), TopAbs_VERTEX);
418     for(; anExp1.More(); anExp1.Next()) {
419       if(aMap.IsBound(anExp1.Current())) {
420         connect = aMap(anExp1.Current());
421         if(n != connect) {
422           aRes = Standard_False;
423           return aRes;
424         }
425       }
426       else {
427         aMap.Bind(anExp1.Current(), n);
428       }
429     }
430   }
431
432   anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
433   for(; anExp.More(); anExp.Next()) {
434     aRes = IsManifold(anExp.Current());
435     if(!aRes) return aRes;
436     ++n;
437
438     anExp1.Init(anExp.Current(), TopAbs_EDGE);
439     for(; anExp1.More(); anExp1.Next()) {
440       if(aMap.IsBound(anExp1.Current())) {
441         connect = aMap(anExp1.Current());
442         if(n != connect) {
443           aRes = Standard_False;
444           return aRes;
445         }
446       }
447       else {
448         aMap.Bind(anExp1.Current(), n);
449       }
450     }
451
452     anExp1.Init(anExp.Current(), TopAbs_VERTEX);
453     for(; anExp1.More(); anExp1.Next()) {
454       if(aMap.IsBound(anExp1.Current())) {
455         connect = aMap(anExp1.Current());
456         if(n != connect) {
457           aRes = Standard_False;
458           return aRes;
459         }
460       }
461       else {
462         aMap.Bind(anExp1.Current(), n);
463       }
464     }
465   }
466
467   anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
468   for(; anExp.More(); anExp.Next()) {
469     aRes = IsManifold(anExp.Current());
470     if(!aRes) return aRes;
471     ++n;
472
473     anExp1.Init(anExp.Current(), TopAbs_VERTEX);
474     for(; anExp1.More(); anExp1.Next()) {
475       if(aMap.IsBound(anExp1.Current())) {
476         connect = aMap(anExp1.Current());
477         if(n != connect) {
478           aRes = Standard_False;
479           return aRes;
480         }
481       }
482       else {
483         aMap.Bind(anExp1.Current(), n);
484       }
485     }
486   }
487
488   anExp.Init(TheS, TopAbs_VERTEX, TopAbs_EDGE);
489   for(; anExp.More(); anExp.Next()) {
490     ++n;
491
492     if(aMap.IsBound(anExp.Current())) {
493       connect = aMap(anExp.Current());
494       if(n != connect) {
495         aRes = Standard_False;
496         return aRes;
497       }
498     }
499     else {
500       aMap.Bind(anExp.Current(), n);
501     }
502   }
503
504   return aRes;
505 }
506
507
508 TopAbs_ShapeEnum  QANewModTopOpe::TypeOfShape(const TopoDS_Shape& TheS)
509 {
510   if(TheS.ShapeType() != TopAbs_COMPOUND) return TheS.ShapeType();
511
512   TopAbs_ShapeEnum aType = TopAbs_COMPOUND;
513
514   TopoDS_Iterator anIter(TheS);
515
516   if(!anIter.More()) return aType;
517
518   aType = TypeOfShape(anIter.Value());
519
520   if(aType == TopAbs_COMPOUND) return aType;
521
522   anIter.Next();
523
524   for(; anIter.More(); anIter.Next()) {
525
526     if(TypeOfShape(anIter.Value()) != aType) return TopAbs_COMPOUND;
527
528   }
529
530   return aType;
531   
532 }
533
534
535 Standard_Boolean QANewModTopOpe::IsConnected(const TopoDS_Shape& TheS)
536 {
537   cout << "QANewModTopOpe::IsConnected BEGIN" << endl;
538   Standard_Boolean aRes = Standard_True;
539
540   if(TheS.IsNull()) return aRes;
541
542   TopAbs_ShapeEnum aType = TheS.ShapeType();
543
544   if(aType != TopAbs_COMPOUND) return aRes;
545       
546   TopTools_ListOfShape aCompList;
547   TopTools_DataMapOfShapeInteger aMap;
548   TopTools_MapOfShape aSMap;
549   TopoDS_Iterator anTDIter;
550   TopExp_Explorer anExp;
551
552   anTDIter.Initialize(TheS);
553   for(; anTDIter.More(); anTDIter.Next()) {
554     if(anTDIter.Value().ShapeType() == TopAbs_COMPOUND) aCompList.Append(anTDIter.Value());
555     else aSMap.Add(anTDIter.Value());
556   }
557
558   TopTools_ListIteratorOfListOfShape anIter(aCompList);
559   for(;anIter.More(); anIter.Next()) {
560     anTDIter.Initialize(anIter.Value());
561     for(; anTDIter.More(); anTDIter.Next()) {
562       if(anTDIter.Value().ShapeType() == TopAbs_COMPOUND) aCompList.Append(anTDIter.Value());
563       else aSMap.Add(anTDIter.Value());
564     }
565   }
566   //cout << "QANewModTopOpe::IsConnected(2)" << endl;
567    
568
569   Standard_Integer nbs = aSMap.Extent();
570   if(nbs <= 1) return aRes;
571
572   //  math_Matrix aMat(1, nbs, 1, nbs, 0.0);
573   int *aMat = new int[nbs*nbs];
574   Standard_Integer aMax=nbs*nbs;
575   for(Standard_Integer kk=0;kk<aMax;kk++) aMat[kk]=0;
576
577   TopTools_MapIteratorOfMapOfShape anMIter(aSMap);
578   Standard_Integer n = 1;
579   Standard_Integer connect;
580   const TopoDS_Shape& aFirstShape = anMIter.Key();
581
582   //  aMat(n,n) = 1.;
583   aMat[0] = 1;
584
585   anExp.Init(aFirstShape, TopAbs_VERTEX);
586   for(; anExp.More(); anExp.Next()) {
587     aMap.Bind(anExp.Current(), n);
588   }
589
590   anMIter.Next();
591
592   for(; anMIter.More(); anMIter.Next()) {
593     ++n;
594     aMat[(n-1)*nbs+n-1] = 1;
595     // aMat(n,n) = 1.;
596
597     const TopoDS_Shape& aShape = anMIter.Key();
598
599     anExp.Init(aShape, TopAbs_VERTEX);
600     for(; anExp.More(); anExp.Next()) {
601       if(aMap.IsBound(anExp.Current())) {
602         connect = aMap(anExp.Current());
603         //aMat(n, connect) = 1.;
604         //aMat(connect, n) = 1.;
605         aMat[(n-1)*nbs+connect-1] = 1;
606         aMat[(connect-1)*nbs+n-1] = 1;
607       }
608       else {
609         aMap.Bind(anExp.Current(), n);
610       }
611     }
612   }
613   //cout << "QANewModTopOpe::IsConnected(3)Lnbs=" <<nbs<< endl;
614
615   Standard_Integer k,i,ncount=0;
616   Standard_Real p; 
617   Standard_Boolean aNotChanged;
618   // math_Vector aRow(1, nbs), aCol(1, nbs);
619
620   //    aRow = aMat.Row(1);
621
622   for(k = 1; k <= nbs; k++) {
623     aRes = Standard_True;
624     aNotChanged = Standard_True;
625     for(n = 1; n <= nbs; n++) {
626       //      if(aMat(1, n) < 1.) {
627       if(aMat[n-1] == 0) {
628         //      aRow = aMat.Row(1);
629         //aCol = aMat.Col(n);
630         p=0.;
631         for(i=1;i<=nbs;i++) {
632           //ncount++;
633           //      if(aMat(1,i) > 0. && aMat(i,n)> 0.) {
634           if(aMat[i-1] == 1 && aMat[(i-1)*nbs+n-1] == 1) {
635             p=1.;
636             break;
637           }
638           //      p+=aMat(1,i)*aMat(i,n);
639         }
640         //p = aRow*aCol;
641         if(p > 0.0) {
642           //      aMat(1, n) = 1.0;
643           //      aMat(n, 1) = 1.0;
644           aMat[n-1] = 1;
645           aMat[(n-1)*nbs+1-1] = 1;
646           aNotChanged = Standard_False;
647         }
648         aRes = Standard_False;
649       }
650     }
651     if(aNotChanged) break;
652     if(aRes) break;
653   }
654   delete aMat;
655
656   //  cout << "QANewModTopOpe::IsConnected END: aRes="<<aRes   << ";ncount="<<ncount<<endl;
657   cout << "QANewModTopOpe::IsConnected END: aRes="<<aRes <<endl;
658   return aRes;
659
660 }
661
662
663 // @@SDM: begin
664
665 // Copyright SAMTECH ..........................................Version    3.0-00
666 // Lastly modified by : pat                                    Date :   04/16/03
667
668 // File history synopsis (creation,modification,correction)
669 // +---------------------------------------------------------------------------+
670 // ! Developer !              Comments                   !   Date   ! Version  !
671 // +-----------!-----------------------------------------!----------!----------+
672 // !       ifv ! Creation                                !28-01-2002! 3.0-00-1!
673 // !      ivan ! print de trace                          !  01/21/03!    4.0-1!
674 // !       pat ! Optimise IsConnected()                  !  04/16/03!    4.0-2!
675 // +---------------------------------------------------------------------------+
676
677 // @@SDM: end