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