1 // Created on: 2002-01-28
2 // Created by: Igor FEOKTISTOV
3 // Copyright (c) 2002-2012 OPEN CASCADE SAS
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.
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.
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.
20 #include <QANewModTopOpe.ixx>
22 #include <TopoDS_Iterator.hxx>
23 #include <BRepCheck_Analyzer.hxx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS_Shell.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>
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>
45 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS);
46 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS);
48 static TopoDS_Shape RemoveIntExtEdges(const TopoDS_Shape& TheS)
51 TopoDS_Shape aCopy = TheS;
52 BRepTools_Substitution aSubst;
53 TopTools_ListOfShape anEmptyList;
54 TopAbs_Orientation anOr;
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);
68 if(aSubst.IsCopied(aCopy)) {
69 aCopy = aSubst.Copy(aCopy).First();
75 Standard_Boolean QANewModTopOpe::IsValid(const TopoDS_Shape& TheS, const Standard_Boolean GeomControls)
78 TopExp_Explorer anExp, anExp1;
81 anExp.Init(TheS, TopAbs_SOLID);
82 for(; anExp.More(); anExp.Next()) {
84 aCopy = RemoveIntExtEdges(anExp.Current());
86 BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
88 if(anAnlz.IsValid()) continue;
89 else return Standard_False;
93 anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
94 for(; anExp.More(); anExp.Next()) {
96 aCopy = RemoveIntExtEdges(anExp.Current());
98 Handle(BRepCheck_Shell) aChkSh = new BRepCheck_Shell(TopoDS::Shell(aCopy));
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;
111 anExp1.Init(anExp.Current(), TopAbs_FACE);
112 for(; anExp1.More(); anExp1.Next()) {
113 if(IsValid(anExp1.Current())) continue;
114 else return Standard_False;
118 anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
119 for(; anExp.More(); anExp.Next()) {
121 aCopy = RemoveIntExtEdges(anExp.Current());
123 BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
125 if(anAnlz.IsValid()) continue;
126 else return Standard_False;
130 anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
131 for(; anExp.More(); anExp.Next()) {
133 BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
135 Handle(BRepCheck_Result) aChkWr = anAnlz.Result(anExp.Current());
136 BRepCheck_ListIteratorOfListOfStatus anItl(aChkWr->Status());
137 for (;anItl.More(); anItl.Next()) {
139 if(anItl.Value() == BRepCheck_NoError ||
140 anItl.Value() == BRepCheck_BadOrientationOfSubshape) continue;
142 return Standard_False;
148 anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
149 for(; anExp.More(); anExp.Next()) {
151 BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
153 if(anAnlz.IsValid()) continue;
154 else return Standard_False;
158 return Standard_True;
161 Standard_Boolean QANewModTopOpe::IsManifold(const TopoDS_Shape& TheS)
164 Standard_Boolean aRes = Standard_False;
166 if(TheS.IsNull()) return aRes;
168 TopAbs_ShapeEnum aType = TheS.ShapeType();
172 case TopAbs_COMPOUND :
174 TopoDS_Iterator anIter(TheS);
175 if(!anIter.More()) return aRes;
176 const TopoDS_Shape& aS = anIter.Value();
178 if(anIter.More()) aRes = IsCompoundManifold(TopoDS::Compound(TheS));
179 else aRes = IsManifold(aS);
182 case TopAbs_COMPSOLID :
183 aRes = Standard_False;
187 aRes = NoInternalVertices(TheS);
192 aRes = NoInternalVertices(TheS);
193 if(aRes) aRes = CorrectOrientation(TopoDS::Shell(TheS));
198 aRes = NoInternalVertices(TheS);
203 aRes = NoInternalVertices(TheS);
207 aRes = NoInternalVertices(TheS);
210 aRes = Standard_True;
222 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS)
225 TopAbs_Orientation anOrnt;
226 TopExp_Explorer anExp(TheS, TopAbs_VERTEX);
227 for(; anExp.More(); anExp.Next()) {
229 anOrnt = anExp.Current().Orientation();
231 if(anOrnt == TopAbs_FORWARD) continue;
232 if(anOrnt == TopAbs_REVERSED) continue;
234 return Standard_False;
238 return Standard_True;
242 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS)
245 TopoDS_Iterator anIter(TheS);
247 if(!anIter.More()) return Standard_False; //Empty shell;
249 if(!anIter.More()) return Standard_True; // only one face
252 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFace;
253 TopExp::MapShapesAndAncestors(TheS, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFace);
255 Standard_Integer i, nbEdgs = aMapEdgeFace.Extent();
256 TopExp_Explorer anExp;
257 TopAbs_Orientation anOrnt;
259 for(i = 1; i <= nbEdgs; i++) {
261 const TopTools_ListOfShape& aL = aMapEdgeFace(i);
263 if(aL.Extent() > 2) return Standard_False;
264 if(aL.Extent() == 1) continue;
266 const TopoDS_Shape& anE = aMapEdgeFace.FindKey(i);
268 anExp.Init(aL.First(), TopAbs_EDGE);
269 for(; anExp.More(); anExp.Next()) {
270 if(anE.IsSame(anExp.Current())) {
271 anOrnt = anExp.Current().Orientation();
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;
286 return Standard_True;
290 Standard_Boolean QANewModTopOpe::IsCompoundManifold(const TopoDS_Compound& TheS)
292 Standard_Boolean aRes = Standard_True;
294 TopExp_Explorer anExp;
296 anExp.Init(TheS, TopAbs_COMPSOLID);
299 aRes = Standard_False;
304 TopTools_ListOfShape aList;
305 TopExp_Explorer anExp1;
306 TopTools_DataMapOfShapeInteger aMap;
307 Standard_Integer n = 0, connect;
309 anExp.Init(TheS, TopAbs_SOLID);
310 for(; anExp.More(); anExp.Next()) {
311 aRes = IsManifold(anExp.Current());
312 if(!aRes) return aRes;
314 anExp1.Init(anExp.Current(), TopAbs_FACE);
315 for(; anExp1.More(); anExp1.Next()) {
316 if(aMap.IsBound(anExp1.Current())) {
317 connect = aMap(anExp1.Current());
319 aRes = Standard_False;
324 aMap.Bind(anExp1.Current(), n);
328 anExp1.Init(anExp.Current(), TopAbs_EDGE);
329 for(; anExp1.More(); anExp1.Next()) {
330 if(aMap.IsBound(anExp1.Current())) {
331 connect = aMap(anExp1.Current());
333 aRes = Standard_False;
338 aMap.Bind(anExp1.Current(), n);
342 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
343 for(; anExp1.More(); anExp1.Next()) {
344 if(aMap.IsBound(anExp1.Current())) {
345 connect = aMap(anExp1.Current());
347 aRes = Standard_False;
352 aMap.Bind(anExp1.Current(), n);
357 anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
358 for(; anExp.More(); anExp.Next()) {
359 aRes = IsManifold(anExp.Current());
360 if(!aRes) return aRes;
362 anExp1.Init(anExp.Current(), TopAbs_FACE);
363 for(; anExp1.More(); anExp1.Next()) {
364 if(aMap.IsBound(anExp1.Current())) {
365 connect = aMap(anExp1.Current());
367 aRes = Standard_False;
372 aMap.Bind(anExp1.Current(), n);
376 anExp1.Init(anExp.Current(), TopAbs_EDGE);
377 for(; anExp1.More(); anExp1.Next()) {
378 if(aMap.IsBound(anExp1.Current())) {
379 connect = aMap(anExp1.Current());
381 aRes = Standard_False;
386 aMap.Bind(anExp1.Current(), n);
390 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
391 for(; anExp1.More(); anExp1.Next()) {
392 if(aMap.IsBound(anExp1.Current())) {
393 connect = aMap(anExp1.Current());
395 aRes = Standard_False;
400 aMap.Bind(anExp1.Current(), n);
405 anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
406 for(; anExp.More(); anExp.Next()) {
407 aRes = IsManifold(anExp.Current());
408 if(!aRes) return aRes;
411 anExp1.Init(anExp.Current(), TopAbs_EDGE);
412 for(; anExp1.More(); anExp1.Next()) {
413 if(aMap.IsBound(anExp1.Current())) {
414 connect = aMap(anExp1.Current());
416 aRes = Standard_False;
421 aMap.Bind(anExp1.Current(), n);
425 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
426 for(; anExp1.More(); anExp1.Next()) {
427 if(aMap.IsBound(anExp1.Current())) {
428 connect = aMap(anExp1.Current());
430 aRes = Standard_False;
435 aMap.Bind(anExp1.Current(), n);
440 anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
441 for(; anExp.More(); anExp.Next()) {
442 aRes = IsManifold(anExp.Current());
443 if(!aRes) return aRes;
446 anExp1.Init(anExp.Current(), TopAbs_EDGE);
447 for(; anExp1.More(); anExp1.Next()) {
448 if(aMap.IsBound(anExp1.Current())) {
449 connect = aMap(anExp1.Current());
451 aRes = Standard_False;
456 aMap.Bind(anExp1.Current(), n);
460 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
461 for(; anExp1.More(); anExp1.Next()) {
462 if(aMap.IsBound(anExp1.Current())) {
463 connect = aMap(anExp1.Current());
465 aRes = Standard_False;
470 aMap.Bind(anExp1.Current(), n);
475 anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
476 for(; anExp.More(); anExp.Next()) {
477 aRes = IsManifold(anExp.Current());
478 if(!aRes) return aRes;
481 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
482 for(; anExp1.More(); anExp1.Next()) {
483 if(aMap.IsBound(anExp1.Current())) {
484 connect = aMap(anExp1.Current());
486 aRes = Standard_False;
491 aMap.Bind(anExp1.Current(), n);
496 anExp.Init(TheS, TopAbs_VERTEX, TopAbs_EDGE);
497 for(; anExp.More(); anExp.Next()) {
500 if(aMap.IsBound(anExp.Current())) {
501 connect = aMap(anExp.Current());
503 aRes = Standard_False;
508 aMap.Bind(anExp.Current(), n);
516 TopAbs_ShapeEnum QANewModTopOpe::TypeOfShape(const TopoDS_Shape& TheS)
518 if(TheS.ShapeType() != TopAbs_COMPOUND) return TheS.ShapeType();
520 TopAbs_ShapeEnum aType = TopAbs_COMPOUND;
522 TopoDS_Iterator anIter(TheS);
524 if(!anIter.More()) return aType;
526 aType = TypeOfShape(anIter.Value());
528 if(aType == TopAbs_COMPOUND) return aType;
532 for(; anIter.More(); anIter.Next()) {
534 if(TypeOfShape(anIter.Value()) != aType) return TopAbs_COMPOUND;
543 Standard_Boolean QANewModTopOpe::IsConnected(const TopoDS_Shape& TheS)
545 cout << "QANewModTopOpe::IsConnected BEGIN" << endl;
546 Standard_Boolean aRes = Standard_True;
548 if(TheS.IsNull()) return aRes;
550 TopAbs_ShapeEnum aType = TheS.ShapeType();
552 if(aType != TopAbs_COMPOUND) return aRes;
554 TopTools_ListOfShape aCompList;
555 TopTools_DataMapOfShapeInteger aMap;
556 TopTools_MapOfShape aSMap;
557 TopoDS_Iterator anTDIter;
558 TopExp_Explorer anExp;
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());
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());
574 //cout << "QANewModTopOpe::IsConnected(2)" << endl;
577 Standard_Integer nbs = aSMap.Extent();
578 if(nbs <= 1) return aRes;
580 math_Matrix aMat(1, nbs, 1, nbs, 0);
581 Standard_Integer aMax=nbs*nbs;
583 TopTools_MapIteratorOfMapOfShape anMIter(aSMap);
584 Standard_Integer n = 1;
585 Standard_Integer connect;
586 const TopoDS_Shape& aFirstShape = anMIter.Key();
590 anExp.Init(aFirstShape, TopAbs_VERTEX);
591 for(; anExp.More(); anExp.Next()) {
592 aMap.Bind(anExp.Current(), n);
597 for(; anMIter.More(); anMIter.Next()) {
601 const TopoDS_Shape& aShape = anMIter.Key();
603 anExp.Init(aShape, TopAbs_VERTEX);
604 for(; anExp.More(); anExp.Next()) {
605 if(aMap.IsBound(anExp.Current()))
607 connect = aMap(anExp.Current());
608 aMat(n, connect) = 1;
609 aMat(connect, n) = 1;
613 aMap.Bind(anExp.Current(), n);
617 //cout << "QANewModTopOpe::IsConnected(3)Lnbs=" <<nbs<< endl;
619 Standard_Integer k,i,ncount=0;
621 Standard_Boolean aNotChanged;
623 for (k = 1; k <= nbs; k++)
625 aRes = Standard_True;
626 aNotChanged = Standard_True;
627 for (n = 1; n <= nbs; n++)
632 for (i = 1; i <= nbs; i++)
634 if (aMat(1, i) == 1 && aMat(i, n) == 1)
644 aNotChanged = Standard_False;
646 aRes = Standard_False;
649 if(aNotChanged) break;
653 cout << "QANewModTopOpe::IsConnected END: aRes="<<aRes <<endl;