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