7fd59977 |
1 | // File: BOP_WireSplitter.cxx |
2 | // Created: Mon Apr 9 11:00:15 2001 |
3 | // Author: Peter KURNEV |
4 | |
5 | #include <BOP_WireSplitter.ixx> |
6 | |
7 | #include <gp_Pnt2d.hxx> |
8 | #include <gp_Vec2d.hxx> |
9 | |
10 | #include <Geom_Curve.hxx> |
11 | #include <Geom2d_Curve.hxx> |
12 | |
13 | #include <TopoDS.hxx> |
14 | #include <TopoDS_Vertex.hxx> |
15 | #include <TopoDS_Edge.hxx> |
16 | #include <TopoDS_Face.hxx> |
17 | #include <TopAbs_Orientation.hxx> |
18 | |
19 | #include <BRep_Tool.hxx> |
20 | |
21 | #include <TopExp.hxx> |
22 | #include <TopExp_Explorer.hxx> |
23 | |
24 | #include <TColgp_SequenceOfPnt2d.hxx> |
25 | |
26 | #include <TopTools_SequenceOfShape.hxx> |
27 | #include <TopTools_ListOfShape.hxx> |
28 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
29 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
30 | #include <TopTools_IndexedMapOfShape.hxx> |
31 | |
32 | #include <BOPTColStd_ListOfListOfShape.hxx> |
33 | #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx> |
34 | |
35 | #include <BOPTools_Tools2D.hxx> |
36 | |
37 | #include <BOP_EdgeInfo.hxx> |
38 | #include <BOP_ListOfEdgeInfo.hxx> |
39 | #include <BOP_ListIteratorOfListOfEdgeInfo.hxx> |
40 | #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx> |
41 | |
42 | |
43 | #include <BRepAdaptor_Surface.hxx> |
44 | #include <GeomAdaptor_Surface.hxx> |
45 | #include <BRepAdaptor_Curve2d.hxx> |
46 | #include <TColStd_SequenceOfReal.hxx> |
47 | #include <Precision.hxx> |
48 | |
49 | static |
50 | void Path (const GeomAdaptor_Surface& aGAS, |
51 | const TopoDS_Face& myFace, |
52 | const TopoDS_Vertex& aVa, |
53 | const TopoDS_Edge& aEOuta, |
54 | BOP_EdgeInfo& anEdgeInfo, |
55 | TopTools_SequenceOfShape& aLS, |
56 | TopTools_SequenceOfShape& aVertVa, |
57 | TColgp_SequenceOfPnt2d& aCoordVa, |
58 | BOPTColStd_ListOfListOfShape& myShapes, |
59 | BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap); |
60 | |
61 | |
62 | static |
63 | Standard_Real Angle (const gp_Dir2d& aDir2D); |
64 | |
65 | |
66 | static |
67 | void GetNextVertex(const TopoDS_Vertex& aV, |
68 | const TopoDS_Edge& aE, |
69 | TopoDS_Vertex& aV1); |
70 | static |
71 | Standard_Real ClockWiseAngle(const Standard_Real aAngleIn, |
72 | const Standard_Real aAngleOut); |
73 | |
74 | static |
75 | Standard_Real AngleIn(const TopoDS_Edge& aEIn, |
76 | const BOP_ListOfEdgeInfo& aLEInfo); |
77 | |
78 | static |
79 | Standard_Real Angle2D (const TopoDS_Vertex& aV, |
80 | const TopoDS_Edge& anEdge, |
81 | const TopoDS_Face& myFace, |
82 | const GeomAdaptor_Surface& aGAS, |
83 | const Standard_Boolean aFlag); |
84 | static |
85 | gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1, |
86 | const TopoDS_Edge& aE1, |
87 | const TopoDS_Face& aF); |
88 | static |
89 | gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE, |
90 | const TopoDS_Face& aF); |
91 | static |
92 | Standard_Real Tolerance2D (const TopoDS_Vertex& aV, |
93 | const GeomAdaptor_Surface& aGAS); |
94 | |
95 | static |
96 | Standard_Real UTolerance2D (const TopoDS_Vertex& aV, |
97 | const GeomAdaptor_Surface& aGAS); |
98 | static |
99 | Standard_Real VTolerance2D (const TopoDS_Vertex& aV, |
100 | const GeomAdaptor_Surface& aGAS); |
101 | |
102 | static |
103 | Standard_Boolean RecomputeAngles(const BOP_ListOfEdgeInfo& aLEInfo, |
104 | const TopoDS_Face& theFace, |
105 | const gp_Pnt2d& thePb, |
106 | const TopoDS_Vertex& theVb, |
107 | const GeomAdaptor_Surface& theGAS, |
108 | const TopoDS_Edge& theEOuta, |
109 | const Standard_Boolean& bHasClosed, |
110 | const Standard_Real& theTol2D, |
111 | TColStd_SequenceOfReal& theRecomputedAngles); |
112 | // |
113 | static |
114 | Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& ); |
115 | // |
116 | |
117 | //======================================================================= |
118 | // function: DoWithFace |
119 | // purpose: |
120 | //======================================================================= |
121 | void BOP_WireSplitter::DoWithFace() |
122 | { |
123 | myEdges.Clear(); |
124 | |
125 | TopExp_Explorer anExpEdges (myFace, TopAbs_EDGE); |
126 | for (; anExpEdges.More(); anExpEdges.Next()) { |
127 | const TopoDS_Edge& anEdge = TopoDS::Edge(anExpEdges.Current()); |
128 | // |
129 | if (anEdge.Orientation()==TopAbs_INTERNAL){ |
130 | continue; |
131 | } |
132 | // |
133 | myEdges.Append(anEdge); |
134 | } |
135 | Do(); |
136 | } |
137 | //======================================================================= |
138 | // function: DoWithListOfEdges |
139 | // purpose: |
140 | //======================================================================= |
141 | void BOP_WireSplitter::DoWithListOfEdges(const TopTools_ListOfShape& aLE) |
142 | { |
143 | myEdges.Clear(); |
144 | |
145 | TopTools_ListIteratorOfListOfShape anItList; |
146 | |
147 | anItList.Initialize(aLE); |
148 | for (; anItList.More(); anItList.Next()) { |
149 | const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); |
150 | // |
151 | if (anEdge.Orientation()==TopAbs_INTERNAL){ |
152 | continue; |
153 | } |
154 | // |
155 | myEdges.Append(anEdge); |
156 | } |
157 | Do(); |
158 | } |
159 | //======================================================================= |
160 | // function: Do |
161 | // purpose: |
162 | //======================================================================= |
163 | void BOP_WireSplitter::Do() |
164 | { |
165 | myIsDone=Standard_False; |
166 | myNothingToDo=Standard_True; |
167 | |
168 | Standard_Integer index, i, aNb, aCntIn, aCntOut; |
169 | Standard_Boolean anIsIn; |
170 | Standard_Real anAngle; |
171 | |
172 | BOP_ListOfEdgeInfo emptyInfo; |
173 | TopTools_ListIteratorOfListOfShape anItList; |
174 | // |
175 | // 1.Filling mySmartMap |
176 | mySmartMap.Clear(); |
177 | |
178 | anItList.Initialize(myEdges); |
179 | for (; anItList.More(); anItList.Next()) { |
180 | const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); |
181 | // |
182 | if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) { |
183 | continue; |
184 | } |
185 | // |
186 | TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX); |
187 | for (; anExpVerts.More(); anExpVerts.Next()) { |
188 | const TopoDS_Shape& aVertex= anExpVerts.Current(); |
189 | |
190 | index = mySmartMap.FindIndex(aVertex); |
191 | if (!index) { |
192 | index=mySmartMap.Add(aVertex, emptyInfo); |
193 | } |
194 | |
195 | BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index); |
196 | |
197 | BOP_EdgeInfo aEInfo; |
198 | aEInfo.SetEdge(anEdge); |
199 | |
200 | TopAbs_Orientation anOr=aVertex.Orientation(); |
201 | |
202 | if (anOr==TopAbs_FORWARD) { |
203 | aEInfo.SetInFlag(Standard_False); |
204 | } |
205 | |
206 | else if (anOr==TopAbs_REVERSED) { |
207 | aEInfo.SetInFlag(Standard_True); |
208 | } |
209 | |
210 | aListOfEInfo.Append(aEInfo); |
211 | } |
212 | } |
213 | // |
214 | aNb=mySmartMap.Extent(); |
215 | // |
216 | // 2. myNothingToDo |
217 | myNothingToDo=Standard_True; |
218 | |
219 | for (i=1; i<=aNb; i++) { |
220 | aCntIn=0; |
221 | aCntOut=0; |
222 | const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); |
223 | BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); |
224 | for (; anIt.More(); anIt.Next()) { |
225 | const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); |
226 | anIsIn=anEdgeInfo.IsIn(); |
227 | if (anIsIn) { |
228 | aCntIn++; |
229 | } |
230 | else { |
231 | aCntOut++; |
232 | } |
233 | } |
234 | if (aCntIn!=1 || aCntOut!=1) { |
235 | myNothingToDo=Standard_False; |
236 | break; |
237 | } |
238 | } |
239 | // |
240 | // Each vertex has one edge In and one - Out. Good. But it is not enought |
241 | // to consider that nothing to do with this. We must check edges on TShape |
242 | // coinsidence. If there are such edges there is something to do with. |
243 | // |
244 | if (myNothingToDo) { |
245 | Standard_Integer aNbE, aNbMapEE; |
246 | TopTools_IndexedDataMapOfShapeListOfShape aMapEE; |
247 | aNbE=myEdges.Extent(); |
248 | |
249 | anItList.Initialize(myEdges); |
250 | for (; anItList.More(); anItList.Next()) { |
251 | const TopoDS_Shape& aE = anItList.Value(); |
252 | |
253 | if (!aMapEE.Contains(aE)) { |
254 | TopTools_ListOfShape aLEx; |
255 | aLEx.Append(aE); |
256 | aMapEE.Add(aE, aLEx); |
257 | } |
258 | else { |
259 | TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE); |
260 | aLEx.Append(aE); |
261 | } |
262 | } |
263 | |
264 | Standard_Boolean bFlag; |
265 | bFlag=Standard_True; |
266 | aNbMapEE=aMapEE.Extent(); |
267 | for (i=1; i<=aNbMapEE; i++) { |
268 | const TopTools_ListOfShape& aLEx=aMapEE(i); |
269 | aNbE=aLEx.Extent(); |
270 | if (aNbE==1) { |
271 | // usual case |
272 | continue; |
273 | } |
274 | else if (aNbE==2){ |
275 | const TopoDS_Shape& aE1=aLEx.First(); |
276 | const TopoDS_Shape& aE2=aLEx.Last(); |
277 | if (aE1.IsSame(aE2)) { |
278 | bFlag=Standard_False; |
279 | break; |
280 | } |
281 | } |
282 | else { |
283 | bFlag=Standard_False; |
284 | break; |
285 | } |
286 | } |
287 | myNothingToDo=myNothingToDo && bFlag; |
288 | } |
289 | // |
290 | // |
291 | if (myNothingToDo) { |
292 | myIsDone=Standard_True; |
293 | return; |
294 | } |
295 | // |
296 | // 3. Angles in mySmartMap |
297 | BRepAdaptor_Surface aBAS(myFace); |
298 | const GeomAdaptor_Surface& aGAS=aBAS.Surface(); |
299 | for (i=1; i<=aNb; i++) { |
300 | const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i)); |
301 | const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); |
302 | |
303 | BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); |
304 | for (; anIt.More(); anIt.Next()) { |
305 | BOP_EdgeInfo& anEdgeInfo=anIt.Value(); |
306 | const TopoDS_Edge& aE=anEdgeInfo.Edge(); |
307 | // |
308 | TopoDS_Vertex aVV=aV; |
309 | // |
310 | anIsIn=anEdgeInfo.IsIn(); |
311 | if (anIsIn) { |
312 | // |
313 | aVV.Orientation(TopAbs_REVERSED); |
314 | anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True); |
315 | } |
316 | // |
317 | else { // OUT |
318 | // |
319 | aVV.Orientation(TopAbs_FORWARD); |
320 | anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False); |
321 | } |
322 | anEdgeInfo.SetAngle(anAngle); |
323 | |
324 | } |
325 | } |
326 | // |
327 | // 4. Do |
328 | // |
329 | Standard_Boolean anIsOut, anIsNotPassed; |
330 | |
331 | TopTools_SequenceOfShape aLS, aVertVa; |
332 | TColgp_SequenceOfPnt2d aCoordVa; |
333 | |
334 | BOP_ListIteratorOfListOfEdgeInfo anIt; |
335 | |
336 | for (i=1; i<=aNb; i++) { |
337 | const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i)); |
338 | const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i); |
339 | |
340 | anIt.Initialize(aLEInfo); |
341 | for (; anIt.More(); anIt.Next()) { |
342 | BOP_EdgeInfo& anEdgeInfo=anIt.Value(); |
343 | const TopoDS_Edge& aEOuta=anEdgeInfo.Edge(); |
344 | |
345 | anIsOut=!anEdgeInfo.IsIn(); |
346 | anIsNotPassed=!anEdgeInfo.Passed(); |
347 | |
348 | if (anIsOut && anIsNotPassed) { |
349 | // |
350 | aLS.Clear(); |
351 | aVertVa.Clear(); |
352 | aCoordVa.Clear(); |
353 | // |
354 | Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, |
355 | aVertVa, aCoordVa, myShapes, mySmartMap); |
356 | } |
357 | } |
358 | } |
359 | // |
360 | { |
361 | Standard_Integer aNbV, aNbE; |
362 | TopoDS_Vertex aV1, aV2; |
363 | BOPTColStd_ListOfListOfShape aShapes; |
364 | BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes); |
365 | |
366 | for (; anItW.More(); anItW.Next()) { |
367 | TopTools_IndexedMapOfShape aMV, aME; |
368 | const TopTools_ListOfShape& aLE=anItW.Value(); |
369 | TopTools_ListIteratorOfListOfShape anItE(aLE); |
370 | for (; anItE.More(); anItE.Next()) { |
371 | const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value()); |
372 | aME.Add(aE); |
373 | TopExp::Vertices(aE, aV1, aV2); |
374 | aMV.Add(aV1); |
375 | aMV.Add(aV2); |
376 | } |
377 | aNbV=aMV.Extent(); |
378 | aNbE=aME.Extent(); |
379 | if (aNbV<=aNbE) { |
380 | aShapes.Append(aLE); |
381 | } |
382 | } |
383 | // |
384 | myShapes.Clear(); |
385 | anItW.Initialize(aShapes); |
386 | for (; anItW.More(); anItW.Next()) { |
387 | const TopTools_ListOfShape& aLE=anItW.Value(); |
388 | myShapes.Append(aLE); |
389 | } |
390 | } |
391 | // |
392 | myIsDone=Standard_True; |
393 | } |
394 | //======================================================================= |
395 | // function: Path |
396 | // purpose: |
397 | //======================================================================= |
398 | void Path (const GeomAdaptor_Surface& aGAS, |
399 | const TopoDS_Face& myFace, |
400 | const TopoDS_Vertex& aVa, |
401 | const TopoDS_Edge& aEOuta, |
402 | BOP_EdgeInfo& anEdgeInfo, |
403 | TopTools_SequenceOfShape& aLS, |
404 | TopTools_SequenceOfShape& aVertVa, |
405 | TColgp_SequenceOfPnt2d& aCoordVa, |
406 | BOPTColStd_ListOfListOfShape& myShapes, |
407 | BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap) |
408 | |
409 | { |
410 | Standard_Integer i,j, aNb, aNbj; |
411 | Standard_Real aD, aTol=1.e-7, anAngleIn, anAngleOut, anAngle, aMinAngle; |
412 | Standard_Real aTol2D, aTolVb, aTolVPrev; |
413 | Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed; |
414 | BOP_ListIteratorOfListOfEdgeInfo anIt; |
415 | |
416 | TopoDS_Vertex aVb; |
417 | TopoDS_Edge aEOutb; |
418 | // |
419 | // append block |
420 | // |
421 | // Do not escape through edge from which you enter |
422 | aNb=aLS.Length(); |
423 | if (aNb==1) { |
424 | const TopoDS_Shape& anEPrev=aLS(aNb); |
425 | |
426 | if (anEPrev.IsSame(aEOuta)) { |
427 | return; |
428 | } |
429 | } |
430 | // |
431 | // |
432 | anEdgeInfo.SetPassed(Standard_True); |
433 | aLS.Append(aEOuta); |
434 | aVertVa.Append(aVa); |
435 | |
436 | TopoDS_Vertex pVa=aVa; |
437 | pVa.Orientation(TopAbs_FORWARD); |
438 | gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace); |
439 | aCoordVa.Append(aPa); |
440 | |
441 | GetNextVertex (pVa, aEOuta, aVb); |
442 | |
443 | gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace); |
444 | |
445 | const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb); |
446 | |
447 | TopoDS_Vertex aV1, aV2; |
448 | TopExp::Vertices(aEOuta, aV1, aV2); |
449 | Standard_Boolean bHasClosedEdge = aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2); |
450 | Standard_Boolean bHasDegenerated = BRep_Tool::Degenerated(aEOuta); |
451 | Standard_Boolean bHasSeam = BRep_Tool::IsClosed(aEOuta, myFace); |
452 | anIt.Initialize(aLEInfoVb); |
453 | |
454 | for (; anIt.More(); anIt.Next()) { |
455 | BOP_EdgeInfo& anEI=anIt.Value(); |
456 | const TopoDS_Edge& aE=anEI.Edge(); |
457 | bHasDegenerated = bHasDegenerated || BRep_Tool::Degenerated(aE); |
458 | bHasSeam = bHasSeam || BRep_Tool::IsClosed(aE, myFace); |
459 | aV1.Nullify(); |
460 | aV2.Nullify(); |
461 | TopExp::Vertices(aE, aV1, aV2); |
462 | bHasClosedEdge = bHasClosedEdge || aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2); |
463 | } |
464 | |
465 | aNb=aLS.Length(); |
466 | if (aNb>0) { |
467 | // |
468 | TopTools_ListOfShape aBuf; |
469 | for (i=aNb; i>0; i--) { |
470 | const TopoDS_Shape& aVPrev=aVertVa(i); |
471 | const gp_Pnt2d& aPaPrev=aCoordVa(i); |
472 | const TopoDS_Shape& aEPrev=aLS(i); |
473 | |
474 | aBuf.Append(aEPrev); |
475 | |
476 | anIsSameV=aVPrev.IsSame(aVb); |
477 | anIsSameV2d = Standard_False; |
478 | |
479 | if (anIsSameV) { |
480 | anIsSameV2d = Standard_True; |
481 | |
482 | if(bHasDegenerated || bHasSeam || bHasClosedEdge) { |
483 | aTolVb =BRep_Tool::Tolerance(TopoDS::Vertex(aVb)); |
484 | aTolVPrev=BRep_Tool::Tolerance(TopoDS::Vertex(aVPrev)); |
485 | aTol=aTolVb+aTolVPrev; |
486 | // |
487 | aTol=2.*Tolerance2D(aVb, aGAS); |
488 | aD=aPaPrev.Distance(aPb); |
489 | anIsSameV2d = (aD < aTol); |
490 | |
491 | if(anIsSameV2d) { |
492 | Standard_Real udist = fabs(aPaPrev.X() - aPb.X()); |
493 | Standard_Real vdist = fabs(aPaPrev.Y() - aPb.Y()); |
494 | Standard_Real aTolU = 2. * UTolerance2D(aVb, aGAS); |
495 | Standard_Real aTolV = 2. * VTolerance2D(aVb, aGAS); |
496 | |
497 | if((udist > aTolU) || |
498 | (vdist > aTolV)) { |
499 | anIsSameV2d = Standard_False; |
500 | } |
501 | } |
502 | } |
503 | } |
504 | |
505 | // |
506 | if (anIsSameV && anIsSameV2d) { |
507 | myShapes.Append(aBuf); |
508 | // |
509 | TopTools_SequenceOfShape aLSt, aVertVat; |
510 | TColgp_SequenceOfPnt2d aCoordVat; |
511 | // |
512 | aNbj=i-1; |
513 | if (aNbj<1) { |
514 | // |
515 | aLS.Clear(); |
516 | aVertVa.Clear(); |
517 | aCoordVa.Clear(); |
518 | // |
519 | return; |
520 | } |
521 | |
522 | aVb=TopoDS::Vertex(aVertVa(i)); |
523 | |
524 | for (j=1; j<=aNbj; j++) { |
525 | aLSt.Append(aLS(j)); |
526 | aVertVat.Append(aVertVa(j)); |
527 | aCoordVat.Append(aCoordVa(j)); |
528 | } |
529 | // |
530 | aLS.Clear(); |
531 | aVertVa.Clear(); |
532 | aCoordVa.Clear(); |
533 | |
534 | aLS=aLSt; |
535 | aVertVa=aVertVat; |
536 | aCoordVa=aCoordVat; |
537 | // |
538 | break; |
539 | } |
540 | } |
541 | } |
542 | // |
543 | aTol2D=2.*Tolerance2D(aVb, aGAS); |
544 | // |
545 | // anAngleIn in Vb from edge aEOuta |
546 | const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb); |
547 | // |
548 | anAngleIn=AngleIn(aEOuta, aLEInfo); |
549 | // |
550 | // aEOutb |
551 | BOP_EdgeInfo *pEdgeInfo=NULL; |
552 | |
553 | aMinAngle=100.; |
554 | anIsFound=Standard_False; |
555 | |
556 | TColStd_SequenceOfReal aRecomputedAngles; |
557 | |
558 | Standard_Boolean bRecomputeAngle = |
559 | RecomputeAngles(aLEInfo, myFace, aPb, aVb, aGAS, aEOuta, |
560 | (bHasDegenerated || bHasSeam || bHasClosedEdge), |
561 | aTol2D, aRecomputedAngles); |
562 | |
563 | Standard_Integer aCurIndexE = 0; |
564 | |
565 | anIt.Initialize(aLEInfo); |
566 | for (; anIt.More(); anIt.Next()) { |
567 | BOP_EdgeInfo& anEI=anIt.Value(); |
568 | const TopoDS_Edge& aE=anEI.Edge(); |
569 | anIsOut=!anEI.IsIn(); |
570 | anIsNotPassed=!anEI.Passed(); |
571 | |
572 | if (anIsOut && anIsNotPassed) { |
573 | aCurIndexE++; |
574 | // |
575 | // Is there one way to go out of the vertex |
576 | // we have to use it only. |
577 | Standard_Integer iCnt; |
578 | iCnt=NbWaysOut (aLEInfo); |
579 | // |
580 | if (!iCnt) { |
581 | // no way to go . (Error) |
582 | return ; |
583 | } |
584 | // |
585 | if (iCnt==1) { |
586 | // the one and only way to go out . |
587 | pEdgeInfo=&anEI; |
588 | anIsFound=Standard_True; |
589 | break; |
590 | } |
591 | // |
592 | // Look for minimal angle and make the choice. |
593 | gp_Pnt2d aP2Dx; |
594 | // |
595 | aP2Dx=Coord2dVf(aE, myFace); |
596 | // |
597 | aD=aP2Dx.Distance(aPb); |
598 | if (aD > aTol2D){ |
599 | continue; |
600 | } |
601 | // |
602 | // |
603 | anAngleOut=anEI.Angle(); |
604 | // |
605 | if(bRecomputeAngle) { |
606 | if(aCurIndexE <= aRecomputedAngles.Length()) { |
607 | anAngleOut = aRecomputedAngles.Value(aCurIndexE); |
608 | } |
609 | } |
610 | // |
611 | anAngle=ClockWiseAngle(anAngleIn, anAngleOut); |
612 | if (anAngle < aMinAngle) { |
613 | aMinAngle=anAngle; |
614 | pEdgeInfo=&anEI; |
615 | anIsFound=Standard_True; |
616 | } |
617 | } |
618 | } // for (; anIt.More(); anIt.Next()) |
619 | // |
620 | if (!anIsFound) { |
621 | // no way to go . (Error) |
622 | return; |
623 | } |
624 | |
625 | aEOutb=pEdgeInfo->Edge(); |
626 | Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS, |
627 | aVertVa, aCoordVa, myShapes, mySmartMap); |
628 | } |
629 | //======================================================================= |
630 | // function: Coord2dVf |
631 | // purpose: |
632 | //======================================================================= |
633 | gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE, |
634 | const TopoDS_Face& aF) |
635 | { |
636 | TopExp_Explorer anExp(aE, TopAbs_VERTEX); |
637 | for (; anExp.More(); anExp.Next()) { |
638 | const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); |
639 | if (aVx.Orientation()==TopAbs_FORWARD) |
640 | return Coord2d(aVx, aE, aF); |
641 | } |
642 | const Standard_Real aCoord=99.; |
643 | const gp_Pnt2d aP2D1(aCoord, aCoord); |
644 | return aP2D1; |
645 | } |
646 | //======================================================================= |
647 | // function: Tolerance2D |
648 | // purpose: |
649 | //======================================================================= |
650 | Standard_Real Tolerance2D (const TopoDS_Vertex& aV, |
651 | const GeomAdaptor_Surface& aGAS) |
652 | { |
653 | const GeomAbs_SurfaceType aType=aGAS.GetType(); |
654 | const Standard_Real aTolV3D=BRep_Tool::Tolerance(aV); |
655 | const Standard_Real aUr=aGAS.UResolution(aTolV3D); |
656 | const Standard_Real aVr=aGAS.VResolution(aTolV3D); |
657 | // |
658 | Standard_Real aTol2D=(aVr>aUr) ? aVr : aUr; |
659 | // |
660 | if (aType==GeomAbs_BSplineSurface || aType==GeomAbs_Sphere) { |
661 | if (aTol2D < aTolV3D) |
662 | aTol2D=aTolV3D; |
663 | } |
664 | //modified by NIZNHY-PKV Wed Jul 5 16:44:59 2006f |
665 | else if (aType==GeomAbs_BSplineSurface) { |
666 | aTol2D=1.1*aTol2D; |
667 | } |
668 | //modified by NIZNHY-PKV Wed Jul 5 16:45:02 2006t |
669 | // |
670 | return aTol2D; |
671 | } |
672 | |
673 | //======================================================================= |
674 | // function: Coord2d |
675 | // purpose: |
676 | //======================================================================= |
677 | gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1, |
678 | const TopoDS_Edge& aE1, |
679 | const TopoDS_Face& aF) |
680 | { |
681 | const Standard_Real t=BRep_Tool::Parameter (aV1, aE1, aF); |
682 | |
683 | Standard_Real aFirst, aLast, aToler; |
684 | Handle(Geom2d_Curve) aC2D; |
685 | BOPTools_Tools2D::CurveOnSurface |
686 | (aE1, aF, aC2D, aFirst, aLast, aToler, Standard_True); |
687 | |
688 | gp_Pnt2d aP2D1; |
689 | aC2D->D0 (t, aP2D1); |
690 | |
691 | return aP2D1; |
692 | } |
693 | //======================================================================= |
694 | // function: AngleIn |
695 | // purpose: |
696 | //======================================================================= |
697 | Standard_Real AngleIn(const TopoDS_Edge& aEIn, |
698 | const BOP_ListOfEdgeInfo& aLEInfo) |
699 | { |
700 | BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); |
701 | for (; anIt.More(); anIt.Next()) { |
702 | const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); |
703 | const TopoDS_Edge& aE=anEdgeInfo.Edge(); |
704 | const Standard_Boolean anIsIn=anEdgeInfo.IsIn(); |
705 | // |
706 | if (anIsIn && aE==aEIn) |
707 | return anEdgeInfo.Angle(); |
708 | } |
709 | return 0.; |
710 | } |
711 | //======================================================================= |
712 | // function: ClockWiseAngle |
713 | // purpose: |
714 | //======================================================================= |
715 | Standard_Real ClockWiseAngle(const Standard_Real aAngleIn, |
716 | const Standard_Real aAngleOut) |
717 | { |
718 | const Standard_Real aTwoPi=Standard_PI+Standard_PI; |
719 | Standard_Real dA, A1, A2, AIn, AOut ; |
720 | |
721 | AIn=aAngleIn; |
722 | AOut=aAngleOut; |
723 | if (AIn >= aTwoPi) { |
724 | AIn=AIn-aTwoPi; |
725 | } |
726 | |
727 | if (AOut >= aTwoPi) { |
728 | AOut=AOut-aTwoPi; |
729 | } |
730 | |
731 | A1=AIn+Standard_PI; |
732 | |
733 | if (A1 >= aTwoPi) { |
734 | A1=A1-aTwoPi; |
735 | } |
736 | |
737 | A2=AOut; |
738 | |
739 | dA=A1-A2; |
740 | if (dA <= 0.) { |
741 | dA=aTwoPi+dA; |
742 | } |
743 | //xx |
744 | //else if (dA <= 1.e-15) { |
745 | else if (dA <= 1.e-14) { |
746 | dA=aTwoPi; |
747 | } |
748 | return dA; |
749 | } |
750 | //======================================================================= |
751 | // function: GetNextVertex |
752 | // purpose: |
753 | //======================================================================= |
754 | void GetNextVertex(const TopoDS_Vertex& aV, |
755 | const TopoDS_Edge& aE, |
756 | TopoDS_Vertex& aV1) |
757 | { |
758 | TopExp_Explorer anExp(aE, TopAbs_VERTEX); |
759 | for (; anExp.More(); anExp.Next()) { |
760 | const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); |
761 | if (!aVx.IsEqual(aV)) { |
762 | aV1=aVx; |
763 | return ; |
764 | } |
765 | } |
766 | aV1=aV; |
767 | } |
768 | //======================================================================= |
769 | // function: Angle2D |
770 | // purpose: |
771 | //======================================================================= |
772 | Standard_Real Angle2D (const TopoDS_Vertex& aV, |
773 | const TopoDS_Edge& anEdge, |
774 | const TopoDS_Face& myFace, |
775 | const GeomAdaptor_Surface& aGAS, |
776 | const Standard_Boolean aFlag) |
777 | { |
778 | const Standard_Real aTV=BRep_Tool::Parameter (aV, anEdge, myFace); |
779 | if (Precision::IsInfinite(aTV)) |
780 | return 0.; |
781 | |
782 | Handle(Geom2d_Curve) aC2D; |
783 | Standard_Real aFirst, aLast, aToler; |
784 | BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D, aFirst, aLast, aToler, Standard_True); |
785 | if (aC2D.IsNull()) |
786 | return 0.; |
787 | |
788 | //dt=1.e-7; |
789 | Standard_Real dt=Tolerance2D(aV, aGAS); |
790 | const Standard_Real dtmax=(aLast - aFirst) * 0.25; |
791 | if(dt > dtmax) { |
792 | // to save direction of the curve as much as it possible |
793 | // in the case of big tolerances |
794 | dt = dtmax; |
795 | } |
796 | const Standard_Real aTV1 = (fabs (aTV-aFirst) < fabs(aTV - aLast))? aTV + dt : aTV - dt; |
797 | // |
798 | gp_Pnt2d aPV, aPV1; |
799 | aC2D->D0 (aTV, aPV); |
800 | aC2D->D0 (aTV1, aPV1); |
801 | const gp_XY aV2D( aFlag? (aPV.XY()-aPV1.XY()) : (aPV1.XY()-aPV.XY()) ); |
802 | |
803 | //See http://www.opencascade.org/org/forum/thread_17712/ |
804 | if (aV2D.SquareModulus() <= gp::Resolution()*gp::Resolution()) |
805 | return 0.; |
806 | |
807 | const gp_Dir2d aDir2D(aV2D); |
808 | |
809 | return Angle(aDir2D); |
810 | } |
811 | //======================================================================= |
812 | // function: Angle |
813 | // purpose: |
814 | //======================================================================= |
815 | Standard_Real Angle (const gp_Dir2d& aDir2D) |
816 | { |
817 | const Standard_Real anAngle = gp_Dir2d(1.,0.).Angle(aDir2D); |
818 | return ((anAngle < 0.)? anAngle + Standard_PI + Standard_PI : anAngle); |
819 | } |
820 | |
821 | //======================================================================= |
822 | // function: NbWaysOut |
823 | // purpose: |
824 | //======================================================================= |
825 | Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo) |
826 | { |
827 | Standard_Integer iCnt=0; |
828 | // |
829 | BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); |
830 | for (; anIt.More(); anIt.Next()) { |
831 | const BOP_EdgeInfo& anEI=anIt.Value(); |
832 | // |
833 | //const TopoDS_Edge& aE=anEI.Edge(); |
834 | const Standard_Boolean bIsOut=!anEI.IsIn(); |
835 | const Standard_Boolean bIsNotPassed=!anEI.Passed(); |
836 | if (bIsOut && bIsNotPassed) |
837 | iCnt++; |
838 | } |
839 | return iCnt; |
840 | } |
841 | |
842 | //======================================================================= |
843 | //function : UTolerance2D |
844 | //purpose : |
845 | //======================================================================= |
846 | Standard_Real UTolerance2D (const TopoDS_Vertex& aV, |
847 | const GeomAdaptor_Surface& aGAS) |
848 | { |
849 | const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV); |
850 | const Standard_Real anUr = aGAS.UResolution(aTolV3D); |
851 | // |
852 | return anUr; |
853 | } |
854 | |
855 | //======================================================================= |
856 | //function : VTolerance2D |
857 | //purpose : |
858 | //======================================================================= |
859 | Standard_Real VTolerance2D (const TopoDS_Vertex& aV, |
860 | const GeomAdaptor_Surface& aGAS) |
861 | { |
862 | const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV); |
863 | const Standard_Real anVr = aGAS.VResolution(aTolV3D); |
864 | // |
865 | return anVr; |
866 | } |
867 | //======================================================================= |
868 | // function: RecomputeAngles |
869 | // purpose: |
870 | //======================================================================= |
871 | Standard_Boolean RecomputeAngles(const BOP_ListOfEdgeInfo& aLEInfo, |
872 | const TopoDS_Face& theFace, |
873 | const gp_Pnt2d& thePb, |
874 | const TopoDS_Vertex& theVb, |
875 | const GeomAdaptor_Surface& theGAS, |
876 | const TopoDS_Edge& theEOuta, |
877 | const Standard_Boolean& bHasClosed, |
878 | const Standard_Real& theTol2D, |
879 | TColStd_SequenceOfReal& theRecomputedAngles) |
880 | { |
881 | Standard_Boolean bRecomputeAngle = Standard_False; |
882 | BOP_ListIteratorOfListOfEdgeInfo anIt; |
883 | anIt.Initialize(aLEInfo); |
884 | |
885 | for (; anIt.More(); anIt.Next()) { |
886 | BOP_EdgeInfo& anEI=anIt.Value(); |
887 | const TopoDS_Edge& aE=anEI.Edge(); |
888 | Standard_Boolean anIsOut=!anEI.IsIn(); |
889 | Standard_Boolean anIsNotPassed=!anEI.Passed(); |
890 | |
891 | if (anIsOut && anIsNotPassed) { |
892 | theRecomputedAngles.Append(anEI.Angle()); |
893 | Standard_Integer acurindex = theRecomputedAngles.Length(); |
894 | |
895 | Standard_Boolean bRecomputeAngleLocal = Standard_False; |
896 | TopExp_Explorer anExp1(aE, TopAbs_VERTEX); |
897 | |
898 | for(; anExp1.More(); anExp1.Next()) { |
899 | TopExp_Explorer anExp2(theEOuta, TopAbs_VERTEX); |
900 | Standard_Boolean existsInEdge = Standard_False; |
901 | |
902 | for(; anExp2.More(); anExp2.Next()) { |
903 | if(anExp1.Current().IsSame(anExp2.Current())) { |
904 | existsInEdge = Standard_True; |
905 | break; |
906 | } |
907 | } |
908 | |
909 | if(!existsInEdge) { |
910 | bRecomputeAngleLocal = Standard_False; |
911 | break; |
912 | } |
913 | bRecomputeAngleLocal = Standard_True; |
914 | } |
915 | bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; |
916 | |
917 | if(!bRecomputeAngle) { |
918 | BOP_ListIteratorOfListOfEdgeInfo anIt2(aLEInfo); |
919 | |
920 | for(; anIt2.More(); anIt2.Next()) { |
921 | BOP_EdgeInfo& anEI2=anIt2.Value(); |
922 | const TopoDS_Edge& aE2=anEI2.Edge(); |
923 | |
924 | if(aE2.IsSame(aE)) |
925 | continue; |
926 | Standard_Boolean anIsOut2=!anEI2.IsIn(); |
927 | Standard_Boolean anIsNotPassed2=!anEI2.Passed(); |
928 | |
929 | if (anIsOut2 && anIsNotPassed2) { |
930 | anExp1.Init(aE, TopAbs_VERTEX); |
931 | |
932 | for(; anExp1.More(); anExp1.Next()) { |
933 | TopExp_Explorer anExp2(aE2, TopAbs_VERTEX); |
934 | Standard_Boolean existsInEdge = Standard_False; |
935 | |
936 | for(; anExp2.More(); anExp2.Next()) { |
937 | if(anExp1.Current().IsSame(anExp2.Current())) { |
938 | existsInEdge = Standard_True; |
939 | break; |
940 | } |
941 | } |
942 | |
943 | if(!existsInEdge) { |
944 | bRecomputeAngleLocal = Standard_False; |
945 | break; |
946 | } |
947 | bRecomputeAngleLocal = Standard_True; |
948 | } |
949 | bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; |
950 | } |
951 | } |
952 | } |
953 | |
954 | bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal; |
955 | |
956 | if(bRecomputeAngle) { |
957 | gp_Pnt2d aP2Dx; |
958 | // |
959 | aP2Dx=Coord2dVf(aE, theFace); |
960 | Standard_Real aD = aP2Dx.Distance(thePb); |
961 | |
962 | TopoDS_Vertex aVf; |
963 | TopExp_Explorer anExp(aE, TopAbs_VERTEX); |
964 | |
965 | for (; anExp.More(); anExp.Next()) { |
966 | const TopoDS_Vertex& aVx=TopoDS::Vertex(anExp.Current()); |
967 | if (aVx.Orientation()==TopAbs_FORWARD) { |
968 | aVf = aVx; |
969 | } |
970 | } |
971 | Standard_Boolean bIgnore = Standard_False; |
972 | |
973 | if(bHasClosed || aVf.IsNull() || !aVf.IsSame(theVb)) { |
974 | bIgnore = (aD > theTol2D); |
975 | } |
976 | |
977 | if(!bIgnore && (theTol2D > PI)) { |
978 | Standard_Real udist = fabs(aP2Dx.X() - thePb.X()); |
979 | Standard_Real vdist = fabs(aP2Dx.Y() - thePb.Y()); |
980 | Standard_Real aTolU = 2. * UTolerance2D(theVb, theGAS); |
981 | Standard_Real aTolV = 2. * VTolerance2D(theVb, theGAS); |
982 | |
983 | if((udist > aTolU) || |
984 | (vdist > aTolV)) { |
985 | bIgnore = Standard_True; |
986 | } |
987 | } |
988 | |
989 | if((aD > Precision::Confusion()) && !bIgnore) { |
990 | Standard_Real f1, l1; |
991 | Handle(Geom2d_Curve) ac1 = BRep_Tool::CurveOnSurface(aE, theFace, f1, l1); |
992 | |
993 | Standard_Real aTV1 = BRep_Tool::Parameter (aVf, aE, theFace); |
994 | Standard_Real aTV12 = 0.; |
995 | Standard_Real dt1 = (l1 - f1) * 0.5; |
996 | |
997 | if (fabs (aTV1-f1) < fabs(aTV1 - l1)) { |
998 | aTV12 = aTV1 + dt1; |
999 | } |
1000 | else { |
1001 | aTV12 = aTV1 - dt1; |
1002 | } |
1003 | |
1004 | gp_Pnt2d aPointNew = ac1->Value(aTV12); |
1005 | gp_Vec2d aV2DOut(thePb, aPointNew); |
1006 | |
1007 | gp_Dir2d aDir2D(aV2DOut); |
1008 | Standard_Real anAngleOut = Angle(aDir2D); |
1009 | theRecomputedAngles.ChangeValue(acurindex) = anAngleOut; |
1010 | } |
1011 | } |
1012 | } |
1013 | } |
1014 | return bRecomputeAngle; |
1015 | } |