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