Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepCheck / BRepCheck_Shell.cxx
... / ...
CommitLineData
1// File: BRepCheck_Shell.cxx
2// Created: Tue Dec 12 17:49:08 1995
3// Author: Jacques GOUSSARD
4// <jag@bravox>
5
6
7#include <BRepCheck_Shell.ixx>
8
9#include <BRepCheck_ListOfStatus.hxx>
10#include <BRepCheck_ListIteratorOfListOfStatus.hxx>
11
12#include <TopTools_MapOfShape.hxx>
13#include <TopTools_MapIteratorOfMapOfShape.hxx>
14#include <TopTools_ListOfShape.hxx>
15#include <TopTools_ListIteratorOfListOfShape.hxx>
16#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
17#include <BRep_Tool.hxx>
18#include <BRep_Builder.hxx>
19
20#include <TopExp_Explorer.hxx>
21
22#include <BRepCheck.hxx>
23#include <TopoDS.hxx>
24#include <TopoDS_Edge.hxx>
25#include <TopoDS_Face.hxx>
26#include <TopExp.hxx>
27
28#include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
29#include <TopTools_DataMapOfShapeInteger.hxx>
30
31
32Standard_EXPORT Standard_Integer BRepCheck_Trace(const Standard_Integer phase) {
33 static int BRC_Trace = 0;
34 if (phase < 0) BRC_Trace =0;
35 else if (phase > 0) BRC_Trace=phase;
36 return BRC_Trace;
37}
38
39void PrintShape(const TopoDS_Shape& theShape, const Standard_Integer upper) {
40 if (!theShape.IsNull()) {
41 Standard_Integer code = theShape.HashCode(upper);
42
43 switch (theShape.ShapeType()) {
44 case TopAbs_COMPOUND :
45 cout << "COMPOUND";
46 break;
47 case TopAbs_COMPSOLID :
48 cout << "COMPSOLID";
49 break;
50 case TopAbs_SOLID :
51 cout << "SOLID";
52 break;
53 case TopAbs_SHELL :
54 cout << "SHELL";
55 break;
56 case TopAbs_FACE :
57 cout << "FACE";
58 break;
59 case TopAbs_WIRE :
60 cout << "WIRE";
61 break;
62 case TopAbs_EDGE :
63 cout << "EDGE";
64 break;
65 case TopAbs_VERTEX :
66 cout << "VERTEX";
67 break;
68 case TopAbs_SHAPE :
69 cout << "SHAPE";
70 break;
71 }
72 cout << " : " << code << " ";
73 switch (theShape.Orientation()) {
74 case TopAbs_FORWARD :
75 cout << "FORWARD";
76 break;
77 case TopAbs_REVERSED :
78 cout << "REVERSED";
79 break;
80 case TopAbs_INTERNAL :
81 cout << "INTERNAL";
82 break;
83 case TopAbs_EXTERNAL :
84 cout << "EXTERNAL";
85 break;
86 }
87 cout << endl;
88 }
89}
90
91static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape&,
92 const TopoDS_Shape&, // Face
93 TopTools_MapOfShape&); // mapofface
94
95
96#ifdef DEB
97static TopAbs_Orientation GetOrientation(const TopoDS_Face&,
98 const TopoDS_Shape&);
99#endif
100
101
102inline Standard_Boolean IsOriented(const TopoDS_Shape& S)
103{
104 return (S.Orientation() == TopAbs_FORWARD ||
105 S.Orientation() == TopAbs_REVERSED);
106}
107
108
109//=======================================================================
110//function : BRepCheck_Shell
111//purpose :
112//=======================================================================
113
114BRepCheck_Shell::BRepCheck_Shell(const TopoDS_Shell& S)
115{
116 Init(S);
117}
118
119
120//=======================================================================
121//function : Minimum
122//purpose :
123//=======================================================================
124
125void BRepCheck_Shell::Minimum()
126{
127 myCdone = Standard_False;
128 myOdone = Standard_False;
129
130 if (!myMin) {
131 BRepCheck_ListOfStatus thelist;
132 myMap.Bind(myShape, thelist);
133 BRepCheck_ListOfStatus& lst = myMap(myShape);
134
135 // it is checked if the shell is "connected"
136 TopExp_Explorer exp(myShape,TopAbs_FACE);
137 Standard_Integer nbface = 0;
138 myMapEF.Clear();
139 for (; exp.More(); exp.Next()) {
140 nbface++;
141 TopExp_Explorer expe;
142 for (expe.Init(exp.Current(),TopAbs_EDGE);
143 expe.More(); expe.Next()) {
144 const TopoDS_Shape& edg = expe.Current();
145 Standard_Integer index = myMapEF.FindIndex(edg);
146 if (index == 0) {
147 TopTools_ListOfShape thelist1;
148 index = myMapEF.Add(edg, thelist1);
149 }
150 myMapEF(index).Append(exp.Current());
151 }
152 }
153
154 if (nbface == 0) {
155 BRepCheck::Add(lst,BRepCheck_EmptyShell);
156 }
157 else if (nbface >= 2) {
158 TopTools_MapOfShape mapF;
159 exp.ReInit();
160 Propagate(myMapEF,exp.Current(),mapF);
161 if (mapF.Extent() != nbface) {
162 BRepCheck::Add(lst,BRepCheck_NotConnected);
163 }
164 }
165 if (lst.IsEmpty()) {
166 lst.Append(BRepCheck_NoError);
167 }
168 myMapEF.Clear();
169 myMin = Standard_True;
170 }
171}
172
173
174
175//=======================================================================
176//function : InContext
177//purpose :
178//=======================================================================
179
180void BRepCheck_Shell::InContext(const TopoDS_Shape& S)
181{
182
183 if (myMap.IsBound(S)) {
184 return;
185 }
186 BRepCheck_ListOfStatus thelist;
187 myMap.Bind(S, thelist);
188
189 BRepCheck_ListOfStatus& lst = myMap(S);
190
191// for (TopExp_Explorer exp(S,TopAbs_SHELL); exp.More(); exp.Next()) {
192 TopExp_Explorer exp(S,TopAbs_SHELL) ;
193 for ( ; exp.More(); exp.Next()) {
194 if (exp.Current().IsSame(myShape)) {
195 break;
196 }
197 }
198 if (!exp.More()) {
199 BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
200 return;
201 }
202
203 TopAbs_ShapeEnum styp = S.ShapeType();
204 switch (styp) {
205
206 case TopAbs_SOLID:
207 {
208 BRepCheck_Status fst = Closed();
209 if ((fst == BRepCheck_NotClosed && S.Closed()) ||
210 (fst != BRepCheck_NoError)) {
211 BRepCheck::Add(lst,fst);
212 }
213 else if (!IsUnorientable()) {
214 fst = Orientation();
215 BRepCheck::Add(lst,fst);
216 }
217 }
218 break;
219
220 default:
221 break;
222 }
223
224
225 if (lst.IsEmpty()) {
226 lst.Append(BRepCheck_NoError);
227 }
228}
229
230
231//=======================================================================
232//function : Blind
233//purpose :
234//=======================================================================
235
236void BRepCheck_Shell::Blind()
237{
238 if (!myBlind) {
239 // nothing more than in the minimum
240 myBlind = Standard_True;
241 }
242}
243
244
245//=======================================================================
246//function : Closed
247//purpose :
248//=======================================================================
249
250BRepCheck_Status BRepCheck_Shell::Closed(const Standard_Boolean Update)
251{
252
253 if (myCdone) {
254 if (Update) {
255 BRepCheck::Add(myMap(myShape), myCstat);
256 }
257 return myCstat;
258 }
259
260 myCdone = Standard_True; // it will be done...
261
262 BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
263 if (itl.Value() != BRepCheck_NoError) {
264 myCstat = itl.Value();
265 return myCstat; // already saved
266 }
267
268 myCstat = BRepCheck_NoError;
269 //
270 Standard_Integer index, aNbF;
271 TopExp_Explorer exp, ede;
272 TopTools_MapOfShape mapS, aMEToAvoid;
273 myMapEF.Clear();
274
275
276 // Checks if the oriented faces of the shell give a "closed" shell,
277 // i-e if each oriented edge on oriented faces is found 2 times.
278 //
279 //modified by NIZNHY-PKV Mon Jun 4 13:59:21 2007f
280 exp.Init(myShape,TopAbs_FACE);
281 for (; exp.More(); exp.Next()) {
282 const TopoDS_Shape& aF=exp.Current();
283 if (IsOriented(aF)) {
284 ede.Init(exp.Current(),TopAbs_EDGE);
285 for (; ede.More(); ede.Next()) {
286 const TopoDS_Shape& aE=ede.Current();
287 if (!IsOriented(aE)) {
288 aMEToAvoid.Add(aE);
289 }
290 }
291 }
292 }
293 //modified by NIZNHY-PKV Mon Jun 4 13:59:23 2007t
294 //
295 exp.Init(myShape,TopAbs_FACE);
296 for (; exp.More(); exp.Next()) {
297 const TopoDS_Shape& aF=exp.Current();
298 if (IsOriented(aF)) {
299 if (!mapS.Add(aF)) {
300 myCstat = BRepCheck_RedundantFace;
301 if (Update) {
302 BRepCheck::Add(myMap(myShape),myCstat);
303 }
304 return myCstat;
305 }
306 //
307 ede.Init(exp.Current(),TopAbs_EDGE);
308 for (; ede.More(); ede.Next()) {
309 const TopoDS_Shape& aE=ede.Current();
310 //modified by NIZNHY-PKV Mon Jun 4 14:07:57 2007f
311 //if (IsOriented(aE)) {
312 if (!aMEToAvoid.Contains(aE)) {
313 //modified by NIZNHY-PKV Mon Jun 4 14:08:01 2007
314 index = myMapEF.FindIndex(aE);
315 if (!index) {
316 TopTools_ListOfShape thelist;
317 index = myMapEF.Add(aE, thelist);
318 }
319 myMapEF(index).Append(aF);
320 }
321 }
322 }
323 }
324 //
325 myNbori = mapS.Extent();
326 if (myNbori >= 2) {
327 mapS.Clear();
328 // Search for the first oriented face
329 TopoDS_Shape aF;
330 exp.Init(myShape, TopAbs_FACE);
331 for (;exp.More(); exp.Next()) {
332 aF=exp.Current();
333 if (IsOriented(aF)) {
334 break;
335 }
336 }
337 //
338 Propagate(myMapEF, aF, mapS);
339 }
340 //
341 //
342 aNbF=mapS.Extent();
343 if (myNbori != aNbF) {
344 myCstat = BRepCheck_NotConnected;
345 if (Update) {
346 BRepCheck::Add(myMap(myShape),myCstat);
347 }
348 return myCstat;
349 }
350 //
351 //
352 Standard_Integer i, Nbedges, nboc, nbSet;
353 //
354 Nbedges = myMapEF.Extent();
355 for (i = 1; i<=Nbedges; ++i) {
356 nboc = myMapEF(i).Extent();
357 if (nboc == 0 || nboc >= 3) {
358 TopTools_ListOfShape theSet;
359 nbSet=NbConnectedSet(theSet);
360 // If there is more than one closed cavity the shell is considered invalid
361 // this corresponds to the criteria of a solid (not those of a shell)
362 if (nbSet>1) {
363 myCstat = BRepCheck_InvalidMultiConnexity;
364 if (Update) {
365 BRepCheck::Add(myMap(myShape),myCstat);
366 }
367 return myCstat;
368 }
369 }
370 else if (nboc == 1) {
371 if (!BRep_Tool::Degenerated(TopoDS::Edge(myMapEF.FindKey(i)))) {
372 myCstat=BRepCheck_NotClosed;
373 if (Update) {
374 BRepCheck::Add(myMap(myShape),myCstat);
375 }
376 return myCstat;
377 }
378 }
379 }
380
381 if (Update) {
382 BRepCheck::Add(myMap(myShape),myCstat);
383 }
384 return myCstat;
385}
386
387
388//=======================================================================
389//function : Orientation
390//purpose :
391//=======================================================================
392
393BRepCheck_Status BRepCheck_Shell::Orientation(const Standard_Boolean Update)
394{
395 if (myOdone) {
396 if (Update) {
397 BRepCheck::Add(myMap(myShape), myOstat);
398 }
399 return myOstat;
400 }
401 myOdone = Standard_True;
402
403 myOstat = Closed();
404 if (myOstat != BRepCheck_NotClosed && myOstat != BRepCheck_NoError) {
405 if (Update) {
406 BRepCheck::Add(myMap(myShape), myOstat);
407 }
408 return myOstat;
409 }
410
411 myOstat = BRepCheck_NoError;
412
413
414// First the orientation of each face in relation to the shell is found.
415// It is used to check BRepCheck_RedundantFace
416
417 TopTools_DataMapOfShapeInteger MapOfShapeOrientation;
418 TopExp_Explorer exp,ede;
419
420 for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
421 if (!MapOfShapeOrientation.Bind(exp.Current(), (Standard_Integer)(exp.Current().Orientation()))) {
422 myOstat = BRepCheck_RedundantFace;
423 if (Update) {
424 BRepCheck::Add(myMap(myShape), myOstat);
425 }
426 else {
427 return myOstat;
428 }
429 }
430 }
431
432#ifdef DEB
433 if (BRepCheck_Trace(0) > 1) {
434 TopTools_DataMapIteratorOfDataMapOfShapeInteger itt(MapOfShapeOrientation);
435 Standard_Integer upper = MapOfShapeOrientation.NbBuckets();
436 Standard_Integer code = 0;
437 cout << "La map shape Orientation :" << endl;
438 for (; itt.More(); itt.Next()) {
439 PrintShape(itt.Key(), upper);
440 }
441 cout << endl;
442 }
443#endif
444
445
446// Then the orientation of faces by their connectivity is checked
447// BRepCheck_BadOrientationOfSubshape and
448// BRepCheck_SubshapeNotInShape are checked;
449
450 Standard_Integer Nbedges = myMapEF.Extent();
451 TopoDS_Face Fref;
452 TopAbs_Orientation orf;
453
454 for (Standard_Integer i = 1; i<= Nbedges; i++) {
455
456 const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(i));
457 if (BRep_Tool::Degenerated(edg)) continue;
458 TopTools_ListOfShape& lface = myMapEF(i);
459 TopTools_ListIteratorOfListOfShape lite(lface);
460
461 if (lface.Extent() <= 2)
462 {
463 lite.Initialize(lface);
464 Fref = TopoDS::Face(lite.Value());
465
466 if (!MapOfShapeOrientation.IsBound(Fref)) {
467 myOstat = BRepCheck_SubshapeNotInShape;
468 if (Update) {
469 BRepCheck::Add(myMap(myShape), myOstat);
470 }
471 // quit because no workaround for the incoherence is possible
472 return myOstat;
473 }
474 lite.Next();
475
476 if (lite.More()) { // Edge of connectivity
477 //JR/Hp :
478 Standard_Integer iorf = MapOfShapeOrientation.Find(Fref);
479 orf = (TopAbs_Orientation) iorf;
480 //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref);
481 Fref.Orientation(orf);
482
483 // edge is examined
484 if (!lite.Value().IsSame(Fref)) { // edge non "closed"
485 for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) {
486 if (ede.Current().IsSame(edg)) {
487 break;
488 }
489 }
490 TopAbs_Orientation orient = ede.Current().Orientation();
491 TopoDS_Face Fcur= TopoDS::Face(lite.Value());
492
493 if (!MapOfShapeOrientation.IsBound(Fcur)) {
494 myOstat = BRepCheck_SubshapeNotInShape;
495 if (Update) {
496 BRepCheck::Add(myMap(myShape), myOstat);
497 }
498 // quit because no workaround for the incoherence is possible
499 return myOstat;
500 }
501
502 //JR/Hp :
503 Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur) ;
504 orf = (TopAbs_Orientation) iorf ;
505 // orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
506 Fcur.Orientation(orf);
507
508 for (ede.Init(Fcur, TopAbs_EDGE); ede.More(); ede.Next()) {
509 if (ede.Current().IsSame(edg)) {
510 break;
511 }
512 }
513 if (ede.Current().Orientation() == orient) {
514 // The loop is continued on the edges as many times
515 // as the same edge is present in the wire
516
517 // modified by NIZHNY-MKK Tue Sep 30 11:11:42 2003
518 Standard_Boolean bfound = Standard_False;
519 ede.Next();
520 for (; ede.More(); ede.Next()) {
521 if (ede.Current().IsSame(edg)) {
522 // modified by NIZHNY-MKK Tue Sep 30 11:12:03 2003
523 bfound = Standard_True;
524 break;
525 }
526 }
527 // if (ede.Current().Orientation() == orient) {
528 // modified by NIZHNY-MKK Thu Oct 2 17:56:47 2003
529 if (!bfound || (ede.Current().Orientation() == orient)) {
530 myOstat = BRepCheck_BadOrientationOfSubshape;
531 if (Update) {
532 BRepCheck::Add(myMap(myShape), myOstat);
533 break;
534 }
535 return myOstat;
536 }
537 }
538 }
539 }
540 }
541 else //more than two faces
542 {
543 Standard_Integer numF = 0, numR = 0;
544 TopTools_MapOfShape Fmap;
545
546 for (lite.Initialize(lface); lite.More(); lite.Next())
547 {
548 TopoDS_Face Fcur= TopoDS::Face(lite.Value());
549 if (!MapOfShapeOrientation.IsBound(Fcur))
550 {
551 myOstat = BRepCheck_SubshapeNotInShape;
552 if (Update)
553 BRepCheck::Add(myMap(myShape), myOstat);
554 // quit because no workaround for the incoherence is possible
555 return myOstat;
556 }
557
558 Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur);
559 orf = (TopAbs_Orientation) iorf;
560 //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
561 Fcur.Orientation(orf);
562
563 for (ede.Init(Fcur,TopAbs_EDGE); ede.More(); ede.Next())
564 if (ede.Current().IsSame(edg))
565 break;
566 if (Fmap.Contains(Fcur)) //edge is "closed" on Fcur, we meet Fcur twice
567 {
568 ede.Next();
569 for (; ede.More(); ede.Next())
570 if (ede.Current().IsSame(edg))
571 break;
572 }
573 TopAbs_Orientation orient = ede.Current().Orientation();
574 if (orient == TopAbs_FORWARD)
575 numF++;
576 else
577 numR++;
578
579 Fmap.Add(Fcur);
580 }
581
582 if (numF != numR)
583 {
584 myOstat = BRepCheck_BadOrientationOfSubshape;
585 if (Update)
586 {
587 BRepCheck::Add(myMap(myShape), myOstat);
588 break;
589 }
590 return myOstat;
591 }
592 }
593 }
594
595// If at least one incorrectly oriented face has been found, it is checked if the shell can be oriented.
596// i.e. : if by modification of the orientation of a face it is possible to find
597// a coherent orientation. (it is not possible on a Moebius band)
598// BRepCheck_UnorientableShape is checked
599
600 if (myOstat == BRepCheck_BadOrientationOfSubshape) {
601 if (!Fref.IsNull()) {
602 if (Nbedges > 0) {
603 TopTools_MapOfShape alre;
604 TopTools_ListOfShape voisin;
605 voisin.Append(Fref);
606 alre.Clear();
607 while (!voisin.IsEmpty()) {
608 Fref=TopoDS::Face(voisin.First());
609 voisin.RemoveFirst();
610 if (!MapOfShapeOrientation.IsBound(Fref)) {
611 myOstat = BRepCheck_SubshapeNotInShape;
612 if (Update) {
613 BRepCheck::Add(myMap(myShape), myOstat);
614 }
615 // quit because no workaround for the incoherence is possible
616 return myOstat;
617 }
618//JR/Hp :
619 Standard_Integer iorf = MapOfShapeOrientation.Find(Fref) ;
620 orf = (TopAbs_Orientation) iorf ;
621// orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref);
622 Fref.Orientation(orf);
623
624#ifdef DEB
625 if (BRepCheck_Trace(0) > 3) {
626 cout << "Fref : " ;
627 PrintShape(Fref, MapOfShapeOrientation.NbBuckets());
628 }
629#endif
630
631 TopExp_Explorer edFcur;
632 alre.Add(Fref);
633
634 for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) {
635 const TopoDS_Edge& edg = TopoDS::Edge(ede.Current());
636 TopAbs_Orientation orient = edg.Orientation();
637 TopTools_ListOfShape& lface = myMapEF.ChangeFromKey(edg);
638 TopTools_ListIteratorOfListOfShape lite(lface);
639
640 TopoDS_Face Fcur= TopoDS::Face(lite.Value());
641 if (Fcur.IsSame(Fref)) {
642 lite.Next();
643 if (lite.More()) {
644 Fcur=TopoDS::Face(lite.Value());
645 }
646 else {
647 // from the free border one goes to the next edge
648 continue;
649 }
650 }
651
652 if (!MapOfShapeOrientation.IsBound(Fcur)) {
653 myOstat = BRepCheck_SubshapeNotInShape;
654 if (Update) {
655 BRepCheck::Add(myMap(myShape), myOstat);
656 }
657 // quit because no workaround for the incoherence is possible
658 return myOstat;
659 }
660
661//JR/Hp :
662 Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur) ;
663 orf = (TopAbs_Orientation) iorf ;
664// orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
665 Fcur.Orientation(orf);
666
667#ifdef DEB
668 if (BRepCheck_Trace(0) > 3) {
669 cout << " Fcur : " ;
670 PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
671 }
672#endif
673 for (edFcur.Init(Fcur, TopAbs_EDGE); edFcur.More(); edFcur.Next()) {
674 if (edFcur.Current().IsSame(edg)) {
675 break;
676 }
677 }
678 if (edFcur.Current().Orientation() == orient) {
679 if (alre.Contains(Fcur)) {
680 // It is necessary to return a face that has been already examined or returned
681 // if one gets nowhere, the shell cannot be oriented.
682 myOstat = BRepCheck_UnorientableShape;
683 if (Update) {
684 BRepCheck::Add(myMap(myShape), myOstat);
685 }
686 // quit, otherwise there is a risk of taking too much time.
687#ifdef DEB
688 if (BRepCheck_Trace(0) > 3) {
689 orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
690 Fcur.Orientation(orf);
691 cout << " Error : this face has been already examined " << endl;
692 cout << " Imposible to return it ";
693 PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
694 }
695#endif
696 return myOstat;
697 }
698 orf = TopAbs::Reverse(orf);
699 MapOfShapeOrientation(Fcur)=orf;
700
701
702#ifdef DEB
703 if (BRepCheck_Trace(0) > 3) {
704 orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
705 Fcur.Orientation(orf);
706 cout << " Resulting Fcur is returned : " ;
707 PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
708 }
709#endif
710
711 }
712 if (alre.Add(Fcur)) {
713 voisin.Append(Fcur);
714 }
715 }
716 }
717 }
718 }
719 }
720
721 if (Update) {
722 BRepCheck::Add(myMap(myShape), myOstat);
723 }
724 return myOstat;
725}
726
727//=======================================================================
728//function : SetUnorientable
729//purpose :
730//=======================================================================
731
732void BRepCheck_Shell::SetUnorientable()
733{
734 BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
735}
736
737
738//=======================================================================
739//function : IsUnorientable
740//purpose :
741//=======================================================================
742
743Standard_Boolean BRepCheck_Shell::IsUnorientable() const
744{
745 if (myOdone) {
746 return (myOstat != BRepCheck_NoError);
747 }
748 for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
749 itl.More();
750 itl.Next()) {
751 if (itl.Value() == BRepCheck_UnorientableShape) {
752 return Standard_True;
753 }
754 }
755 return Standard_False;
756}
757
758//=======================================================================
759//function : NbConnectedSet
760//purpose :
761//=======================================================================
762
763Standard_Integer BRepCheck_Shell::NbConnectedSet(TopTools_ListOfShape& theSets)
764{
765 // The connections are found
766 TopTools_IndexedDataMapOfShapeListOfShape parents;
767 TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, parents);
768 // All faces are taken
769 TopTools_MapOfShape theFaces;
770 TopExp_Explorer exsh(myShape, TopAbs_FACE);
771 for (; exsh.More(); exsh.Next()) theFaces.Add(exsh.Current());
772 // The edges that are not oriented or have more than 2 connections are missing
773 Standard_Integer iCur;
774 TopTools_MapOfShape theMultiEd;
775 TopTools_MapOfShape theUnOriEd;
776 for (iCur=1; iCur<=parents.Extent(); iCur++) {
777 const TopoDS_Edge& Ed = TopoDS::Edge(parents.FindKey(iCur));
778 if (parents(iCur).Extent()> 2) theMultiEd.Add(Ed);
779 if (Ed.Orientation()!=TopAbs_REVERSED &&
780 Ed.Orientation()!=TopAbs_FORWARD) theUnOriEd.Add(Ed);
781 }
782 // Starting from multiconnected edges propagation by simple connections
783 TopTools_ListIteratorOfListOfShape lconx1, lconx2;
784 TopTools_MapIteratorOfMapOfShape itmsh(theMultiEd);
785 TopoDS_Shell CurShell;
786 TopoDS_Shape adFac;
787 TopTools_ListOfShape lesCur;
788 BRep_Builder BRB;
789 Standard_Boolean newCur=Standard_True;
790 BRB.MakeShell(CurShell);
791 for (; itmsh.More(); itmsh.Next()) {
792 const TopoDS_Shape& Ed = itmsh.Key();
793 if (!theUnOriEd.Contains(Ed)) {
794 for (lconx1.Initialize(parents.FindFromKey(Ed)); lconx1.More(); lconx1.Next()) {
795 if (theFaces.Contains(lconx1.Value())) {
796 adFac=lconx1.Value();
797 BRB.Add(CurShell, adFac);
798 theFaces.Remove(adFac);
799 newCur=Standard_False;
800 if (theFaces.IsEmpty()) break;
801 lesCur.Append(adFac);
802 while (!lesCur.IsEmpty()) {
803 adFac=lesCur.First();
804 lesCur.RemoveFirst();
805 for (exsh.Init(adFac, TopAbs_EDGE); exsh.More(); exsh.Next()) {
806 const TopoDS_Shape& ced = exsh.Current();
807 if (!theMultiEd.Contains(ced)) {
808 for (lconx2.Initialize(parents.FindFromKey(ced)); lconx2.More(); lconx2.Next()) {
809 if (theFaces.Contains(lconx2.Value())) {
810 adFac=lconx2.Value();
811 BRB.Add(CurShell, adFac);
812 theFaces.Remove(adFac);
813 newCur=Standard_False;
814 if (theFaces.IsEmpty()) break;
815 lesCur.Append(adFac);
816 }
817 }
818 }
819 if (theFaces.IsEmpty()) break;
820 }
821 }
822 if (!newCur) {
823 theSets.Append(CurShell);
824 CurShell.Nullify();
825 newCur=Standard_True;
826 BRB.MakeShell(CurShell);
827 }
828 }
829 if (theFaces.IsEmpty()) break;
830 }
831 }
832 if (theFaces.IsEmpty()) break;
833 }
834 return theSets.Extent();
835}
836
837//=======================================================================
838//function : GetOrientation
839//purpose :
840//=======================================================================
841
842#ifdef DEB
843static TopAbs_Orientation GetOrientation(const TopoDS_Face& F,
844 const TopoDS_Shape& S)
845
846{
847 TopExp_Explorer exp;
848 for (exp.Init(S,TopAbs_FACE); exp.More(); exp.Next()) {
849 if (exp.Current().IsSame(F)) {
850 return exp.Current().Orientation();
851 }
852 }
853 return TopAbs_FORWARD; // for compilation
854}
855#endif
856
857
858//=======================================================================
859//function : Propagate
860//purpose :
861//=======================================================================
862
863static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape& mapEF,
864 const TopoDS_Shape& fac,
865 TopTools_MapOfShape& mapF)
866{
867 if (mapF.Contains(fac)) {
868 return;
869 }
870 mapF.Add(fac); // attention, if oriented == Standard_True, fac should
871 // be FORWARD or REVERSED. It is not checked.
872
873 TopExp_Explorer ex;
874 for (ex.Init(fac,TopAbs_EDGE); ex.More(); ex.Next()) {
875 const TopoDS_Edge& edg = TopoDS::Edge(ex.Current());
876// test if the edge is in the map (only orienteed edges are present)
877 if (mapEF.Contains(edg)) {
878 for (TopTools_ListIteratorOfListOfShape itl(mapEF.FindFromKey(edg));
879 itl.More(); itl.Next()) {
880 if (!itl.Value().IsSame(fac) &&
881 !mapF.Contains(itl.Value())) {
882 Propagate(mapEF,itl.Value(),mapF);
883 }
884 }
885 }
886 }
887}