0025609: Clean up the duplicate classes in TKBO project
[occt.git] / src / BOPAlgo / BOPAlgo_WireSplitter_1.cxx
CommitLineData
4e57c75e 1// Created by: Peter KURNEV
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
4e57c75e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
4e57c75e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
4e57c75e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
4e57c75e 14
42cf5bc1 15#include <BOPAlgo_WireEdgeSet.hxx>
16#include <BOPAlgo_WireSplitter.hxx>
42cf5bc1 17#include <BOPTools_AlgoTools2D.hxx>
18#include <BRep_Builder.hxx>
19#include <BRep_Tool.hxx>
20#include <BRepAdaptor_Surface.hxx>
4e57c75e 21#include <Geom2d_Curve.hxx>
c5face6f 22#include <Geom2d_Line.hxx>
c5face6f 23#include <Geom2dAdaptor_Curve.hxx>
c5face6f 24#include <Geom2dInt_GInter.hxx>
42cf5bc1 25#include <Geom_Plane.hxx>
26#include <Geom_RectangularTrimmedSurface.hxx>
27#include <Geom_Surface.hxx>
28#include <GeomAdaptor_Surface.hxx>
29#include <gp_Dir2d.hxx>
30#include <gp_Pnt2d.hxx>
31#include <gp_Vec2d.hxx>
c5face6f 32#include <IntRes2d_Domain.hxx>
33#include <IntRes2d_IntersectionPoint.hxx>
42cf5bc1 34#include <Precision.hxx>
35#include <TopExp.hxx>
36#include <TopExp_Explorer.hxx>
c5face6f 37#include <TopLoc_Location.hxx>
f80842e3 38#include <TopoDS.hxx>
4e57c75e 39#include <TopoDS_Edge.hxx>
42cf5bc1 40#include <TopoDS_Face.hxx>
41#include <TopoDS_Iterator.hxx>
4e57c75e 42#include <TopoDS_Vertex.hxx>
43#include <TopoDS_Wire.hxx>
c5face6f 44#include <TopTools_ShapeMapHasher.hxx>
3ba87fdb 45#include <Geom2dLProp_CLProps2d.hxx>
1155d05a 46#include <TColgp_SequenceOfPnt2d.hxx>
47#include <TColStd_SequenceOfReal.hxx>
48#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
49#include <TopTools_ListOfShape.hxx>
50#include <TopTools_MapOfShape.hxx>
51#include <TopTools_SequenceOfShape.hxx>
52
f56518cd 53typedef NCollection_DataMap \
54 <TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> \
1155d05a 55 MyDataMapOfShapeBoolean;
f56518cd 56//
57
4e57c75e 58static
59 Standard_Real Angle (const gp_Dir2d& aDir2D);
60
61static
62 Standard_Real Angle2D (const TopoDS_Vertex& aV,
63 const TopoDS_Edge& anEdge,
64 const TopoDS_Face& myFace,
65 const GeomAdaptor_Surface& aGAS,
51db0179 66 const Standard_Boolean aFlag,
67 const Handle(IntTools_Context)& theContext);
4e57c75e 68
69static
70 void GetNextVertex(const TopoDS_Vertex& aV,
71 const TopoDS_Edge& aE,
72 TopoDS_Vertex& aV1);
73
74static
75 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
76 const BOPAlgo_ListOfEdgeInfo& aLEInfo);
77
78static
79 Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo);
80
81static
82 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
83 const TopoDS_Face& aF);
84
85static
86 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
87 const TopoDS_Edge& aE1,
88 const TopoDS_Face& aF);
89
f56518cd 90static
4e57c75e 91 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
92 const Standard_Real aAngleOut);
93
94static
95 void Path (const GeomAdaptor_Surface& aGAS,
96 const TopoDS_Face& myFace,
97 const TopoDS_Vertex& aVa,
98 const TopoDS_Edge& aEOuta,
99 BOPAlgo_EdgeInfo& anEdgeInfo,
1155d05a 100 TopTools_SequenceOfShape& aLS,
101 TopTools_SequenceOfShape& aVertVa,
102 TColgp_SequenceOfPnt2d& aCoordVa,
4e57c75e 103 BOPTools_ConnexityBlock& aCB,
f56518cd 104 BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
1155d05a 105 MyDataMapOfShapeBoolean aVertMap);
f56518cd 106
4e57c75e 107static
108 Standard_Real Angle (const gp_Dir2d& aDir2D);
109
110static
111 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
112 const GeomAdaptor_Surface& aGAS);
113
acccace3 114
4e57c75e 115
116static
117 Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
118 const GeomAdaptor_Surface& aGAS);
119static
120 Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
121 const GeomAdaptor_Surface& aGAS);
122
c5face6f 123static
124 void RefineAngles(const TopoDS_Face& myFace,
1155d05a 125 const TopTools_ListOfShape&,
51db0179 126 BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo&,
127 const Handle(IntTools_Context)&);
c5face6f 128
129
130static
131 void RefineAngles(const TopoDS_Vertex& ,
132 const TopoDS_Face& ,
1155d05a 133 const TopTools_MapOfShape& ,
51db0179 134 BOPAlgo_ListOfEdgeInfo&,
135 const Handle(IntTools_Context)&);
c5face6f 136
137static
138 Standard_Boolean RefineAngle2D(const TopoDS_Vertex& ,
139 const TopoDS_Edge& ,
140 const TopoDS_Face& ,
141 const Standard_Real ,
142 const Standard_Real ,
24542bc0 143 const Standard_Real,
51db0179 144 Standard_Real& ,
145 const Handle(IntTools_Context)& );
c5face6f 146
4e57c75e 147//=======================================================================
148//function : SplitBlock
149//purpose :
150//=======================================================================
db8e4b9a 151void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
51db0179 152 BOPTools_ConnexityBlock& aCB,
153 const Handle(IntTools_Context)& theContext)
4e57c75e 154{
f56518cd 155 Standard_Boolean bNothingToDo, bIsClosed, bIsIN;
4e57c75e 156 Standard_Integer aIx, aNb, i, aCntIn, aCntOut;
157 Standard_Real aAngle;
158 TopAbs_Orientation aOr;
159 TopoDS_Iterator aItS;
160 TopoDS_Vertex aVV;
f56518cd 161 TopoDS_Shape aV1;
1155d05a 162 TopTools_ListIteratorOfListOfShape aIt;
4e57c75e 163 BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
164 //
db8e4b9a 165 BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo mySmartMap(100);
1155d05a 166 MyDataMapOfShapeBoolean aVertMap;
4e57c75e 167 //
1155d05a 168 const TopTools_ListOfShape& myEdges=aCB.Shapes();
4e57c75e 169 //
170 // 1.Filling mySmartMap
4e57c75e 171 aIt.Initialize(myEdges);
172 for(; aIt.More(); aIt.Next()) {
173 const TopoDS_Edge& aE=(*(TopoDS_Edge *)&aIt.Value());
174 if (!BOPTools_AlgoTools2D::HasCurveOnSurface (aE, myFace)) {
175 continue;
176 }
177 //
f56518cd 178 bIsClosed = BRep_Tool::Degenerated(aE) ||
179 BRep_Tool::IsClosed(aE, myFace);
180 //
4e57c75e 181 aItS.Initialize(aE);
f56518cd 182 for(i = 0; aItS.More(); aItS.Next(), ++i) {
183 const TopoDS_Shape& aV = aItS.Value();
184 aIx = mySmartMap.FindIndex(aV);
4e57c75e 185 if (!aIx) {
db8e4b9a 186 BOPAlgo_ListOfEdgeInfo aLEIx;
f56518cd 187 aIx = mySmartMap.Add(aV, aLEIx);
4e57c75e 188 }
189 //
f56518cd 190 BOPAlgo_ListOfEdgeInfo& aLEI = mySmartMap(aIx);
4e57c75e 191 BOPAlgo_EdgeInfo aEI;
192 //
193 aEI.SetEdge(aE);
f56518cd 194 aOr = aV.Orientation();
195 bIsIN = (aOr == TopAbs_REVERSED);
196 aEI.SetInFlag(bIsIN);
197 aLEI.Append(aEI);
198 //
199 if (!i) {
200 aV1 = aV;
201 } else {
202 bIsClosed = bIsClosed || aV1.IsSame(aV);
4e57c75e 203 }
f56518cd 204 //
205 if (aVertMap.IsBound(aV)) {
206 if (bIsClosed) {
207 aVertMap.ChangeFind(aV) = bIsClosed;
208 }
209 } else {
210 aVertMap.Bind(aV, bIsClosed);
4e57c75e 211 }
4e57c75e 212 }
213 }
214 //
215 aNb=mySmartMap.Extent();
216 //
217 bNothingToDo=Standard_True;
218 for (i=1; i<=aNb; i++) {
219 aCntIn=0;
220 aCntOut=0;
221 const BOPAlgo_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
222 BOPAlgo_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
223 for (; anIt.More(); anIt.Next()) {
224 const BOPAlgo_EdgeInfo& aEI=anIt.Value();
225 if (aEI.IsIn()) {
226 aCntIn++;
227 }
228 else {
229 aCntOut++;
230 }
231 }
232 if (aCntIn!=1 || aCntOut!=1) {
233 bNothingToDo=Standard_False;
234 break;
235 }
236 }
237 //
238 // Each vertex has one edge In and one - Out. Good. But it is not enought
239 // to consider that nothing to do with this. We must check edges on TShape
240 // coinsidence. If there are such edges there is something to do with.
241 if (bNothingToDo) {
242 Standard_Integer aNbE, aNbMapEE;
243 Standard_Boolean bFlag;
244 //
1155d05a 245 TopTools_IndexedDataMapOfShapeListOfShape aMapEE(100);
4e57c75e 246 aNbE=myEdges.Extent();
247 //
248 aIt.Initialize(myEdges);
249 for (; aIt.More(); aIt.Next()) {
250 const TopoDS_Shape& aE = aIt.Value();
251 if (!aMapEE.Contains(aE)) {
1155d05a 252 TopTools_ListOfShape aLEx;
4e57c75e 253 aLEx.Append(aE);
254 aMapEE.Add(aE, aLEx);
255 }
256 else {
1155d05a 257 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
4e57c75e 258 aLEx.Append(aE);
259 }
260 }
261 //
262 bFlag=Standard_True;
263 aNbMapEE=aMapEE.Extent();
264 for (i=1; i<=aNbMapEE; ++i) {
1155d05a 265 const TopTools_ListOfShape& aLEx=aMapEE(i);
4e57c75e 266 aNbE=aLEx.Extent();
267 if (aNbE==1) {// usual case
268 continue;
269 }
270 else if (aNbE==2){
271 const TopoDS_Shape& aE1=aLEx.First();
272 const TopoDS_Shape& aE2=aLEx.Last();
273 if (aE1.IsSame(aE2)) {
274 bFlag=Standard_False;
275 break;
276 }
277 }
278 else {
279 bFlag=Standard_False;
280 break;
281 }
282 }
283 bNothingToDo=bNothingToDo && bFlag;
284 } // if (bNothingToDo) {
285 if (bNothingToDo) {
286 TopoDS_Wire aW;
287 //
1155d05a 288 TopTools_ListOfShape& aLECB=aCB.ChangeShapes();
4e57c75e 289 BOPAlgo_WireSplitter::MakeWire(aLECB, aW);
1155d05a 290 TopTools_ListOfShape& aLoops=aCB.ChangeLoops();
4e57c75e 291 aLoops.Append(aW);
292 //
4e57c75e 293 return;
294 }
295 //
296 // 3. Angles in mySmartMap
51db0179 297 const BRepAdaptor_Surface& aBAS = theContext->SurfaceAdaptor(myFace);
4e57c75e 298 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
299 //
300 for (i=1; i<=aNb; i++) {
f56518cd 301 const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&mySmartMap.FindKey(i)));
4e57c75e 302 const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
4e57c75e 303 aItLEI.Initialize(aLEI);
304 for (; aItLEI.More(); aItLEI.Next()) {
305 BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
306 const TopoDS_Edge& aE=aEI.Edge();
307 //
f56518cd 308 aVV = aV;
309 bIsIN = aEI.IsIn();
310 aOr = bIsIN ? TopAbs_REVERSED : TopAbs_FORWARD;
311 aVV.Orientation(aOr);
51db0179 312 aAngle = Angle2D(aVV, aE, myFace, aGAS, bIsIN, theContext);
4e57c75e 313 aEI.SetAngle(aAngle);
314 }
315 }// for (i=1; i<=aNb; i++) {
316 //
c5face6f 317 //Theme: The treatment p-curves convergent in node.
318 //The refining the angles of p-curves taking into account
51db0179 319 //bounding curves if exist.
320 RefineAngles(myFace, myEdges, mySmartMap, theContext);
c5face6f 321 //
4e57c75e 322 // 4. Do
323 //
324 Standard_Boolean bIsOut, bIsNotPassed;
1155d05a 325 TopTools_SequenceOfShape aLS, aVertVa;
326 TColgp_SequenceOfPnt2d aCoordVa;
4e57c75e 327 //
328 for (i=1; i<=aNb; ++i) {
329 const TopoDS_Vertex& aVa=(*(TopoDS_Vertex *)(&mySmartMap.FindKey(i)));
330 const BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
331 aItLEI.Initialize(aLEI);
332 for (; aItLEI.More(); aItLEI.Next()) {
333 BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
334 const TopoDS_Edge& aEOuta=aEI.Edge();
335 //
336 bIsOut=!aEI.IsIn();
337 bIsNotPassed=!aEI.Passed();
338 if (bIsOut && bIsNotPassed) {
339 //
340 aLS.Clear();
341 aVertVa.Clear();
342 aCoordVa.Clear();
343 //
344 Path(aGAS, myFace, aVa, aEOuta, aEI, aLS,
f56518cd 345 aVertVa, aCoordVa, aCB, mySmartMap, aVertMap);
4e57c75e 346 }
347 }
348 }// for (i=1; i<=aNb; ++i) {
349}
350//=======================================================================
351// function: Path
352// purpose:
353//=======================================================================
354void Path (const GeomAdaptor_Surface& aGAS,
355 const TopoDS_Face& myFace,
b7357c8b 356 const TopoDS_Vertex& aVFirst,
357 const TopoDS_Edge& aEFirst,
358 BOPAlgo_EdgeInfo& aEIFirst,
1155d05a 359 TopTools_SequenceOfShape& aLS,
360 TopTools_SequenceOfShape& aVertVa,
361 TColgp_SequenceOfPnt2d& aCoordVa,
4e57c75e 362 BOPTools_ConnexityBlock& aCB,
f56518cd 363 BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
1155d05a 364 MyDataMapOfShapeBoolean aVertMap)
4e57c75e 365{
366 Standard_Integer i, j, aNb, aNbj;
ecba6de3 367 Standard_Real anAngleIn, anAngleOut, anAngle, aMinAngle;
368 Standard_Real aTol2D, aTol2D2, aD2, aTwoPI;
4e57c75e 369 Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
f56518cd 370 Standard_Boolean bIsClosed;
b7357c8b 371 TopoDS_Vertex aVa, aVb;
372 TopoDS_Edge aEOuta;
4e57c75e 373 BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
3ba87fdb 374 Standard_Real eps = Epsilon(1.);
4e57c75e 375 //
b7357c8b 376 aVa = aVFirst;
377 aEOuta = aEFirst;
378 BOPAlgo_EdgeInfo* anEdgeInfo = &aEIFirst;
379 //
b20eeb13 380 aTwoPI = M_PI + M_PI;
4e57c75e 381 //
382 // append block
383 //
b7357c8b 384 for (;;) {
385 // Do not escape through edge from which you enter
386 aNb=aLS.Length();
387 if (aNb==1) {
388 const TopoDS_Shape& anEPrev=aLS(aNb);
389 if (anEPrev.IsSame(aEOuta)) {
390 return;
391 }
4e57c75e 392 }
4e57c75e 393 //
b7357c8b 394 anEdgeInfo->SetPassed(Standard_True);
395 aLS.Append(aEOuta);
396 aVertVa.Append(aVa);
397
398 TopoDS_Vertex pVa=aVa;
399 pVa.Orientation(TopAbs_FORWARD);
400 gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
401 aCoordVa.Append(aPa);
402
403 GetNextVertex (pVa, aEOuta, aVb);
404
405 gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
406
ecba6de3 407 const BOPAlgo_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
4e57c75e 408 //
ecba6de3 409 aTol2D = 2.*Tolerance2D(aVb, aGAS);
410 aTol2D2 = aTol2D * aTol2D;
411 //
f56518cd 412 bIsClosed = aVertMap.Find(aVb);
24542bc0 413 {
1155d05a 414 TopTools_ListOfShape aBuf;
f80842e3 415 Standard_Boolean bHasEdge = Standard_False;
b7357c8b 416 //
24542bc0 417 aNb = aLS.Length();
418 for (i = aNb; i>0; --i) {
b7357c8b 419 const TopoDS_Shape& aVPrev=aVertVa(i);
420 const gp_Pnt2d& aPaPrev=aCoordVa(i);
f80842e3 421 const TopoDS_Edge& aEPrev = TopoDS::Edge(aLS(i));
422 //
b7357c8b 423 aBuf.Append(aEPrev);
f80842e3 424 if (!bHasEdge) {
425 bHasEdge = !BRep_Tool::Degenerated(aEPrev);
426 // do not create wire from degenerated edges only
427 if (!bHasEdge) {
428 continue;
429 }
430 }
431 //
ecba6de3 432 anIsSameV = aVPrev.IsSame(aVb);
433 anIsSameV2d = anIsSameV;
b7357c8b 434 if (anIsSameV) {
ecba6de3 435 if(bIsClosed) {
436 aD2 = aPaPrev.SquareDistance(aPb);
437 anIsSameV2d = aD2 < aTol2D2;
438 if (anIsSameV2d) {
439 Standard_Real udist = fabs(aPaPrev.X() - aPb.X());
440 Standard_Real vdist = fabs(aPaPrev.Y() - aPb.Y());
441 Standard_Real aTolU = 2.*UTolerance2D(aVb, aGAS);
442 Standard_Real aTolV = 2.*VTolerance2D(aVb, aGAS);
443 //
444 if((udist > aTolU) || (vdist > aTolV)) {
445 anIsSameV2d = Standard_False;
446 }
b7357c8b 447 }
448 }
449 }//if (anIsSameV) {
4e57c75e 450 //
b7357c8b 451 if (anIsSameV && anIsSameV2d) {
452 Standard_Integer iPriz;
453 iPriz=1;
454 if (aBuf.Extent()==2) {
455 if(aBuf.First().IsSame(aBuf.Last())) {
456 iPriz=0;
457 }
458 }
459 if (iPriz) {
460 TopoDS_Wire aW;
461 BOPAlgo_WireSplitter::MakeWire(aBuf, aW);
462 aCB.ChangeLoops().Append(aW);
463 }
4e57c75e 464 //
b7357c8b 465 aNbj=i-1;
466 if (aNbj<1) {
467 //
468 aLS.Clear();
469 aVertVa.Clear();
470 aCoordVa.Clear();
471 //
472 return;
4e57c75e 473 }
b7357c8b 474 //
1155d05a 475 TopTools_SequenceOfShape aLSt, aVertVat;
476 TColgp_SequenceOfPnt2d aCoordVat;
b7357c8b 477 //
478 aVb=(*(TopoDS_Vertex *)(&aVertVa(i)));
479 //
480 for (j=1; j<=aNbj; ++j) {
481 aLSt.Append(aLS(j));
482 aVertVat.Append(aVertVa(j));
483 aCoordVat.Append(aCoordVa(j));
4e57c75e 484 }
4e57c75e 485 //
486 aLS.Clear();
487 aVertVa.Clear();
488 aCoordVa.Clear();
b7357c8b 489
490 aLS=aLSt;
491 aVertVa=aVertVat;
492 aCoordVa=aCoordVat;
4e57c75e 493 //
b7357c8b 494 break;
4e57c75e 495 }
4e57c75e 496 }
497 }
b7357c8b 498 //
b7357c8b 499 // aEOutb
500 BOPAlgo_EdgeInfo *pEdgeInfo=NULL;
501 //
ecba6de3 502 anAngleIn = AngleIn(aEOuta, aLEInfo);
503 aMinAngle = 100.;
504 anIsFound = Standard_False;
24542bc0 505 Standard_Integer iCnt = NbWaysOut(aLEInfo);
b7357c8b 506 Standard_Integer aCurIndexE = 0;
507 anIt.Initialize(aLEInfo);
508 for (; anIt.More(); anIt.Next()) {
509 BOPAlgo_EdgeInfo& anEI=anIt.ChangeValue();
510 const TopoDS_Edge& aE=anEI.Edge();
511 anIsOut=!anEI.IsIn();
512 anIsNotPassed=!anEI.Passed();
f56518cd 513 //
b7357c8b 514 if (anIsOut && anIsNotPassed) {
515 aCurIndexE++;
b20eeb13 516 //
b7357c8b 517 // Is there one way to go out of the vertex
518 // we have to use it only.
b20eeb13 519 //
b7357c8b 520 if (!iCnt) {
521 // no way to go . (Error)
522 return;
4e57c75e 523 }
b20eeb13 524 //
b7357c8b 525 if (iCnt==1) {
526 // the one and only way to go out .
527 pEdgeInfo=&anEI;
528 anIsFound=Standard_True;
529 break;
530 }
b20eeb13 531 //
b7357c8b 532 if (aE.IsSame(aEOuta)) {
533 anAngle = aTwoPI;
534 } else {
ecba6de3 535 //check 2d distance
536 if (bIsClosed) {
537 gp_Pnt2d aP2Dx;
538 //
539 aP2Dx = Coord2dVf(aE, myFace);
540 //
541 aD2 = aP2Dx.SquareDistance(aPb);
542 if (aD2 > aTol2D2){
543 continue;
544 }
b20eeb13 545 }
b7357c8b 546 //
ecba6de3 547 // Look for minimal angle and make the choice.
b7357c8b 548 anAngleOut=anEI.Angle();
b7357c8b 549 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
550 }
3ba87fdb 551 if (anAngle < aMinAngle - eps) {
b7357c8b 552 aMinAngle=anAngle;
553 pEdgeInfo=&anEI;
554 anIsFound=Standard_True;
b20eeb13 555 }
4e57c75e 556 }
b7357c8b 557 } // for (; anIt.More(); anIt.Next())
558 //
559 if (!anIsFound) {
560 // no way to go . (Error)
561 return;
4e57c75e 562 }
b7357c8b 563 //
564 aVa = aVb;
565 aEOuta = pEdgeInfo->Edge();
566 anEdgeInfo = pEdgeInfo;
4e57c75e 567 }
4e57c75e 568}
569//=======================================================================
570// function: ClockWiseAngle
571// purpose:
572//=======================================================================
573 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
574 const Standard_Real aAngleOut)
575{
576 Standard_Real aTwoPi=M_PI+M_PI;
577 Standard_Real dA, A1, A2, AIn, AOut ;
578
579 AIn=aAngleIn;
580 AOut=aAngleOut;
581 if (AIn >= aTwoPi) {
582 AIn=AIn-aTwoPi;
583 }
584
585 if (AOut >= aTwoPi) {
586 AOut=AOut-aTwoPi;
587 }
588
589 A1=AIn+M_PI;
590
591 if (A1 >= aTwoPi) {
592 A1=A1-aTwoPi;
593 }
594
595 A2=AOut;
596
597 dA=A1-A2;
598 if (dA <= 0.) {
599 dA=aTwoPi+dA;
600 }
601 //xx
602 //else if (dA <= 1.e-15) {
603 else if (dA <= 1.e-14) {
604 dA=aTwoPi;
605 }
606 return dA;
607}
608//=======================================================================
609// function: Coord2d
610// purpose:
611//=======================================================================
612 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
613 const TopoDS_Edge& aE1,
614 const TopoDS_Face& aF)
615{
616 Standard_Real aT, aFirst, aLast;
617 Handle(Geom2d_Curve) aC2D;
618 gp_Pnt2d aP2D1;
619 //
620 aT=BRep_Tool::Parameter (aV1, aE1, aF);
621 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
622 aC2D->D0 (aT, aP2D1);
623 //
624 return aP2D1;
625}
626//=======================================================================
627// function: Coord2dVf
628// purpose:
629//=======================================================================
630 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
631 const TopoDS_Face& aF)
632{
633 Standard_Real aCoord=99.;
634 gp_Pnt2d aP2D1(aCoord, aCoord);
635 TopoDS_Iterator aIt;
636 //
637 aIt.Initialize(aE);
638 for (; aIt.More(); aIt.Next()) {
639 const TopoDS_Shape& aVx=aIt.Value();
640 if (aVx.Orientation()==TopAbs_FORWARD) {
641
642 const TopoDS_Vertex& aVxx=(*(TopoDS_Vertex *)(&aVx));// TopoDS::Vertex(aVx);
643 aP2D1=Coord2d(aVxx, aE, aF);
644 return aP2D1;
645 }
646 }
647 return aP2D1;
648}
649
650//=======================================================================
651// function: NbWaysOut
652// purpose:
653//=======================================================================
654Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
655{
656 Standard_Boolean bIsOut, bIsNotPassed;
657 Standard_Integer iCnt=0;
658 BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
659 //
660 anIt.Initialize(aLEInfo);
661 for (; anIt.More(); anIt.Next()) {
662 const BOPAlgo_EdgeInfo& anEI=anIt.Value();
663 //
664 bIsOut=!anEI.IsIn();
665 bIsNotPassed=!anEI.Passed();
666 if (bIsOut && bIsNotPassed) {
667 iCnt++;
668 }
669 }
670 return iCnt;
671}
672
673//=======================================================================
674// function: AngleIn
675// purpose:
676//=======================================================================
677 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
678 const BOPAlgo_ListOfEdgeInfo& aLEInfo)
679{
680 Standard_Real anAngleIn;
681 Standard_Boolean anIsIn;
682 BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
683
684 anIt.Initialize(aLEInfo);
685 for (; anIt.More(); anIt.Next()) {
686 const BOPAlgo_EdgeInfo& anEdgeInfo=anIt.Value();
687 const TopoDS_Edge& aE=anEdgeInfo.Edge();
688 anIsIn=anEdgeInfo.IsIn();
689 //
690 if (anIsIn && aE==aEIn) {
691 anAngleIn=anEdgeInfo.Angle();
692 return anAngleIn;
693 }
694 }
695 anAngleIn=0.;
696 return anAngleIn;
697}
698//=======================================================================
699// function: GetNextVertex
700// purpose:
701//=======================================================================
702 void GetNextVertex(const TopoDS_Vertex& aV,
703 const TopoDS_Edge& aE,
704 TopoDS_Vertex& aV1)
705{
706 TopoDS_Iterator aIt;
707 //
708 aIt.Initialize(aE);
709 for (; aIt.More(); aIt.Next()) {
710 const TopoDS_Shape& aVx=aIt.Value();
711 if (!aVx.IsEqual(aV)) {
712 aV1=(*(TopoDS_Vertex *)(&aVx));
713 return ;
714 }
715 }
716 aV1=aV;
717}
718//=======================================================================
719// function: Angle2D
720// purpose:
721//=======================================================================
722 Standard_Real Angle2D (const TopoDS_Vertex& aV,
723 const TopoDS_Edge& anEdge,
724 const TopoDS_Face& myFace,
725 const GeomAdaptor_Surface& aGAS,
51db0179 726 const Standard_Boolean bIsIN,
727 const Handle(IntTools_Context)& theContext)
4e57c75e 728{
729 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
730 gp_Pnt2d aPV, aPV1;
731 gp_Vec2d aV2D;
732 Handle(Geom2d_Curve) aC2D;
733 //
734 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
735 if (Precision::IsInfinite(aTV)) {
736 return 0.;
737 }
738 //
739 BOPTools_AlgoTools2D::CurveOnSurface (anEdge, myFace, aC2D,
51db0179 740 aFirst, aLast, aToler, theContext);
3ba87fdb 741 Standard_Real tol2d =2.*Tolerance2D(aV, aGAS);
742 //
743 GeomAbs_CurveType aType;
744 Geom2dAdaptor_Curve aGAC2D(aC2D);
745 //
746 dt = Max(aGAC2D.Resolution(tol2d), Precision::PConfusion());
4e57c75e 747 //
3ba87fdb 748 aType=aGAC2D.GetType();
749 if (aType != GeomAbs_Line )
750 {
751 Geom2dLProp_CLProps2d LProp(aC2D, aTV, 2, Precision::PConfusion());
752 if(LProp.IsTangentDefined())
753 {
754 Standard_Real R = LProp.Curvature();
755 if(R > Precision::PConfusion())
756 {
757 R = 1./R;
758 Standard_Real cosphi = R / (R + tol2d);
759 dt = Max(dt, ACos(cosphi)); //to avoid small dt for big R.
760 }
761 }
762 }
4e57c75e 763 //for case chl/927/r9
3ba87fdb 764 aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
4e57c75e 765 if (aTX < 5.e-5) {
766 aTX = 5.e-5;
767 }
768 if(dt > aTX) {
769 // to save direction of the curve as much as it possible
770 // in the case of big tolerances
771 dt = aTX;
772 }
3ba87fdb 773
4e57c75e 774 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
775 aTV1=aTV + dt;
776 }
777 else {
778 aTV1=aTV - dt;
779 }
780 //
3ba87fdb 781 aGAC2D.D0 (aTV1, aPV1);
782 aGAC2D.D0 (aTV, aPV);
783 //
784 aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
4e57c75e 785 //
786 gp_Dir2d aDir2D(aV2D);
787 anAngle=Angle(aDir2D);
788 //
789 return anAngle;
790}
791//=======================================================================
792// function: Angle
793// purpose:
794//=======================================================================
795Standard_Real Angle (const gp_Dir2d& aDir2D)
796{
797 gp_Dir2d aRefDir(1., 0.);
798 Standard_Real anAngle;
799
800 anAngle = aRefDir.Angle(aDir2D);
801 if (anAngle < 0.)
802 anAngle += M_PI + M_PI;
803 return anAngle;
804}
805//=======================================================================
806// function: Tolerance2D
807// purpose:
808//=======================================================================
809 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
810 const GeomAdaptor_Surface& aGAS)
811{
812 Standard_Real aTol2D, anUr, aVr, aTolV3D;
813 GeomAbs_SurfaceType aType;
814 //
815 aType=aGAS.GetType();
816 aTolV3D=BRep_Tool::Tolerance(aV);
817
818 anUr=aGAS.UResolution(aTolV3D);
819 aVr =aGAS.VResolution(aTolV3D);
820 aTol2D=(aVr>anUr) ? aVr : anUr;
821 //
822 if (aTol2D < aTolV3D) {
823 aTol2D=aTolV3D;
824 }
825 if (aType==GeomAbs_BSplineSurface) {
826 aTol2D=1.1*aTol2D;
827 }
828 //
829 return aTol2D;
830}
acccace3 831
4e57c75e 832//=======================================================================
833//function : UTolerance2D
834//purpose :
835//=======================================================================
836Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
837 const GeomAdaptor_Surface& aGAS)
838{
839 const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
840 const Standard_Real anUr = aGAS.UResolution(aTolV3D);
841 //
842 return anUr;
843}
844
845//=======================================================================
846//function : VTolerance2D
847//purpose :
848//=======================================================================
849Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
850 const GeomAdaptor_Surface& aGAS)
851{
852 const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
853 const Standard_Real anVr = aGAS.VResolution(aTolV3D);
854 //
855 return anVr;
856}
857
c5face6f 858//=======================================================================
859//function : RefineAngles
860//purpose :
861//=======================================================================
862void RefineAngles(const TopoDS_Face& myFace,
1155d05a 863 const TopTools_ListOfShape& myEdges,
51db0179 864 BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
865 const Handle(IntTools_Context)& theContext)
c5face6f 866{
867 Standard_Integer aNb, i;
1155d05a 868 NCollection_IndexedDataMap<TopoDS_Shape,
869 Standard_Integer,
870 TopTools_ShapeMapHasher> aMSI;
871 TopTools_MapOfShape aMBE;
872 TopTools_ListIteratorOfListOfShape aIt;
c5face6f 873 //
874 // 1. Boundary Edges
875 aIt.Initialize(myEdges);
876 for(; aIt.More(); aIt.Next()) {
877 const TopoDS_Shape& aE=aIt.Value();
319da2e4 878 if(aMSI.Contains(aE)) {
879 Standard_Integer& iCnt = aMSI.ChangeFromKey(aE);
c5face6f 880 ++iCnt;
881 }
882 else {
319da2e4 883 Standard_Integer iCnt = 1;
884 aMSI.Add(aE, iCnt);
c5face6f 885 }
886 }
887 //
319da2e4 888 aNb = aMSI.Extent();
889 for (i = 1; i <= aNb; ++i) {
890 Standard_Integer iCnt = aMSI(i);
891 if (iCnt == 1) {
892 const TopoDS_Shape& aE = aMSI.FindKey(i);
c5face6f 893 aMBE.Add(aE);
894 }
c5face6f 895 }
896 //
897 aMSI.Clear();
898 //
319da2e4 899 aNb = mySmartMap.Extent();
900 for (i = 1; i <= aNb; ++i) {
c5face6f 901 const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&mySmartMap.FindKey(i));
902 BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
903 //
51db0179 904 RefineAngles(aV, myFace, aMBE, aLEI, theContext);
c5face6f 905 }
906}
907//=======================================================================
908typedef NCollection_DataMap \
909 <TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> \
1155d05a 910 TopTools_DataMapOfShapeReal;
911typedef TopTools_DataMapOfShapeReal::Iterator \
912 TopTools_DataMapIteratorOfDataMapOfShapeReal;
c5face6f 913//
914//=======================================================================
915//function : RefineAngles
916//purpose :
917//=======================================================================
918void RefineAngles(const TopoDS_Vertex& aV,
919 const TopoDS_Face& myFace,
1155d05a 920 const TopTools_MapOfShape& aMBE,
51db0179 921 BOPAlgo_ListOfEdgeInfo& aLEI,
922 const Handle(IntTools_Context)& theContext)
c5face6f 923{
924 Standard_Boolean bIsIn, bIsBoundary, bRefined;
f56518cd 925 Standard_Integer iCntBnd, iCntInt;
c5face6f 926 Standard_Real aA, aA1, aA2;
1155d05a 927 TopTools_DataMapOfShapeReal aDMSR;
c5face6f 928 BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
929 //
24542bc0 930 aA1=0.; // angle of outgoing edge
931 aA2=0.; // angle of incoming edge
f56518cd 932 iCntBnd=0;
933 iCntInt=0;
c5face6f 934 aItLEI.Initialize(aLEI);
935 for (; aItLEI.More(); aItLEI.Next()) {
936 BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
937 const TopoDS_Edge& aE=aEI.Edge();
938 bIsIn=aEI.IsIn();
939 aA=aEI.Angle();
940 //
941 if (aMBE.Contains(aE)) {
f56518cd 942 ++iCntBnd;
c5face6f 943 if (!bIsIn) {
944 aA1=aA;
945 }
946 else {
24542bc0 947 aA2=aA;
c5face6f 948 }
949 }
f56518cd 950 else {
951 ++iCntInt;
952 }
c5face6f 953 }
954 //
f56518cd 955 if (iCntBnd!=2) {
c5face6f 956 return;
957 }
958 //
24542bc0 959 Standard_Real aDelta = ClockWiseAngle(aA2, aA1);
c5face6f 960 aItLEI.Initialize(aLEI);
961 for (; aItLEI.More(); aItLEI.Next()) {
962 BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
963 const TopoDS_Edge& aE=aEI.Edge();
964 //
965 bIsBoundary=aMBE.Contains(aE);
966 bIsIn=aEI.IsIn();
967 if (bIsBoundary || bIsIn) {
968 continue;
969 }
970 //
971 aA=aEI.Angle();
24542bc0 972 Standard_Real aDA = ClockWiseAngle(aA2, aA);
973 if (aDA < aDelta) {
974 continue; // already inside
c5face6f 975 }
976 //
24542bc0 977 bRefined=RefineAngle2D(aV, aE, myFace, aA1, aA2, aDelta, aA, theContext);
c5face6f 978 if (bRefined) {
979 aDMSR.Bind(aE, aA);
980 }
f56518cd 981 else if (iCntInt == 2) {
982 aA = (aA <= aA1) ? (aA1 + Precision::Angular()) :
983 (aA2 - Precision::Angular());
984 aDMSR.Bind(aE, aA);
985 }
c5face6f 986 }
987
988 if (aDMSR.IsEmpty()) {
989 return;
990 }
991 //
992 // update Angles
993 aItLEI.Initialize(aLEI);
994 for (; aItLEI.More(); aItLEI.Next()) {
995 BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
996 const TopoDS_Edge& aE=aEI.Edge();
997 //
998 bIsIn=aEI.IsIn();
999 if (!aDMSR.IsBound(aE)) {
1000 continue;
1001 }
1002 //
1003 aA=aDMSR.Find(aE);
1004 if (bIsIn) {
1005 aA=aA+M_PI;
1006 }
1007 //
1008 aEI.SetAngle(aA);
1009 }
1010}
1011//=======================================================================
1012//function : RefineAngle2D
1013//purpose :
1014//=======================================================================
1015Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
1016 const TopoDS_Edge& aE,
1017 const TopoDS_Face& myFace,
1018 const Standard_Real aA1,
1019 const Standard_Real aA2,
24542bc0 1020 const Standard_Real aDelta,
51db0179 1021 Standard_Real& aA,
1022 const Handle(IntTools_Context)& theContext)
c5face6f 1023{
1024 Standard_Boolean bRet;
f56518cd 1025 Standard_Integer i, j, aNbP;
1026 Standard_Real aTV, aTol, aT1, aT2, dT, aAngle, aT, aTOp;
c5face6f 1027 Standard_Real aTolInt, aAi, aXi, aYi, aT1j, aT2j, aT1max, aT2max, aCf;
1028 gp_Pnt2d aPV, aP, aP1, aP2;
1029 Handle(Geom2d_Curve) aC2D;
1030 Handle(Geom2d_Line) aLi;
1031 Geom2dAdaptor_Curve aGAC1, aGAC2;
1032 Geom2dInt_GInter aGInter;
1033 IntRes2d_Domain aDomain1, aDomain2;
1034 //
1035 bRet=Standard_True;
1036 aCf=0.01;
1037 aTolInt=1.e-10;
1038 //
51db0179 1039 BOPTools_AlgoTools2D::CurveOnSurface(aE, myFace, aC2D, aT1, aT2, aTol, theContext);
94f71cad 1040 aGAC1.Load(aC2D, aT1, aT2);
c5face6f 1041 //
1042 aTV=BRep_Tool::Parameter (aV, aE, myFace);
94f71cad 1043 aGAC1.D0(aTV, aPV);
c5face6f 1044 //
f56518cd 1045 aTOp = (fabs(aTV-aT1) < fabs(aTV-aT2)) ? aT2 : aT1;
c5face6f 1046 //
24542bc0 1047 const Standard_Real MaxDT = 0.3 * (aT2 - aT1);
94f71cad 1048 aGAC1.D0(aT1, aP1);
1049 aGAC1.D0(aT2, aP2);
c5face6f 1050 aDomain1.SetValues(aP1, aT1, aTolInt, aP2, aT2, aTolInt);
1051 //
1052 for (i=0; i<2; ++i) {
24542bc0 1053 aAi=(!i) ? aA1 : (aA2 + M_PI);
c5face6f 1054 aXi=cos(aAi);
1055 aYi=sin(aAi);
1056 gp_Dir2d aDiri(aXi, aYi);
1057 aLi=new Geom2d_Line(aPV, aDiri);
1058 //
1059 aGAC2.Load(aLi);
c5face6f 1060 //
1061 aGInter.Perform(aGAC1, aDomain1, aGAC2, aDomain2, aTolInt, aTolInt);
1062 if (!aGInter.IsDone()) {
1063 continue;
1064 }
1065 //
24542bc0 1066 aNbP = aGInter.NbPoints();
1067 aT1max = aTV;
1068 aT2max = -1.;
1069 for (j = 1; j <= aNbP; ++j) {
1070 const IntRes2d_IntersectionPoint& aIPj = aGInter.Point(j);
1071 aT1j = aIPj.ParamOnFirst();
1072 aT2j = aIPj.ParamOnSecond();
c5face6f 1073 //
24542bc0 1074 if (aT2j > aT2max && Abs(aT1j - aTV) < MaxDT) {
1075 aT2max = aT2j;
1076 aT1max = aT1j;
c5face6f 1077 }
1078 }
1079 //
24542bc0 1080 if (aT2max > 0) {
1081 dT = aTOp - aT1max;
1082 if (Abs(dT) < aTolInt) {
1083 continue;
1084 }
1085 //
1086 aT = aT1max + aCf*dT;
1087 aGAC1.D0(aT, aP);
1088 gp_Vec2d aV2D(aPV, aP);
1089 gp_Dir2d aDir2D(aV2D);
1090 //
1091 aAngle = Angle(aDir2D);
1092 Standard_Real aDA = ClockWiseAngle(aA2, aAngle);
1093 if (aDA < aDelta) {
1094 aA = aAngle;
1095 return bRet;
1096 }
c5face6f 1097 }
1098 }// for (i=0; i<2; ++i) {
1099 return !bRet;
24542bc0 1100}