7fd59977 |
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 | |
32 | Standard_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 | |
39 | void 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 | |
91 | static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape&, |
92 | const TopoDS_Shape&, // Face |
93 | TopTools_MapOfShape&); // mapofface |
94 | |
95 | |
96 | #ifdef DEB |
97 | static TopAbs_Orientation GetOrientation(const TopoDS_Face&, |
98 | const TopoDS_Shape&); |
99 | #endif |
100 | |
101 | |
102 | inline 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 | |
114 | BRepCheck_Shell::BRepCheck_Shell(const TopoDS_Shell& S) |
115 | { |
116 | Init(S); |
117 | } |
118 | |
119 | |
120 | //======================================================================= |
121 | //function : Minimum |
122 | //purpose : |
123 | //======================================================================= |
124 | |
125 | void 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 | |
180 | void 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 | |
236 | void 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 | |
250 | BRepCheck_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 | |
393 | BRepCheck_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(); |
7fd59977 |
436 | cout << "La map shape Orientation :" << endl; |
437 | for (; itt.More(); itt.Next()) { |
438 | PrintShape(itt.Key(), upper); |
439 | } |
440 | cout << endl; |
441 | } |
442 | #endif |
443 | |
444 | |
445 | // Then the orientation of faces by their connectivity is checked |
446 | // BRepCheck_BadOrientationOfSubshape and |
447 | // BRepCheck_SubshapeNotInShape are checked; |
448 | |
449 | Standard_Integer Nbedges = myMapEF.Extent(); |
450 | TopoDS_Face Fref; |
451 | TopAbs_Orientation orf; |
452 | |
453 | for (Standard_Integer i = 1; i<= Nbedges; i++) { |
454 | |
455 | const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(i)); |
456 | if (BRep_Tool::Degenerated(edg)) continue; |
457 | TopTools_ListOfShape& lface = myMapEF(i); |
458 | TopTools_ListIteratorOfListOfShape lite(lface); |
459 | |
460 | if (lface.Extent() <= 2) |
461 | { |
462 | lite.Initialize(lface); |
463 | Fref = TopoDS::Face(lite.Value()); |
464 | |
465 | if (!MapOfShapeOrientation.IsBound(Fref)) { |
466 | myOstat = BRepCheck_SubshapeNotInShape; |
467 | if (Update) { |
468 | BRepCheck::Add(myMap(myShape), myOstat); |
469 | } |
470 | // quit because no workaround for the incoherence is possible |
471 | return myOstat; |
472 | } |
473 | lite.Next(); |
474 | |
475 | if (lite.More()) { // Edge of connectivity |
476 | //JR/Hp : |
477 | Standard_Integer iorf = MapOfShapeOrientation.Find(Fref); |
478 | orf = (TopAbs_Orientation) iorf; |
479 | //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref); |
480 | Fref.Orientation(orf); |
481 | |
482 | // edge is examined |
483 | if (!lite.Value().IsSame(Fref)) { // edge non "closed" |
484 | for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) { |
485 | if (ede.Current().IsSame(edg)) { |
486 | break; |
487 | } |
488 | } |
489 | TopAbs_Orientation orient = ede.Current().Orientation(); |
490 | TopoDS_Face Fcur= TopoDS::Face(lite.Value()); |
491 | |
492 | if (!MapOfShapeOrientation.IsBound(Fcur)) { |
493 | myOstat = BRepCheck_SubshapeNotInShape; |
494 | if (Update) { |
495 | BRepCheck::Add(myMap(myShape), myOstat); |
496 | } |
497 | // quit because no workaround for the incoherence is possible |
498 | return myOstat; |
499 | } |
500 | |
501 | //JR/Hp : |
502 | Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur) ; |
503 | orf = (TopAbs_Orientation) iorf ; |
504 | // orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur); |
505 | Fcur.Orientation(orf); |
506 | |
507 | for (ede.Init(Fcur, TopAbs_EDGE); ede.More(); ede.Next()) { |
508 | if (ede.Current().IsSame(edg)) { |
509 | break; |
510 | } |
511 | } |
512 | if (ede.Current().Orientation() == orient) { |
513 | // The loop is continued on the edges as many times |
514 | // as the same edge is present in the wire |
515 | |
516 | // modified by NIZHNY-MKK Tue Sep 30 11:11:42 2003 |
517 | Standard_Boolean bfound = Standard_False; |
518 | ede.Next(); |
519 | for (; ede.More(); ede.Next()) { |
520 | if (ede.Current().IsSame(edg)) { |
521 | // modified by NIZHNY-MKK Tue Sep 30 11:12:03 2003 |
522 | bfound = Standard_True; |
523 | break; |
524 | } |
525 | } |
526 | // if (ede.Current().Orientation() == orient) { |
527 | // modified by NIZHNY-MKK Thu Oct 2 17:56:47 2003 |
528 | if (!bfound || (ede.Current().Orientation() == orient)) { |
529 | myOstat = BRepCheck_BadOrientationOfSubshape; |
530 | if (Update) { |
531 | BRepCheck::Add(myMap(myShape), myOstat); |
532 | break; |
533 | } |
534 | return myOstat; |
535 | } |
536 | } |
537 | } |
538 | } |
539 | } |
540 | else //more than two faces |
541 | { |
542 | Standard_Integer numF = 0, numR = 0; |
543 | TopTools_MapOfShape Fmap; |
544 | |
545 | for (lite.Initialize(lface); lite.More(); lite.Next()) |
546 | { |
547 | TopoDS_Face Fcur= TopoDS::Face(lite.Value()); |
548 | if (!MapOfShapeOrientation.IsBound(Fcur)) |
549 | { |
550 | myOstat = BRepCheck_SubshapeNotInShape; |
551 | if (Update) |
552 | BRepCheck::Add(myMap(myShape), myOstat); |
553 | // quit because no workaround for the incoherence is possible |
554 | return myOstat; |
555 | } |
556 | |
557 | Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur); |
558 | orf = (TopAbs_Orientation) iorf; |
559 | //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur); |
560 | Fcur.Orientation(orf); |
561 | |
562 | for (ede.Init(Fcur,TopAbs_EDGE); ede.More(); ede.Next()) |
563 | if (ede.Current().IsSame(edg)) |
564 | break; |
565 | if (Fmap.Contains(Fcur)) //edge is "closed" on Fcur, we meet Fcur twice |
566 | { |
567 | ede.Next(); |
568 | for (; ede.More(); ede.Next()) |
569 | if (ede.Current().IsSame(edg)) |
570 | break; |
571 | } |
572 | TopAbs_Orientation orient = ede.Current().Orientation(); |
573 | if (orient == TopAbs_FORWARD) |
574 | numF++; |
575 | else |
576 | numR++; |
577 | |
578 | Fmap.Add(Fcur); |
579 | } |
580 | |
581 | if (numF != numR) |
582 | { |
583 | myOstat = BRepCheck_BadOrientationOfSubshape; |
584 | if (Update) |
585 | { |
586 | BRepCheck::Add(myMap(myShape), myOstat); |
587 | break; |
588 | } |
589 | return myOstat; |
590 | } |
591 | } |
592 | } |
593 | |
594 | // If at least one incorrectly oriented face has been found, it is checked if the shell can be oriented. |
595 | // i.e. : if by modification of the orientation of a face it is possible to find |
596 | // a coherent orientation. (it is not possible on a Moebius band) |
597 | // BRepCheck_UnorientableShape is checked |
598 | |
599 | if (myOstat == BRepCheck_BadOrientationOfSubshape) { |
600 | if (!Fref.IsNull()) { |
601 | if (Nbedges > 0) { |
602 | TopTools_MapOfShape alre; |
603 | TopTools_ListOfShape voisin; |
604 | voisin.Append(Fref); |
605 | alre.Clear(); |
606 | while (!voisin.IsEmpty()) { |
607 | Fref=TopoDS::Face(voisin.First()); |
608 | voisin.RemoveFirst(); |
609 | if (!MapOfShapeOrientation.IsBound(Fref)) { |
610 | myOstat = BRepCheck_SubshapeNotInShape; |
611 | if (Update) { |
612 | BRepCheck::Add(myMap(myShape), myOstat); |
613 | } |
614 | // quit because no workaround for the incoherence is possible |
615 | return myOstat; |
616 | } |
617 | //JR/Hp : |
618 | Standard_Integer iorf = MapOfShapeOrientation.Find(Fref) ; |
619 | orf = (TopAbs_Orientation) iorf ; |
620 | // orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref); |
621 | Fref.Orientation(orf); |
622 | |
623 | #ifdef DEB |
624 | if (BRepCheck_Trace(0) > 3) { |
625 | cout << "Fref : " ; |
626 | PrintShape(Fref, MapOfShapeOrientation.NbBuckets()); |
627 | } |
628 | #endif |
629 | |
630 | TopExp_Explorer edFcur; |
631 | alre.Add(Fref); |
632 | |
633 | for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) { |
634 | const TopoDS_Edge& edg = TopoDS::Edge(ede.Current()); |
635 | TopAbs_Orientation orient = edg.Orientation(); |
636 | TopTools_ListOfShape& lface = myMapEF.ChangeFromKey(edg); |
637 | TopTools_ListIteratorOfListOfShape lite(lface); |
638 | |
639 | TopoDS_Face Fcur= TopoDS::Face(lite.Value()); |
640 | if (Fcur.IsSame(Fref)) { |
641 | lite.Next(); |
642 | if (lite.More()) { |
643 | Fcur=TopoDS::Face(lite.Value()); |
644 | } |
645 | else { |
646 | // from the free border one goes to the next edge |
647 | continue; |
648 | } |
649 | } |
650 | |
651 | if (!MapOfShapeOrientation.IsBound(Fcur)) { |
652 | myOstat = BRepCheck_SubshapeNotInShape; |
653 | if (Update) { |
654 | BRepCheck::Add(myMap(myShape), myOstat); |
655 | } |
656 | // quit because no workaround for the incoherence is possible |
657 | return myOstat; |
658 | } |
659 | |
660 | //JR/Hp : |
661 | Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur) ; |
662 | orf = (TopAbs_Orientation) iorf ; |
663 | // orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur); |
664 | Fcur.Orientation(orf); |
665 | |
666 | #ifdef DEB |
667 | if (BRepCheck_Trace(0) > 3) { |
668 | cout << " Fcur : " ; |
669 | PrintShape(Fcur, MapOfShapeOrientation.NbBuckets()); |
670 | } |
671 | #endif |
672 | for (edFcur.Init(Fcur, TopAbs_EDGE); edFcur.More(); edFcur.Next()) { |
673 | if (edFcur.Current().IsSame(edg)) { |
674 | break; |
675 | } |
676 | } |
677 | if (edFcur.Current().Orientation() == orient) { |
678 | if (alre.Contains(Fcur)) { |
679 | // It is necessary to return a face that has been already examined or returned |
680 | // if one gets nowhere, the shell cannot be oriented. |
681 | myOstat = BRepCheck_UnorientableShape; |
682 | if (Update) { |
683 | BRepCheck::Add(myMap(myShape), myOstat); |
684 | } |
685 | // quit, otherwise there is a risk of taking too much time. |
686 | #ifdef DEB |
687 | if (BRepCheck_Trace(0) > 3) { |
688 | orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur); |
689 | Fcur.Orientation(orf); |
690 | cout << " Error : this face has been already examined " << endl; |
691 | cout << " Imposible to return it "; |
692 | PrintShape(Fcur, MapOfShapeOrientation.NbBuckets()); |
693 | } |
694 | #endif |
695 | return myOstat; |
696 | } |
697 | orf = TopAbs::Reverse(orf); |
698 | MapOfShapeOrientation(Fcur)=orf; |
699 | |
700 | |
701 | #ifdef DEB |
702 | if (BRepCheck_Trace(0) > 3) { |
703 | orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur); |
704 | Fcur.Orientation(orf); |
705 | cout << " Resulting Fcur is returned : " ; |
706 | PrintShape(Fcur, MapOfShapeOrientation.NbBuckets()); |
707 | } |
708 | #endif |
709 | |
710 | } |
711 | if (alre.Add(Fcur)) { |
712 | voisin.Append(Fcur); |
713 | } |
714 | } |
715 | } |
716 | } |
717 | } |
718 | } |
719 | |
720 | if (Update) { |
721 | BRepCheck::Add(myMap(myShape), myOstat); |
722 | } |
723 | return myOstat; |
724 | } |
725 | |
726 | //======================================================================= |
727 | //function : SetUnorientable |
728 | //purpose : |
729 | //======================================================================= |
730 | |
731 | void BRepCheck_Shell::SetUnorientable() |
732 | { |
733 | BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape); |
734 | } |
735 | |
736 | |
737 | //======================================================================= |
738 | //function : IsUnorientable |
739 | //purpose : |
740 | //======================================================================= |
741 | |
742 | Standard_Boolean BRepCheck_Shell::IsUnorientable() const |
743 | { |
744 | if (myOdone) { |
745 | return (myOstat != BRepCheck_NoError); |
746 | } |
747 | for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape)); |
748 | itl.More(); |
749 | itl.Next()) { |
750 | if (itl.Value() == BRepCheck_UnorientableShape) { |
751 | return Standard_True; |
752 | } |
753 | } |
754 | return Standard_False; |
755 | } |
756 | |
757 | //======================================================================= |
758 | //function : NbConnectedSet |
759 | //purpose : |
760 | //======================================================================= |
761 | |
762 | Standard_Integer BRepCheck_Shell::NbConnectedSet(TopTools_ListOfShape& theSets) |
763 | { |
764 | // The connections are found |
765 | TopTools_IndexedDataMapOfShapeListOfShape parents; |
766 | TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, parents); |
767 | // All faces are taken |
768 | TopTools_MapOfShape theFaces; |
769 | TopExp_Explorer exsh(myShape, TopAbs_FACE); |
770 | for (; exsh.More(); exsh.Next()) theFaces.Add(exsh.Current()); |
771 | // The edges that are not oriented or have more than 2 connections are missing |
772 | Standard_Integer iCur; |
773 | TopTools_MapOfShape theMultiEd; |
774 | TopTools_MapOfShape theUnOriEd; |
775 | for (iCur=1; iCur<=parents.Extent(); iCur++) { |
776 | const TopoDS_Edge& Ed = TopoDS::Edge(parents.FindKey(iCur)); |
777 | if (parents(iCur).Extent()> 2) theMultiEd.Add(Ed); |
778 | if (Ed.Orientation()!=TopAbs_REVERSED && |
779 | Ed.Orientation()!=TopAbs_FORWARD) theUnOriEd.Add(Ed); |
780 | } |
781 | // Starting from multiconnected edges propagation by simple connections |
782 | TopTools_ListIteratorOfListOfShape lconx1, lconx2; |
783 | TopTools_MapIteratorOfMapOfShape itmsh(theMultiEd); |
784 | TopoDS_Shell CurShell; |
785 | TopoDS_Shape adFac; |
786 | TopTools_ListOfShape lesCur; |
787 | BRep_Builder BRB; |
788 | Standard_Boolean newCur=Standard_True; |
789 | BRB.MakeShell(CurShell); |
790 | for (; itmsh.More(); itmsh.Next()) { |
791 | const TopoDS_Shape& Ed = itmsh.Key(); |
792 | if (!theUnOriEd.Contains(Ed)) { |
793 | for (lconx1.Initialize(parents.FindFromKey(Ed)); lconx1.More(); lconx1.Next()) { |
794 | if (theFaces.Contains(lconx1.Value())) { |
795 | adFac=lconx1.Value(); |
796 | BRB.Add(CurShell, adFac); |
797 | theFaces.Remove(adFac); |
798 | newCur=Standard_False; |
799 | if (theFaces.IsEmpty()) break; |
800 | lesCur.Append(adFac); |
801 | while (!lesCur.IsEmpty()) { |
802 | adFac=lesCur.First(); |
803 | lesCur.RemoveFirst(); |
804 | for (exsh.Init(adFac, TopAbs_EDGE); exsh.More(); exsh.Next()) { |
805 | const TopoDS_Shape& ced = exsh.Current(); |
806 | if (!theMultiEd.Contains(ced)) { |
807 | for (lconx2.Initialize(parents.FindFromKey(ced)); lconx2.More(); lconx2.Next()) { |
808 | if (theFaces.Contains(lconx2.Value())) { |
809 | adFac=lconx2.Value(); |
810 | BRB.Add(CurShell, adFac); |
811 | theFaces.Remove(adFac); |
812 | newCur=Standard_False; |
813 | if (theFaces.IsEmpty()) break; |
814 | lesCur.Append(adFac); |
815 | } |
816 | } |
817 | } |
818 | if (theFaces.IsEmpty()) break; |
819 | } |
820 | } |
821 | if (!newCur) { |
822 | theSets.Append(CurShell); |
823 | CurShell.Nullify(); |
824 | newCur=Standard_True; |
825 | BRB.MakeShell(CurShell); |
826 | } |
827 | } |
828 | if (theFaces.IsEmpty()) break; |
829 | } |
830 | } |
831 | if (theFaces.IsEmpty()) break; |
832 | } |
833 | return theSets.Extent(); |
834 | } |
835 | |
836 | //======================================================================= |
837 | //function : GetOrientation |
838 | //purpose : |
839 | //======================================================================= |
840 | |
841 | #ifdef DEB |
842 | static TopAbs_Orientation GetOrientation(const TopoDS_Face& F, |
843 | const TopoDS_Shape& S) |
844 | |
845 | { |
846 | TopExp_Explorer exp; |
847 | for (exp.Init(S,TopAbs_FACE); exp.More(); exp.Next()) { |
848 | if (exp.Current().IsSame(F)) { |
849 | return exp.Current().Orientation(); |
850 | } |
851 | } |
852 | return TopAbs_FORWARD; // for compilation |
853 | } |
854 | #endif |
855 | |
856 | |
857 | //======================================================================= |
858 | //function : Propagate |
859 | //purpose : |
860 | //======================================================================= |
861 | |
862 | static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape& mapEF, |
863 | const TopoDS_Shape& fac, |
864 | TopTools_MapOfShape& mapF) |
865 | { |
866 | if (mapF.Contains(fac)) { |
867 | return; |
868 | } |
869 | mapF.Add(fac); // attention, if oriented == Standard_True, fac should |
870 | // be FORWARD or REVERSED. It is not checked. |
871 | |
872 | TopExp_Explorer ex; |
873 | for (ex.Init(fac,TopAbs_EDGE); ex.More(); ex.Next()) { |
874 | const TopoDS_Edge& edg = TopoDS::Edge(ex.Current()); |
875 | // test if the edge is in the map (only orienteed edges are present) |
876 | if (mapEF.Contains(edg)) { |
877 | for (TopTools_ListIteratorOfListOfShape itl(mapEF.FindFromKey(edg)); |
878 | itl.More(); itl.Next()) { |
879 | if (!itl.Value().IsSame(fac) && |
880 | !mapF.Contains(itl.Value())) { |
881 | Propagate(mapEF,itl.Value(),mapF); |
882 | } |
883 | } |
884 | } |
885 | } |
886 | } |