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