1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <Bnd_Box.hxx>
17 #include <BndLib_Add3dCurve.hxx>
18 #include <TColStd_MapOfInteger.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Curve.hxx>
22 #include <Geom_BezierCurve.hxx>
23 #include <Geom_BSplineCurve.hxx>
24 #include <Geom_Line.hxx>
25 #include <Geom_Circle.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Ellipse.hxx>
28 #include <Geom_OffsetCurve.hxx>
29 #include <GeomAPI_ProjectPointOnCurve.hxx>
32 #include <IntTools_CommonPrt.hxx>
33 #include <IntTools_EdgeEdge.hxx>
34 #include <IntTools_Range.hxx>
35 #include <IntTools_Tools.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <BRepExtrema_DistShapeShape.hxx>
41 void BndBuildBox(const BRepAdaptor_Curve& theBAC,
42 const Standard_Real aT1,
43 const Standard_Real aT2,
44 const Standard_Real theTol,
47 Standard_Real PointBoxDistance(const Bnd_Box& aB,
50 Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
51 const Standard_Real aT2,
52 const Standard_Real theResolution,
53 const Standard_Integer theNbSeg,
54 IntTools_SequenceOfRanges& theSegments);
56 Standard_Integer DistPC(const Standard_Real aT1,
57 const Handle(Geom_Curve)& theC1,
58 const Standard_Real theCriteria,
59 GeomAPI_ProjectPointOnCurve& theProjector,
62 const Standard_Integer iC = 1);
64 Standard_Integer DistPC(const Standard_Real aT1,
65 const Handle(Geom_Curve)& theC1,
66 const Standard_Real theCriteria,
67 GeomAPI_ProjectPointOnCurve& theProjector,
71 Standard_Real& aT1max,
72 Standard_Real& aT2max,
73 const Standard_Integer iC = 1);
75 Standard_Integer FindDistPC(const Standard_Real aT1A,
76 const Standard_Real aT1B,
77 const Handle(Geom_Curve)& theC1,
78 const Standard_Real theCriteria,
79 const Standard_Real theEps,
80 GeomAPI_ProjectPointOnCurve& theProjector,
82 Standard_Real& aT1max,
83 Standard_Real& aT2max,
84 const Standard_Boolean bMaxDist = Standard_True);
86 Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
87 const IntTools_Range& theRange);
89 Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
90 const GeomAbs_CurveType theCurveType,
91 const Standard_Real theResCoeff,
92 const Standard_Real theR3D);
94 Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
95 const IntTools_Range& theRange);
97 Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
98 const Standard_Real aT1,
99 const Standard_Real aT2,
100 const Standard_Real theTol,
101 const Standard_Real theRes);
103 Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType);
105 //=======================================================================
108 //=======================================================================
109 void IntTools_EdgeEdge::Prepare()
111 GeomAbs_CurveType aCT1, aCT2;
112 Standard_Integer iCT1, iCT2;
114 myCurve1.Initialize(myEdge1);
115 myCurve2.Initialize(myEdge2);
117 if (myRange1.First() == 0. && myRange1.Last() == 0.) {
118 myRange1.SetFirst(myCurve1.FirstParameter());
119 myRange1.SetLast (myCurve1.LastParameter());
122 if (myRange2.First() == 0. && myRange2.Last() == 0.) {
123 myRange2.SetFirst(myCurve2.FirstParameter());
124 myRange2.SetLast (myCurve2.LastParameter());
127 aCT1 = myCurve1.GetType();
128 aCT2 = myCurve2.GetType();
130 iCT1 = TypeToInteger(aCT1);
131 iCT2 = TypeToInteger(aCT2);
136 Standard_Real aC1, aC2;
138 aC2 = CurveDeflection(myCurve2, myRange2);
139 aC1 = (aC2 > Precision::Confusion()) ?
140 CurveDeflection(myCurve1, myRange1) : 1.;
149 TopoDS_Edge tmpE = myEdge1;
153 BRepAdaptor_Curve tmpC = myCurve1;
157 IntTools_Range tmpR = myRange1;
161 mySwap = Standard_True;
164 Standard_Real aTolAdd = myFuzzyValue / 2.;
165 myTol1 = myCurve1.Tolerance() + aTolAdd;
166 myTol2 = myCurve2.Tolerance() + aTolAdd;
167 myTol = myTol1 + myTol2;
169 if (iCT1 != 0 || iCT2 != 0) {
170 Standard_Real f, l, aTM;
172 myGeom1 = BRep_Tool::Curve(myEdge1, f, l);
173 myGeom2 = BRep_Tool::Curve(myEdge2, f, l);
175 myResCoeff1 = ResolutionCoeff(myCurve1, myRange1);
176 myResCoeff2 = ResolutionCoeff(myCurve2, myRange2);
178 myRes1 = Resolution(myCurve1.Curve().Curve(), myCurve1.GetType(), myResCoeff1, myTol1);
179 myRes2 = Resolution(myCurve2.Curve().Curve(), myCurve2.GetType(), myResCoeff2, myTol2);
182 aTM = Max(fabs(myRange1.First()), fabs(myRange1.Last()));
184 myPTol1 = 5.e-16 * aTM;
188 aTM = Max(fabs(myRange2.First()), fabs(myRange2.Last()));
190 myPTol2 = 5.e-16 * aTM;
195 //=======================================================================
198 //=======================================================================
199 void IntTools_EdgeEdge::Perform()
210 //3.1. Check Line/Line case
211 if (myCurve1.GetType() == GeomAbs_Line &&
212 myCurve2.GetType() == GeomAbs_Line) {
217 if (myQuickCoincidenceCheck) {
218 if (IsCoincident()) {
219 Standard_Real aT11, aT12, aT21, aT22;
221 myRange1.Range(aT11, aT12);
222 myRange2.Range(aT21, aT22);
223 AddSolution(aT11, aT12, aT21, aT22, TopAbs_EDGE);
228 if ((myCurve1.GetType() <= GeomAbs_Parabola && myCurve2.GetType() <= GeomAbs_Parabola) &&
229 (myCurve1.GetType() == GeomAbs_Line || myCurve2.GetType() == GeomAbs_Line))
231 //Improvement of performance for cases of searching common parts between line
232 //and analytical curve. This code allows to define that edges have no
233 //common parts more fast, then regular algorithm (FindSolution(...))
234 //Check minimal distance between edges
235 BRepExtrema_DistShapeShape aMinDist(myEdge1, myEdge2, Extrema_ExtFlag_MIN);
236 if (aMinDist.IsDone())
238 Standard_Real d = aMinDist.Value();
246 IntTools_SequenceOfRanges aRanges1, aRanges2;
248 //3.2. Find ranges containig solutions
249 Standard_Boolean bSplit2;
250 FindSolutions(aRanges1, aRanges2, bSplit2);
252 //4. Merge solutions and save common parts
253 MergeSolutions(aRanges1, aRanges2, bSplit2);
256 //=======================================================================
257 //function : IsCoincident
259 //=======================================================================
260 Standard_Boolean IntTools_EdgeEdge::IsCoincident()
262 Standard_Integer i, iCnt, aNbSeg, aNbP2;
263 Standard_Real dT, aT1, aCoeff, aTresh, aD;
264 Standard_Real aT11, aT12, aT21, aT22;
265 GeomAPI_ProjectPointOnCurve aProjPC;
270 myRange1.Range(aT11, aT12);
271 myRange2.Range(aT21, aT22);
273 aProjPC.Init(myGeom2, aT21, aT22);
275 dT=(aT12-aT11)/aNbSeg;
278 for(i=0; i <= aNbSeg; ++i) {
280 myGeom1->D0(aT1, aP1);
282 aProjPC.Perform(aP1);
283 aNbP2=aProjPC.NbPoints();
288 aD=aProjPC.LowerDistance();
294 aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
295 return aCoeff > aTresh;
297 //=======================================================================
298 //function : FindSolutions
300 //=======================================================================
301 void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
302 IntTools_SequenceOfRanges& theRanges2,
303 Standard_Boolean& bSplit2)
305 Standard_Boolean bIsClosed2;
306 Standard_Real aT11, aT12, aT21, aT22;
309 bSplit2 = Standard_False;
310 myRange1.Range(aT11, aT12);
311 myRange2.Range(aT21, aT22);
313 bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2);
316 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
318 gp_Pnt aP = myGeom2->Value(aT21);
319 bIsClosed2 = !aB1.IsOut(aP);
323 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
324 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
325 FindSolutions(myRange1, aB1, myRange2, aB2, theRanges1, theRanges2);
329 if (!CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1)) {
330 theRanges1.Append(myRange1);
331 theRanges2.Append(myRange2);
335 Standard_Integer i, j, aNb1, aNb2;
336 IntTools_SequenceOfRanges aSegments1, aSegments2;
338 aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1;
341 aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
342 aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
344 for (i = 1; i <= aNb1; ++i) {
345 const IntTools_Range& aR1 = aSegments1(i);
346 BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1);
347 for (j = 1; j <= aNb2; ++j) {
348 const IntTools_Range& aR2 = aSegments2(j);
349 BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2);
350 FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2);
357 //=======================================================================
358 //function : FindSolutions
360 //=======================================================================
361 void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
362 const Bnd_Box& theBox1,
363 const IntTools_Range& theR2,
364 const Bnd_Box& theBox2,
365 IntTools_SequenceOfRanges& theRanges1,
366 IntTools_SequenceOfRanges& theRanges2)
368 Standard_Boolean bOut, bStop, bThin;
369 Standard_Real aT11, aT12, aT21, aT22;
370 Standard_Real aTB11, aTB12, aTB21, aTB22;
371 Standard_Real aSmallStep1, aSmallStep2;
372 Standard_Integer iCom;
375 theR1.Range(aT11, aT12);
376 theR2.Range(aT21, aT22);
381 bThin = Standard_False;
382 bStop = Standard_False;
391 //1. Find parameters of the second edge in the box of first one
392 bOut = aB1.IsOut(aB2);
397 bThin = ((aT12 - aT11) < myRes1) ||
398 (aB1.IsXThin(myTol) && aB1.IsYThin(myTol) && aB1.IsZThin(myTol));
400 bOut = !FindParameters(myCurve2, aTB21, aTB22, myTol2, myRes2, myPTol2,
401 myResCoeff2, aB1, aT21, aT22);
406 //2. Build box for second edge and find parameters
407 // of the first one in that box
408 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
409 bOut = aB1.IsOut(aB2);
414 bThin = ((aT22 - aT21) < myRes2) ||
415 (aB2.IsXThin(myTol) && aB2.IsYThin(myTol) && aB2.IsZThin(myTol));
417 bOut = !FindParameters(myCurve1, aTB11, aTB12, myTol1, myRes1, myPTol1,
418 myResCoeff1, aB2, aT11, aT12);
424 //3. Check if it makes sense to continue
425 aSmallStep1 = (aTB12 - aTB11) / 250.;
426 aSmallStep2 = (aTB22 - aTB21) / 250.;
428 if (aSmallStep1 < myRes1) {
429 aSmallStep1 = myRes1;
431 if (aSmallStep2 < myRes2) {
432 aSmallStep2 = myRes2;
435 if (((aT11 - aTB11) < aSmallStep1) && ((aTB12 - aT12) < aSmallStep1) &&
436 ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) {
437 bStop = Standard_True;
440 BndBuildBox (myCurve1, aT11, aT12, myTol1, aB1);
450 //check curves for coincidence on the ranges
451 iCom = CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1);
453 bThin = Standard_True;
459 //check intermediate points
460 Standard_Boolean bSol;
463 GeomAPI_ProjectPointOnCurve aProjPC;
465 aT1 = (aT11 + aT12) * .5;
466 myGeom1->D0(aT1, aP1);
468 aProjPC.Init(myGeom2, aT21, aT22);
469 aProjPC.Perform(aP1);
471 if (aProjPC.NbPoints()) {
472 bSol = aProjPC.LowerDistance() <= myTol;
478 aT2 = (aT21 + aT22) * .5;
479 myGeom2->D0(aT2, aP2);
481 bSol = aP1.IsEqual(aP2, myTol);
489 IntTools_Range aR1(aT11, aT12), aR2(aT21, aT22);
491 theRanges1.Append(aR1);
492 theRanges2.Append(aR2);
496 if (!IsIntersection(aT11, aT12, aT21, aT22)) {
500 //split ranges on segments and repeat
501 Standard_Integer i, aNb1;
502 IntTools_SequenceOfRanges aSegments1;
504 // Build box for first curve to compare
505 // the boxes of the splits with this one
506 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
507 const Standard_Real aB1SqExtent = aB1.SquareExtent();
509 IntTools_Range aR2(aT21, aT22);
510 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
512 aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
513 for (i = 1; i <= aNb1; ++i) {
514 const IntTools_Range& aR1 = aSegments1(i);
515 BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1);
516 if (!aB1.IsOut(aB2) && (aNb1 == 1 || aB1.SquareExtent() < aB1SqExtent))
517 FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2);
521 //=======================================================================
522 //function : FindParameters
524 //=======================================================================
525 Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theBAC,
526 const Standard_Real aT1,
527 const Standard_Real aT2,
528 const Standard_Real theTol,
529 const Standard_Real theRes,
530 const Standard_Real thePTol,
531 const Standard_Real theResCoeff,
532 const Bnd_Box& theCBox,
536 Standard_Boolean bRet;
537 Standard_Integer aC, i;
538 Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn;
539 Standard_Real aDist, aDistP;
543 bRet = Standard_False;
544 aCf = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))/2.;
546 aCBx.SetGap(aCBx.GetGap() + theTol);
548 const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
549 const GeomAbs_CurveType aCurveType = theBAC.GetType();
550 Standard_Real aMaxDt = (aT2 - aT1) * 0.01;
552 for (i = 0; i < 2; ++i) {
553 aTB = !i ? aT1 : aT2;
554 aT = !i ? aT2 : aTB1;
558 bRet = Standard_False;
560 //looking for the point on the edge which is in the box;
561 while (aC*(aT-aTB) >= 0) {
563 aDist = PointBoxDistance(theCBox, aP);
564 if (aDist > theTol) {
566 Standard_Boolean toGrow = Standard_False;
567 if (Abs(aDistP - aDist) / aDistP < 0.1) {
568 aDt = Resolution(aCurve, aCurveType, theResCoeff, k*aDist);
571 toGrow = Standard_True;
577 aDt = Resolution(aCurve, aCurveType, theResCoeff, aDist);
582 bRet = Standard_True;
590 //edge is out of the box;
601 //one point IN, one point OUT; looking for the bounding point;
603 aTOut = aTB - aC*aDt;
604 aDiff = aTIn - aTOut;
605 while (fabs(aDiff) > thePTol) {
606 aTB = aTOut + aDiff*aCf;
608 if (aCBx.IsOut(aP)) {
613 aDiff = aTIn - aTOut;
625 //=======================================================================
626 //function : MergeSolutions
628 //=======================================================================
629 void IntTools_EdgeEdge::MergeSolutions(const IntTools_SequenceOfRanges& theRanges1,
630 const IntTools_SequenceOfRanges& theRanges2,
631 const Standard_Boolean bSplit2)
633 Standard_Integer aNbCP = theRanges1.Length();
638 IntTools_Range aRi1, aRi2, aRj1, aRj2;
639 Standard_Boolean bCond;
640 Standard_Integer i, j;
641 TopAbs_ShapeEnum aType;
642 Standard_Real aT11, aT12, aT21, aT22;
643 Standard_Real aTi11, aTi12, aTi21, aTi22;
644 Standard_Real aTj11, aTj12, aTj21, aTj22;
645 Standard_Real aRes1, aRes2, dTR1, dTR2;
646 TColStd_MapOfInteger aMI;
648 aRes1 = Resolution(myCurve1.Curve().Curve(),
649 myCurve1.GetType(), myResCoeff1, myTol);
650 aRes2 = Resolution(myCurve2.Curve().Curve(),
651 myCurve2.GetType(), myResCoeff2, myTol);
653 myRange1.Range(aT11, aT12);
654 myRange2.Range(aT21, aT22);
657 aType = TopAbs_VERTEX;
659 for (i = 1; i <= aNbCP;) {
660 if (aMI.Contains(i)) {
665 aRi1 = theRanges1(i);
666 aRi2 = theRanges2(i);
668 aRi1.Range(aTi11, aTi12);
669 aRi2.Range(aTi21, aTi22);
673 for (j = i+1; j <= aNbCP; ++j) {
674 if (aMI.Contains(j)) {
678 aRj1 = theRanges1(j);
679 aRj2 = theRanges2(j);
681 aRj1.Range(aTj11, aTj12);
682 aRj2.Range(aTj21, aTj22);
684 bCond = (fabs(aTi12 - aTj11) < dTR1) ||
685 (bSplit2 && (fabs(aTj12 - aTi11) < dTR1));
686 if (bCond && bSplit2) {
687 bCond = (fabs((Max(aTi22, aTj22) - Min(aTi21, aTj21)) -
688 ((aTi22 - aTi21) + (aTj22 - aTj21))) < dTR2);
692 aTi11 = Min(aTi11, aTj11);
693 aTi12 = Max(aTi12, aTj12);
694 aTi21 = Min(aTi21, aTj21);
695 aTi22 = Max(aTi22, aTj22);
704 if (((fabs(aT11 - aTi11) < myRes1) && (fabs(aT12 - aTi12) < myRes1)) ||
705 ((fabs(aT21 - aTi21) < myRes2) && (fabs(aT22 - aTi22) < myRes2))) {
707 myCommonParts.Clear();
710 AddSolution(aTi11, aTi12, aTi21, aTi22, aType);
711 if (aType == TopAbs_EDGE) {
721 //=======================================================================
722 //function : AddSolution
724 //=======================================================================
725 void IntTools_EdgeEdge::AddSolution(const Standard_Real aT11,
726 const Standard_Real aT12,
727 const Standard_Real aT21,
728 const Standard_Real aT22,
729 const TopAbs_ShapeEnum theType)
731 IntTools_CommonPrt aCPart;
733 aCPart.SetType(theType);
735 aCPart.SetEdge1(myEdge1);
736 aCPart.SetEdge2(myEdge2);
737 aCPart.SetRange1(aT11, aT12);
738 aCPart.AppendRange2(aT21, aT22);
740 aCPart.SetEdge1(myEdge2);
741 aCPart.SetEdge2(myEdge1);
742 aCPart.SetRange1(aT21, aT22);
743 aCPart.AppendRange2(aT11, aT12);
746 if (theType == TopAbs_VERTEX) {
747 Standard_Real aT1, aT2;
749 FindBestSolution(aT11, aT12, aT21, aT22, aT1, aT2);
752 aCPart.SetVertexParameter1(aT1);
753 aCPart.SetVertexParameter2(aT2);
755 aCPart.SetVertexParameter1(aT2);
756 aCPart.SetVertexParameter2(aT1);
759 myCommonParts.Append(aCPart);
762 //=======================================================================
763 //function : FindBestSolution
765 //=======================================================================
766 void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
767 const Standard_Real aT12,
768 const Standard_Real aT21,
769 const Standard_Real aT22,
773 Standard_Integer i, aNbS, iErr;
774 Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria;
775 Standard_Real aT1A, aT1B, aT1Min, aT2Min;
776 GeomAPI_ProjectPointOnCurve aProjPC;
777 IntTools_SequenceOfRanges aRanges;
779 aDMin = Precision::Infinite();
780 aSolCriteria = 5.e-16;
781 aTouchCriteria = 5.e-13;
782 Standard_Boolean bTouch = Standard_False;
783 Standard_Boolean bTouchConfirm = Standard_False;
785 aRes1 = Resolution(myCurve1.Curve().Curve(),
786 myCurve1.GetType(), myResCoeff1, myTol);
788 aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges);
790 aProjPC.Init(myGeom2, aT21, aT22);
792 Standard_Real aT11Touch = aT11, aT12Touch = aT12;
793 Standard_Real aT21Touch = aT21, aT22Touch = aT22;
794 Standard_Boolean isSolFound = Standard_False;
795 for (i = 1; i <= aNbS; ++i) {
796 const IntTools_Range& aR1 = aRanges(i);
797 aR1.Range(aT1A, aT1B);
800 iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1,
801 aProjPC, aD, aT1Min, aT2Min, Standard_False);
807 isSolFound = Standard_True;
810 if (aD < aTouchCriteria) {
814 bTouchConfirm = Standard_True;
819 bTouch = Standard_True;
824 if (!isSolFound || bTouchConfirm)
826 aT1 = (aT11Touch + aT12Touch) * 0.5;
827 iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1);
829 aT2 = (aT21Touch + aT22Touch) * 0.5;
834 //=======================================================================
835 //function : ComputeLineLine
837 //=======================================================================
838 void IntTools_EdgeEdge::ComputeLineLine()
840 Standard_Boolean IsParallel, IsCoincide;
841 Standard_Real aSin, aCos, aAng, aTol;
842 Standard_Real aT1, aT2, aT11, aT12, aT21, aT22;
846 IntTools_CommonPrt aCommonPrt;
848 IsParallel = Standard_False;
849 IsCoincide = Standard_False;
851 aL1 = myCurve1.Line();
852 aL2 = myCurve2.Line();
853 aD1 = aL1.Position().Direction();
854 aD2 = aL2.Position().Direction();
855 myRange1.Range(aT11, aT12);
856 myRange2.Range(aT21, aT22);
858 aCommonPrt.SetEdge1(myEdge1);
859 aCommonPrt.SetEdge2(myEdge2);
862 aAng = (aCos >= 0.) ? 2.*(1. - aCos) : 2.*(1. + aCos);
864 if(aAng <= Precision::Angular()) {
865 IsParallel = Standard_True;
866 if(aL1.SquareDistance(aL2.Location()) <= aTol) {
867 IsCoincide = Standard_True;
868 aP11 = ElCLib::Value(aT11, aL1);
869 aP12 = ElCLib::Value(aT12, aL1);
873 aP11 = ElCLib::Value(aT11, aL1);
874 aP12 = ElCLib::Value(aT12, aL1);
875 if(aL2.SquareDistance(aP11) <= aTol && aL2.SquareDistance(aP12) <= aTol) {
876 IsCoincide = Standard_True;
881 Standard_Real t21, t22;
883 t21 = ElCLib::Parameter(aL2, aP11);
884 t22 = ElCLib::Parameter(aL2, aP12);
885 if((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) {
898 aCommonPrt.SetRange1(aT11, aT12);
899 aCommonPrt.SetAllNullFlag(Standard_True);
900 aCommonPrt.AppendRange2(t21, t22);
903 aCommonPrt.SetRange1(aT11, aT12 - (t22 - aT22));
904 aCommonPrt.AppendRange2(t21, aT22);
908 aCommonPrt.SetRange1(aT11 + (aT21 - t21), aT12);
909 aCommonPrt.AppendRange2(aT21, t22);
911 aCommonPrt.SetType(TopAbs_EDGE);
912 myCommonParts.Append(aCommonPrt);
921 TopoDS_Iterator aIt1, aIt2;
922 aIt1.Initialize(myEdge1);
923 for (; aIt1.More(); aIt1.Next()) {
924 const TopoDS_Shape& aV1 = aIt1.Value();
925 aIt2.Initialize(myEdge2);
926 for (; aIt2.More(); aIt2.Next()) {
927 const TopoDS_Shape& aV2 = aIt2.Value();
928 if (aV2.IsSame(aV1)) {
935 aSin = 1. - aCos*aCos;
936 gp_Pnt O1 = aL1.Location();
937 gp_Pnt O2 = aL2.Location();
938 gp_Vec O1O2 (O1, O2);
940 aT2 = (aD1.XYZ()*(O1O2.Dot(aD1))-(O1O2.XYZ())).Dot(aD2.XYZ());
943 if(aT2 < aT21 || aT2 > aT22) {
947 gp_Pnt aP2(ElCLib::Value(aT2, aL2));
948 aT1 = (gp_Vec(O1, aP2)).Dot(aD1);
950 if(aT1 < aT11 || aT1 > aT12) {
954 gp_Pnt aP1(ElCLib::Value(aT1, aL1));
955 Standard_Real aDist = aP1.SquareDistance(aP2);
961 // compute correct range on the edges
962 Standard_Real anAngle, aDt1, aDt2;
964 anAngle = aD1.Angle(aD2);
966 aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle);
967 aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle);
969 aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1);
970 aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2);
971 aCommonPrt.SetType(TopAbs_VERTEX);
972 aCommonPrt.SetVertexParameter1(aT1);
973 aCommonPrt.SetVertexParameter2(aT2);
974 myCommonParts.Append(aCommonPrt);
977 //=======================================================================
978 //function : IsIntersection
980 //=======================================================================
981 Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11,
982 const Standard_Real aT12,
983 const Standard_Real aT21,
984 const Standard_Real aT22)
986 Standard_Boolean bRet;
987 gp_Pnt aP11, aP12, aP21, aP22;
988 gp_Vec aV11, aV12, aV21, aV22;
989 Standard_Real aD11_21, aD11_22, aD12_21, aD12_22, aCriteria, aCoef;
990 Standard_Boolean bSmall_11_21, bSmall_11_22, bSmall_12_21, bSmall_12_22;
992 bRet = Standard_True;
994 if (((aT12 - aT11) > aCoef*myRes1) && ((aT22 - aT21) > aCoef*myRes2)) {
997 Standard_Real aTRMin = Min((aT12 - aT11)/myRes1, (aT22 - aT21)/myRes2);
998 aCoef = aTRMin / 100.;
1003 aCriteria = aCoef * myTol;
1004 aCriteria *= aCriteria;
1006 myGeom1->D1(aT11, aP11, aV11);
1007 myGeom1->D1(aT12, aP12, aV12);
1008 myGeom2->D1(aT21, aP21, aV21);
1009 myGeom2->D1(aT22, aP22, aV22);
1011 aD11_21 = aP11.SquareDistance(aP21);
1012 aD11_22 = aP11.SquareDistance(aP22);
1013 aD12_21 = aP12.SquareDistance(aP21);
1014 aD12_22 = aP12.SquareDistance(aP22);
1016 bSmall_11_21 = aD11_21 < aCriteria;
1017 bSmall_11_22 = aD11_22 < aCriteria;
1018 bSmall_12_21 = aD12_21 < aCriteria;
1019 bSmall_12_22 = aD12_22 < aCriteria;
1021 if ((bSmall_11_21 && bSmall_12_22) ||
1022 (bSmall_11_22 && bSmall_12_21)) {
1027 Standard_Real anAngleCriteria;
1028 Standard_Real anAngle1 = 0.0,
1031 anAngleCriteria = 5.e-3;
1032 if (aV11.SquareMagnitude() > Precision::SquareConfusion() &&
1033 aV12.SquareMagnitude() > Precision::SquareConfusion() &&
1034 aV21.SquareMagnitude() > Precision::SquareConfusion() &&
1035 aV22.SquareMagnitude() > Precision::SquareConfusion() )
1037 if (bSmall_11_21 && bSmall_12_22) {
1038 anAngle1 = aV11.Angle(aV21);
1039 anAngle2 = aV12.Angle(aV22);
1041 anAngle1 = aV11.Angle(aV22);
1042 anAngle2 = aV12.Angle(aV21);
1046 if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) ||
1047 ((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) {
1048 GeomAPI_ProjectPointOnCurve aProjPC;
1049 Standard_Integer iErr;
1050 Standard_Real aD, aT1Min, aT2Min;
1052 aD = Precision::Infinite();
1053 aProjPC.Init(myGeom2, aT21, aT22);
1054 iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1,
1055 aProjPC, aD, aT1Min, aT2Min, Standard_False);
1062 //=======================================================================
1063 //function : CheckCoincidence
1065 //=======================================================================
1066 Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
1067 const Standard_Real aT12,
1068 const Standard_Real aT21,
1069 const Standard_Real aT22,
1070 const Standard_Real theCriteria,
1071 const Standard_Real theCurveRes1)
1073 Standard_Integer iErr, aNb, aNb1, i;
1074 Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax;
1075 GeomAPI_ProjectPointOnCurve aProjPC;
1076 IntTools_SequenceOfRanges aRanges;
1080 aProjPC.Init(myGeom2, aT21, aT22);
1082 // 1. Express evaluation
1083 aNb = 10; // Number of intervals on the curve #1
1084 aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges);
1085 for (i = 1; i < aNb1; ++i) {
1086 const IntTools_Range& aR1 = aRanges(i);
1087 aR1.Range(aT1A, aT1B);
1089 iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max);
1095 // if the ranges in aRanges are less than theCurveRes1,
1096 // there is no need to do step 2 (deep evaluation)
1101 // 2. Deep evaluation
1102 for (i = 2; i < aNb1; ++i) {
1103 const IntTools_Range& aR1 = aRanges(i);
1104 aR1.Range(aT1A, aT1B);
1106 iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1,
1107 aProjPC, aDmax, aT1max, aT2max);
1113 // iErr == 0 - the patches are coincided
1114 // iErr == 1 - a point from aC1 can not be projected on aC2
1115 // iErr == 2 - the distance is too big
1119 //=======================================================================
1120 //function : FindDistPC
1122 //=======================================================================
1123 Standard_Integer FindDistPC(const Standard_Real aT1A,
1124 const Standard_Real aT1B,
1125 const Handle(Geom_Curve)& theC1,
1126 const Standard_Real theCriteria,
1127 const Standard_Real theEps,
1128 GeomAPI_ProjectPointOnCurve& theProjPC,
1129 Standard_Real& aDmax,
1130 Standard_Real& aT1max,
1131 Standard_Real& aT2max,
1132 const Standard_Boolean bMaxDist)
1134 Standard_Integer iErr, iC;
1135 Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L;
1137 iC = bMaxDist ? 1 : -1;
1139 aT1max = aT2max = 0.; // silence GCC warning
1141 aGS = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
1146 iErr = DistPC(aA, theC1, theCriteria, theProjPC,
1147 aYP, aT2P, aDmax, aT1max, aT2max, iC);
1152 iErr = DistPC(aB, theC1, theCriteria, theProjPC,
1153 aYL, aT2L, aDmax, aT1max, aT2max, iC);
1158 aXP = aA + (aB - aA)*aGS;
1159 aXL = aB - (aB - aA)*aGS;
1161 iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
1162 aYP, aT2P, aDmax, aT1max, aT2max, iC);
1167 iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
1168 aYL, aT2L, aDmax, aT1max, aT2max, iC);
1173 Standard_Real anEps = Max(theEps, Epsilon(Max(Abs(aA), Abs(aB))) * 10.);
1175 if (iC*(aYP - aYL) > 0) {
1179 aXP = aA + (aB - aA)*aGS;
1180 iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
1181 aYP, aT2P, aDmax, aT1max, aT2max, iC);
1187 aXL = aB - (aB - aA)*aGS;
1188 iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
1189 aYL, aT2L, aDmax, aT1max, aT2max, iC);
1193 if ((iErr == 2) && !bMaxDist) {
1194 aXP = (aA + aB) * 0.5;
1195 DistPC(aXP, theC1, theCriteria, theProjPC,
1196 aYP, aT2P, aDmax, aT1max, aT2max, iC);
1201 if ((aB - aA) < anEps) {
1208 //=======================================================================
1211 //=======================================================================
1212 Standard_Integer DistPC(const Standard_Real aT1,
1213 const Handle(Geom_Curve)& theC1,
1214 const Standard_Real theCriteria,
1215 GeomAPI_ProjectPointOnCurve& theProjPC,
1218 Standard_Real& aDmax,
1219 Standard_Real& aT1max,
1220 Standard_Real& aT2max,
1221 const Standard_Integer iC)
1223 Standard_Integer iErr;
1225 iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC);
1230 if (iC*(aD - aDmax) > 0) {
1238 //=======================================================================
1241 //=======================================================================
1242 Standard_Integer DistPC(const Standard_Real aT1,
1243 const Handle(Geom_Curve)& theC1,
1244 const Standard_Real theCriteria,
1245 GeomAPI_ProjectPointOnCurve& theProjPC,
1248 const Standard_Integer iC)
1250 Standard_Integer iErr, aNbP2;
1254 theC1->D0(aT1, aP1);
1256 theProjPC.Perform(aP1);
1257 aNbP2 = theProjPC.NbPoints();
1259 iErr = 1;// the point from aC1 can not be projected on aC2
1263 aD = theProjPC.LowerDistance();
1264 aT2 = theProjPC.LowerDistanceParameter();
1265 if (iC*(aD - theCriteria) > 0) {
1266 iErr = 2;// the distance is too big or small
1272 //=======================================================================
1273 //function : SplitRangeOnSegments
1275 //=======================================================================
1276 Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
1277 const Standard_Real aT2,
1278 const Standard_Real theResolution,
1279 const Standard_Integer theNbSeg,
1280 IntTools_SequenceOfRanges& theSegments)
1282 Standard_Real aDiff = aT2 - aT1;
1283 if (aDiff < theResolution || theNbSeg == 1) {
1284 theSegments.Append(IntTools_Range(aT1, aT2));
1288 Standard_Real aDt, aT1x, aT2x, aSeg;
1289 Standard_Integer aNbSegments, i;
1291 aNbSegments = theNbSeg;
1292 aDt = aDiff / aNbSegments;
1293 if (aDt < theResolution) {
1294 aSeg = aDiff / theResolution;
1295 aNbSegments = Standard_Integer(aSeg) + 1;
1296 aDt = aDiff / aNbSegments;
1300 for (i = 1; i < aNbSegments; ++i) {
1303 IntTools_Range aR(aT1x, aT2x);
1304 theSegments.Append(aR);
1309 IntTools_Range aR(aT1x, aT2);
1310 theSegments.Append(aR);
1315 //=======================================================================
1316 //function : BndBuildBox
1318 //=======================================================================
1319 void BndBuildBox(const BRepAdaptor_Curve& theBAC,
1320 const Standard_Real aT1,
1321 const Standard_Real aT2,
1322 const Standard_Real theTol,
1326 BndLib_Add3dCurve::Add(theBAC, aT1, aT2, theTol, aB);
1330 //=======================================================================
1331 //function : PointBoxDistance
1333 //=======================================================================
1334 Standard_Real PointBoxDistance(const Bnd_Box& aB,
1337 Standard_Real aPCoord[3];
1338 Standard_Real aBMinCoord[3], aBMaxCoord[3];
1339 Standard_Real aDist, aR1, aR2;
1342 aP.Coord(aPCoord[0], aPCoord[1], aPCoord[2]);
1343 aB.Get(aBMinCoord[0], aBMinCoord[1], aBMinCoord[2],
1344 aBMaxCoord[0], aBMaxCoord[1], aBMaxCoord[2]);
1347 for (i = 0; i < 3; ++i) {
1348 aR1 = aBMinCoord[i] - aPCoord[i];
1354 aR2 = aPCoord[i] - aBMaxCoord[i];
1360 aDist = Sqrt(aDist);
1364 //=======================================================================
1365 //function : TypeToInteger
1367 //=======================================================================
1368 Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType)
1370 Standard_Integer iRet;
1376 case GeomAbs_Hyperbola:
1377 case GeomAbs_Parabola:
1380 case GeomAbs_Circle:
1381 case GeomAbs_Ellipse:
1384 case GeomAbs_BezierCurve:
1385 case GeomAbs_BSplineCurve:
1395 //=======================================================================
1396 //function : ResolutionCoeff
1398 //=======================================================================
1399 Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
1400 const IntTools_Range& theRange)
1402 Standard_Real aResCoeff = 0.;
1404 const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
1405 const GeomAbs_CurveType aCurveType = theBAC.GetType();
1407 switch (aCurveType) {
1408 case GeomAbs_Circle :
1409 aResCoeff = 1. / (2 * Handle(Geom_Circle)::DownCast (aCurve)->Circ().Radius());
1411 case GeomAbs_Ellipse :
1412 aResCoeff = 1. / Handle(Geom_Ellipse)::DownCast (aCurve)->MajorRadius();
1414 case GeomAbs_OffsetCurve : {
1415 const Handle(Geom_OffsetCurve)& anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(aCurve);
1416 const Handle(Geom_Curve)& aBasisCurve = anOffsetCurve->BasisCurve();
1417 GeomAdaptor_Curve aGBasisCurve(aBasisCurve);
1418 const GeomAbs_CurveType aBCType = aGBasisCurve.GetType();
1419 if (aBCType == GeomAbs_Line) {
1422 else if (aBCType == GeomAbs_Circle) {
1423 aResCoeff = 1. / (2 * (anOffsetCurve->Offset() + aGBasisCurve.Circle().Radius()));
1426 else if (aBCType == GeomAbs_Ellipse) {
1427 aResCoeff = 1. / (anOffsetCurve->Offset() + aGBasisCurve.Ellipse().MajorRadius());
1431 Standard_FALLTHROUGH
1432 case GeomAbs_Hyperbola :
1433 case GeomAbs_Parabola :
1434 case GeomAbs_OtherCurve :{
1435 Standard_Real k, kMin, aDist, aDt, aT1, aT2, aT;
1436 Standard_Integer aNbP, i;
1440 theRange.Range(aT1, aT2);
1441 aDt = (aT2 - aT1) / aNbP;
1445 theBAC.D0(aT1, aP1);
1446 for (i = 1; i <= aNbP; ++i) {
1449 aDist = aP1.Distance(aP2);
1467 //=======================================================================
1468 //function : Resolution
1470 //=======================================================================
1471 Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
1472 const GeomAbs_CurveType theCurveType,
1473 const Standard_Real theResCoeff,
1474 const Standard_Real theR3D)
1478 switch (theCurveType) {
1482 case GeomAbs_Circle: {
1483 Standard_Real aDt = theResCoeff * theR3D;
1484 aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
1487 case GeomAbs_BezierCurve:
1488 Handle(Geom_BezierCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
1490 case GeomAbs_BSplineCurve:
1491 Handle(Geom_BSplineCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
1493 case GeomAbs_OffsetCurve: {
1494 const Handle(Geom_Curve)& aBasisCurve =
1495 Handle(Geom_OffsetCurve)::DownCast(theCurve)->BasisCurve();
1496 const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
1497 if (aBCType == GeomAbs_Line) {
1501 else if (aBCType == GeomAbs_Circle) {
1502 Standard_Real aDt = theResCoeff * theR3D;
1503 aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
1507 Standard_FALLTHROUGH
1509 aRes = theResCoeff * theR3D;
1516 //=======================================================================
1517 //function : CurveDeflection
1519 //=======================================================================
1520 Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
1521 const IntTools_Range& theRange)
1523 Standard_Real aDt, aT, aT1, aT2, aDefl;
1524 Standard_Integer i, aNbP;
1530 theRange.Range(aT1, aT2);
1531 aDt = (aT2 - aT1) / aNbP;
1534 theBAC.D1(aT1, aP, aV1);
1535 for (i = 1; i <= aNbP; ++i) {
1537 theBAC.D1(aT, aP, aV2);
1538 if (aV1.Magnitude() > gp::Resolution() &&
1539 aV2.Magnitude() > gp::Resolution()) {
1540 gp_Dir aD1(aV1), aD2(aV2);
1541 aDefl += aD1.Angle(aD2);
1549 //=======================================================================
1550 //function : IsClosed
1552 //=======================================================================
1553 Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
1554 const Standard_Real aT1,
1555 const Standard_Real aT2,
1556 const Standard_Real theTol,
1557 const Standard_Real theRes)
1559 if (Abs(aT1 - aT2) < theRes)
1561 return Standard_False;
1565 theCurve->D0(aT1, aP1);
1566 theCurve->D0(aT2, aP2);
1568 Standard_Real aD = aP1.Distance(aP2);