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
6 // Lastly modified by :
7 // +---------------------------------------------------------------------------+
8 // ! pat ! Optimise IsConnected() ! 04/16/03! 4.0-2!
9 // +---------------------------------------------------------------------------+
12 #include <QANewModTopOpe.ixx>
14 #include <TopoDS_Iterator.hxx>
15 #include <BRepCheck_Analyzer.hxx>
16 #include <TopoDS_Shape.hxx>
17 #include <TopoDS_Shell.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>
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>
37 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS);
38 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS);
40 static TopoDS_Shape RemoveIntExtEdges(const TopoDS_Shape& TheS)
43 TopoDS_Shape aCopy = TheS;
44 BRepTools_Substitution aSubst;
45 TopTools_ListOfShape anEmptyList;
46 TopAbs_Orientation anOr;
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);
60 if(aSubst.IsCopied(aCopy)) {
61 aCopy = aSubst.Copy(aCopy).First();
67 Standard_Boolean QANewModTopOpe::IsValid(const TopoDS_Shape& TheS, const Standard_Boolean GeomControls)
70 TopExp_Explorer anExp, anExp1;
73 anExp.Init(TheS, TopAbs_SOLID);
74 for(; anExp.More(); anExp.Next()) {
76 aCopy = RemoveIntExtEdges(anExp.Current());
78 BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
80 if(anAnlz.IsValid()) continue;
81 else return Standard_False;
85 anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
86 for(; anExp.More(); anExp.Next()) {
88 aCopy = RemoveIntExtEdges(anExp.Current());
90 Handle(BRepCheck_Shell) aChkSh = new BRepCheck_Shell(TopoDS::Shell(aCopy));
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;
103 anExp1.Init(anExp.Current(), TopAbs_FACE);
104 for(; anExp1.More(); anExp1.Next()) {
105 if(IsValid(anExp1.Current())) continue;
106 else return Standard_False;
110 anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
111 for(; anExp.More(); anExp.Next()) {
113 aCopy = RemoveIntExtEdges(anExp.Current());
115 BRepCheck_Analyzer anAnlz(aCopy, GeomControls);
117 if(anAnlz.IsValid()) continue;
118 else return Standard_False;
122 anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
123 for(; anExp.More(); anExp.Next()) {
125 BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
127 Handle(BRepCheck_Result) aChkWr = anAnlz.Result(anExp.Current());
128 BRepCheck_ListIteratorOfListOfStatus anItl(aChkWr->Status());
129 for (;anItl.More(); anItl.Next()) {
131 if(anItl.Value() == BRepCheck_NoError ||
132 anItl.Value() == BRepCheck_BadOrientationOfSubshape) continue;
134 return Standard_False;
140 anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
141 for(; anExp.More(); anExp.Next()) {
143 BRepCheck_Analyzer anAnlz(anExp.Current(), GeomControls);
145 if(anAnlz.IsValid()) continue;
146 else return Standard_False;
150 return Standard_True;
153 Standard_Boolean QANewModTopOpe::IsManifold(const TopoDS_Shape& TheS)
156 Standard_Boolean aRes = Standard_False;
158 if(TheS.IsNull()) return aRes;
160 TopAbs_ShapeEnum aType = TheS.ShapeType();
164 case TopAbs_COMPOUND :
166 TopoDS_Iterator anIter(TheS);
167 if(!anIter.More()) return aRes;
168 const TopoDS_Shape& aS = anIter.Value();
170 if(anIter.More()) aRes = IsCompoundManifold(TopoDS::Compound(TheS));
171 else aRes = IsManifold(aS);
174 case TopAbs_COMPSOLID :
175 aRes = Standard_False;
179 aRes = NoInternalVertices(TheS);
184 aRes = NoInternalVertices(TheS);
185 if(aRes) aRes = CorrectOrientation(TopoDS::Shell(TheS));
190 aRes = NoInternalVertices(TheS);
195 aRes = NoInternalVertices(TheS);
199 aRes = NoInternalVertices(TheS);
202 aRes = Standard_True;
214 static Standard_Boolean NoInternalVertices(const TopoDS_Shape& TheS)
217 TopAbs_Orientation anOrnt;
218 TopExp_Explorer anExp(TheS, TopAbs_VERTEX);
219 for(; anExp.More(); anExp.Next()) {
221 anOrnt = anExp.Current().Orientation();
223 if(anOrnt == TopAbs_FORWARD) continue;
224 if(anOrnt == TopAbs_REVERSED) continue;
226 return Standard_False;
230 return Standard_True;
234 static Standard_Boolean CorrectOrientation(const TopoDS_Shell& TheS)
237 TopoDS_Iterator anIter(TheS);
239 if(!anIter.More()) return Standard_False; //Empty shell;
241 if(!anIter.More()) return Standard_True; // only one face
244 TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFace;
245 TopExp::MapShapesAndAncestors(TheS, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFace);
247 Standard_Integer i, nbEdgs = aMapEdgeFace.Extent();
248 TopExp_Explorer anExp;
249 TopAbs_Orientation anOrnt;
251 for(i = 1; i <= nbEdgs; i++) {
253 const TopTools_ListOfShape& aL = aMapEdgeFace(i);
255 if(aL.Extent() > 2) return Standard_False;
256 if(aL.Extent() == 1) continue;
258 const TopoDS_Shape& anE = aMapEdgeFace.FindKey(i);
260 anExp.Init(aL.First(), TopAbs_EDGE);
261 for(; anExp.More(); anExp.Next()) {
262 if(anE.IsSame(anExp.Current())) {
263 anOrnt = anExp.Current().Orientation();
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;
278 return Standard_True;
282 Standard_Boolean QANewModTopOpe::IsCompoundManifold(const TopoDS_Compound& TheS)
284 Standard_Boolean aRes = Standard_True;
286 TopExp_Explorer anExp;
288 anExp.Init(TheS, TopAbs_COMPSOLID);
291 aRes = Standard_False;
296 TopTools_ListOfShape aList;
297 TopExp_Explorer anExp1;
298 TopTools_DataMapOfShapeInteger aMap;
299 Standard_Integer n = 0, connect;
301 anExp.Init(TheS, TopAbs_SOLID);
302 for(; anExp.More(); anExp.Next()) {
303 aRes = IsManifold(anExp.Current());
304 if(!aRes) return aRes;
306 anExp1.Init(anExp.Current(), TopAbs_FACE);
307 for(; anExp1.More(); anExp1.Next()) {
308 if(aMap.IsBound(anExp1.Current())) {
309 connect = aMap(anExp1.Current());
311 aRes = Standard_False;
316 aMap.Bind(anExp1.Current(), n);
320 anExp1.Init(anExp.Current(), TopAbs_EDGE);
321 for(; anExp1.More(); anExp1.Next()) {
322 if(aMap.IsBound(anExp1.Current())) {
323 connect = aMap(anExp1.Current());
325 aRes = Standard_False;
330 aMap.Bind(anExp1.Current(), n);
334 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
335 for(; anExp1.More(); anExp1.Next()) {
336 if(aMap.IsBound(anExp1.Current())) {
337 connect = aMap(anExp1.Current());
339 aRes = Standard_False;
344 aMap.Bind(anExp1.Current(), n);
349 anExp.Init(TheS, TopAbs_SHELL, TopAbs_SOLID);
350 for(; anExp.More(); anExp.Next()) {
351 aRes = IsManifold(anExp.Current());
352 if(!aRes) return aRes;
354 anExp1.Init(anExp.Current(), TopAbs_FACE);
355 for(; anExp1.More(); anExp1.Next()) {
356 if(aMap.IsBound(anExp1.Current())) {
357 connect = aMap(anExp1.Current());
359 aRes = Standard_False;
364 aMap.Bind(anExp1.Current(), n);
368 anExp1.Init(anExp.Current(), TopAbs_EDGE);
369 for(; anExp1.More(); anExp1.Next()) {
370 if(aMap.IsBound(anExp1.Current())) {
371 connect = aMap(anExp1.Current());
373 aRes = Standard_False;
378 aMap.Bind(anExp1.Current(), n);
382 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
383 for(; anExp1.More(); anExp1.Next()) {
384 if(aMap.IsBound(anExp1.Current())) {
385 connect = aMap(anExp1.Current());
387 aRes = Standard_False;
392 aMap.Bind(anExp1.Current(), n);
397 anExp.Init(TheS, TopAbs_FACE, TopAbs_SHELL);
398 for(; anExp.More(); anExp.Next()) {
399 aRes = IsManifold(anExp.Current());
400 if(!aRes) return aRes;
403 anExp1.Init(anExp.Current(), TopAbs_EDGE);
404 for(; anExp1.More(); anExp1.Next()) {
405 if(aMap.IsBound(anExp1.Current())) {
406 connect = aMap(anExp1.Current());
408 aRes = Standard_False;
413 aMap.Bind(anExp1.Current(), n);
417 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
418 for(; anExp1.More(); anExp1.Next()) {
419 if(aMap.IsBound(anExp1.Current())) {
420 connect = aMap(anExp1.Current());
422 aRes = Standard_False;
427 aMap.Bind(anExp1.Current(), n);
432 anExp.Init(TheS, TopAbs_WIRE, TopAbs_FACE);
433 for(; anExp.More(); anExp.Next()) {
434 aRes = IsManifold(anExp.Current());
435 if(!aRes) return aRes;
438 anExp1.Init(anExp.Current(), TopAbs_EDGE);
439 for(; anExp1.More(); anExp1.Next()) {
440 if(aMap.IsBound(anExp1.Current())) {
441 connect = aMap(anExp1.Current());
443 aRes = Standard_False;
448 aMap.Bind(anExp1.Current(), n);
452 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
453 for(; anExp1.More(); anExp1.Next()) {
454 if(aMap.IsBound(anExp1.Current())) {
455 connect = aMap(anExp1.Current());
457 aRes = Standard_False;
462 aMap.Bind(anExp1.Current(), n);
467 anExp.Init(TheS, TopAbs_EDGE, TopAbs_WIRE);
468 for(; anExp.More(); anExp.Next()) {
469 aRes = IsManifold(anExp.Current());
470 if(!aRes) return aRes;
473 anExp1.Init(anExp.Current(), TopAbs_VERTEX);
474 for(; anExp1.More(); anExp1.Next()) {
475 if(aMap.IsBound(anExp1.Current())) {
476 connect = aMap(anExp1.Current());
478 aRes = Standard_False;
483 aMap.Bind(anExp1.Current(), n);
488 anExp.Init(TheS, TopAbs_VERTEX, TopAbs_EDGE);
489 for(; anExp.More(); anExp.Next()) {
492 if(aMap.IsBound(anExp.Current())) {
493 connect = aMap(anExp.Current());
495 aRes = Standard_False;
500 aMap.Bind(anExp.Current(), n);
508 TopAbs_ShapeEnum QANewModTopOpe::TypeOfShape(const TopoDS_Shape& TheS)
510 if(TheS.ShapeType() != TopAbs_COMPOUND) return TheS.ShapeType();
512 TopAbs_ShapeEnum aType = TopAbs_COMPOUND;
514 TopoDS_Iterator anIter(TheS);
516 if(!anIter.More()) return aType;
518 aType = TypeOfShape(anIter.Value());
520 if(aType == TopAbs_COMPOUND) return aType;
524 for(; anIter.More(); anIter.Next()) {
526 if(TypeOfShape(anIter.Value()) != aType) return TopAbs_COMPOUND;
535 Standard_Boolean QANewModTopOpe::IsConnected(const TopoDS_Shape& TheS)
537 cout << "QANewModTopOpe::IsConnected BEGIN" << endl;
538 Standard_Boolean aRes = Standard_True;
540 if(TheS.IsNull()) return aRes;
542 TopAbs_ShapeEnum aType = TheS.ShapeType();
544 if(aType != TopAbs_COMPOUND) return aRes;
546 TopTools_ListOfShape aCompList;
547 TopTools_DataMapOfShapeInteger aMap;
548 TopTools_MapOfShape aSMap;
549 TopoDS_Iterator anTDIter;
550 TopExp_Explorer anExp;
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());
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());
566 //cout << "QANewModTopOpe::IsConnected(2)" << endl;
569 Standard_Integer nbs = aSMap.Extent();
570 if(nbs <= 1) return aRes;
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;
577 TopTools_MapIteratorOfMapOfShape anMIter(aSMap);
578 Standard_Integer n = 1;
579 Standard_Integer connect;
580 const TopoDS_Shape& aFirstShape = anMIter.Key();
585 anExp.Init(aFirstShape, TopAbs_VERTEX);
586 for(; anExp.More(); anExp.Next()) {
587 aMap.Bind(anExp.Current(), n);
592 for(; anMIter.More(); anMIter.Next()) {
594 aMat[(n-1)*nbs+n-1] = 1;
597 const TopoDS_Shape& aShape = anMIter.Key();
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;
609 aMap.Bind(anExp.Current(), n);
613 //cout << "QANewModTopOpe::IsConnected(3)Lnbs=" <<nbs<< endl;
615 Standard_Integer k,i,ncount=0;
617 Standard_Boolean aNotChanged;
618 // math_Vector aRow(1, nbs), aCol(1, nbs);
620 // aRow = aMat.Row(1);
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.) {
628 // aRow = aMat.Row(1);
629 //aCol = aMat.Col(n);
631 for(i=1;i<=nbs;i++) {
633 // if(aMat(1,i) > 0. && aMat(i,n)> 0.) {
634 if(aMat[i-1] == 1 && aMat[(i-1)*nbs+n-1] == 1) {
638 // p+=aMat(1,i)*aMat(i,n);
645 aMat[(n-1)*nbs+1-1] = 1;
646 aNotChanged = Standard_False;
648 aRes = Standard_False;
651 if(aNotChanged) break;
656 // cout << "QANewModTopOpe::IsConnected END: aRes="<<aRes << ";ncount="<<ncount<<endl;
657 cout << "QANewModTopOpe::IsConnected END: aRes="<<aRes <<endl;
665 // Copyright SAMTECH ..........................................Version 3.0-00
666 // Lastly modified by : pat Date : 04/16/03
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 // +---------------------------------------------------------------------------+