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