1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : GEOMImpl_Fillet1d.cxx
23 #include "GEOMImpl_Fillet1d.hxx"
25 #include <BRep_Tool.hxx>
26 #include <BRepAdaptor_Curve.hxx>
27 #include <BRepBuilderAPI_MakeEdge.hxx>
30 #include <gp_Circ.hxx>
31 #include <Geom2d_Line.hxx>
32 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
33 #include <Geom2dAPI_InterCurveCurve.hxx>
34 #include <GeomAPI_ProjectPointOnCurve.hxx>
35 #include <GeomProjLib.hxx>
36 #include <Geom_Circle.hxx>
37 #include <Precision.hxx>
38 #include <TColStd_ListIteratorOfListOfReal.hxx>
39 #include <IntRes2d_IntersectionSegment.hxx>
42 * class GEOMImpl_Fillet1d
45 //=======================================================================
46 //function : Constructor
48 //=======================================================================
49 GEOMImpl_Fillet1d::GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,
50 const TopoDS_Edge& theEdge2,
51 const gp_Pln& thePlane)
52 : myEdgesExchnged( Standard_False )
54 myPlane = new Geom_Plane(thePlane);
56 BRepAdaptor_Curve aBAC1(theEdge1);
57 BRepAdaptor_Curve aBAC2(theEdge2);
58 if (aBAC1.GetType() < aBAC2.GetType())
59 { // first curve must be more complicated
62 myEdgesExchnged = Standard_True;
70 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(myEdge1, myStart1, myEnd1);
71 Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(myEdge2, myStart2, myEnd2);
73 myCurve1 = GeomProjLib::Curve2d(aCurve1, myStart1, myEnd1, myPlane);
74 myCurve2 = GeomProjLib::Curve2d(aCurve2, myStart2, myEnd2, myPlane);
76 while (myCurve1->IsPeriodic() && myStart1 >= myEnd1)
77 myEnd1 += myCurve1->Period();
78 while (myCurve2->IsPeriodic() && myStart2 >= myEnd2)
79 myEnd2 += myCurve2->Period();
81 if (aBAC1.GetType() == aBAC2.GetType())
83 if (myEnd2 - myStart2 < myEnd1 - myStart1)
84 { // first curve must be parametrically shorter
85 TopoDS_Edge anEdge = myEdge1;
88 Handle(Geom2d_Curve) aCurve = myCurve1;
91 Standard_Real a = myStart1;
97 myEdgesExchnged = Standard_True;
102 //=======================================================================
103 //function : isRadiusIntersected
104 //purpose : local function
105 //=======================================================================
106 static Standard_Boolean isRadiusIntersected(const Handle(Geom2d_Curve)& theCurve,
107 const gp_Pnt2d theStart,
108 const gp_Pnt2d theEnd,
109 const Standard_Boolean theStartConnected)
111 const Standard_Real aTol = Precision::Confusion();
112 const Standard_Real anAngTol = Precision::Angular();
113 Geom2dAPI_InterCurveCurve anInter(theCurve, new Geom2d_Line(theStart,
114 gp_Dir2d(gp_Vec2d(theStart, theEnd))), aTol);
117 for(a = anInter.NbPoints(); a > 0; a--)
119 aPoint = anInter.Point(a);
120 if ( aPoint.Distance(theStart) < aTol && !theStartConnected )
121 return Standard_True;
122 if (aPoint.Distance(theEnd) < aTol * 200)
123 return Standard_True;
124 if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
125 return Standard_True;
127 Handle(Geom2d_Curve) aCurve;
128 for(a = anInter.NbSegments(); a > 0; a--)
130 anInter.Segment(a, aCurve);
131 aPoint = aCurve->Value(aCurve->FirstParameter());
132 if (aPoint.Distance(theStart) < aTol)
133 if (!theStartConnected)
134 return Standard_True;
135 if (aPoint.Distance(theEnd) < aTol)
136 return Standard_True;
137 if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
138 return Standard_True;
139 aPoint = aCurve->Value(aCurve->LastParameter());
140 if (aPoint.Distance(theStart) < aTol)
141 if (!theStartConnected)
142 return Standard_True;
143 if (aPoint.Distance(theEnd) < aTol)
144 return Standard_True;
145 if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
146 return Standard_True;
148 return Standard_False;
152 //=======================================================================
153 //function : fillPoint
155 //=======================================================================
156 void GEOMImpl_Fillet1d::fillPoint(GEOMImpl_Fillet1dPoint* thePoint)
160 const Standard_Real aTol = Precision::Confusion();
161 myCurve1->D1(thePoint->GetParam(), aPoint, aVec);
162 if (aVec.SquareMagnitude() < aTol)
165 gp_Vec2d aPerp(((myStartSide)?-1:1) * aVec.Y(), ((myStartSide)?1:-1) * aVec.X());
167 aPerp.Multiply(myRadius);
168 gp_Pnt2d aCenter = aPoint.Translated(aPerp);
169 thePoint->SetCenter(aCenter);
171 // on the intersection point
172 Standard_Boolean aValid = Standard_True;
173 Geom2dAPI_ProjectPointOnCurve aProjInt(aPoint, myCurve2);
174 if (aProjInt.NbPoints() && aPoint.Distance(aProjInt.NearestPoint()) < aTol)
175 aValid = Standard_False;
177 aValid = !isRadiusIntersected(myCurve2, aPoint, aCenter, Standard_True);
179 Geom2dAPI_ProjectPointOnCurve aProj(aCenter, myCurve2);
180 Standard_Integer a, aNB = aProj.NbPoints();
181 for(a = aNB; a > 0; a--)
183 if (aPoint.Distance(aProj.Point(a)) < aTol)
186 Standard_Boolean aValid2 = aValid;
188 aValid2 = !isRadiusIntersected(myCurve1, aCenter, aProj.Point(a), Standard_False);
190 // checking the right parameter
191 Standard_Real aParam = aProj.Parameter(a);
192 while(myCurve2->IsPeriodic() && aParam < myStart2)
193 aParam += myCurve2->Period();
195 thePoint->AddValue(aProj.Distance(a) * aProj.Distance(a) - myRadius * myRadius,
196 (aParam >= myStart2 && aParam <= myEnd2 && aValid2));
197 if (fabs(fabs(aProj.Distance(a)) - myRadius) < aTol)
198 thePoint->SetParam2(aParam);
202 //=======================================================================
203 //function : fillDiff
205 //=======================================================================
206 void GEOMImpl_Fillet1d::fillDiff(GEOMImpl_Fillet1dPoint* thePoint, Standard_Real theDiffStep, Standard_Boolean theFront)
208 GEOMImpl_Fillet1dPoint* aDiff =
209 new GEOMImpl_Fillet1dPoint(thePoint->GetParam() + (theFront?(theDiffStep):(-theDiffStep)));
211 if (!thePoint->ComputeDifference(aDiff))
213 aDiff->SetParam(thePoint->GetParam() + (theFront?(-theDiffStep):(theDiffStep)));
215 thePoint->ComputeDifference(aDiff);
220 //=======================================================================
223 //=======================================================================
224 Standard_Boolean GEOMImpl_Fillet1d::Perform(const Standard_Real theRadius)
226 myDegreeOfRecursion = 0;
227 myResultParams.Clear();
228 myResultOrientation.Clear();
230 Standard_Real aNBSteps = 100;
231 Geom2dAdaptor_Curve aGAC(myCurve1);
232 switch (aGAC.GetType())
240 case GeomAbs_Ellipse:
243 case GeomAbs_BezierCurve:
244 case GeomAbs_BSplineCurve:
245 aNBSteps = 2 + aGAC.Degree() * aGAC.NbPoles();
247 default: // unknown: maximum
251 myRadius = theRadius;
253 // Compute the intervals.
254 const Standard_Real aTol = Precision::Confusion();
255 Geom2dAPI_InterCurveCurve anAPIInter(myCurve1, myCurve2, aTol);
256 const Geom2dInt_GInter &anInter = anAPIInter.Intersector();
257 Standard_Integer aNb = anInter.NbPoints();
259 TColStd_ListOfReal aParams;
260 TColStd_ListIteratorOfListOfReal anIter;
262 // Treat intersection points.
263 for(i = 1; i <= aNb; i++) {
264 const IntRes2d_IntersectionPoint &aPoint = anInter.Point(i);
265 Standard_Real aParam = aPoint.ParamOnFirst();
267 // Adjust parameter on periodic curve.
268 if (myCurve1->IsPeriodic()) {
269 aParam = ElCLib::InPeriod
270 (aParam, myStart1, myStart1 + myCurve1->Period());
273 if (aParam > myStart1 + aTol && aParam < myEnd1 - aTol) {
274 // Add the point in the list in increasing order.
275 for(anIter.Initialize(aParams); anIter.More(); anIter.Next()) {
276 if (anIter.Value() > aParam) {
277 aParams.InsertBefore(aParam, anIter);
282 if (!anIter.More()) {
283 aParams.Append(aParam);
288 // Treat intersection segments.
289 aNb = anInter.NbSegments();
291 for(i = 1; i <= aNb; i++) {
292 const IntRes2d_IntersectionSegment &aSegment = anInter.Segment(i);
294 if (aSegment.HasFirstPoint() && aSegment.HasLastPoint()) {
295 Standard_Real aParam1 = aSegment.FirstPoint().ParamOnFirst();
296 Standard_Real aParam2 = aSegment.LastPoint().ParamOnFirst();
298 // Adjust parameters on periodic curve.
299 if (myCurve1->IsPeriodic()) {
300 ElCLib::AdjustPeriodic(myStart1, myStart1 + myCurve1->Period(),
301 aTol, aParam1, aParam2);
304 if (aParam1 > myStart1 + aTol && aParam1 < myEnd1 - aTol &&
305 aParam2 > myStart1 + aTol && aParam2 < myEnd1 - aTol) {
306 // Add the point in the list in increasing order.
307 const Standard_Real aParam = 0.5*(aParam1 + aParam2);
309 for(anIter.Initialize(aParams); anIter.More(); anIter.Next()) {
310 if (anIter.Value() > aParam) {
311 aParams.InsertBefore(aParam, anIter);
316 if (!anIter.More()) {
317 aParams.Append(aParam);
323 // Add start and end parameters to the list.
324 aParams.Prepend(myStart1);
325 aParams.Append(myEnd1);
326 anIter.Initialize(aParams);
328 // Perform each interval.
329 Standard_Real aStart = anIter.Value();
331 for (anIter.Next(); anIter.More(); anIter.Next()) {
332 const Standard_Real anEnd = anIter.Value();
334 // Perform the interval.
335 performInterval(aStart, anEnd, aNBSteps);
339 if (myResultParams.Extent())
340 return Standard_True;
342 return Standard_False;
345 //=======================================================================
346 //function : performInterval
348 //=======================================================================
349 void GEOMImpl_Fillet1d::performInterval(const Standard_Real theStart,
350 const Standard_Real theEnd,
351 const Standard_Integer theNBSteps)
353 Standard_Real aParam, aStep, aDStep;
354 aStep = (theEnd - theStart) / theNBSteps;
355 aDStep = aStep/1000.;
357 Standard_Integer aCycle;
358 for(aCycle = 2, myStartSide = Standard_False; aCycle; myStartSide = !myStartSide, aCycle--)
360 GEOMImpl_Fillet1dPoint *aLeft = NULL, *aRight = NULL;
362 for(aParam = theStart + aStep; aParam < theEnd || fabs(theEnd - aParam) < Precision::Confusion(); aParam += aStep)
366 aLeft = new GEOMImpl_Fillet1dPoint(aParam - aStep);
368 fillDiff(aLeft, aDStep, Standard_True);
371 aRight = new GEOMImpl_Fillet1dPoint(aParam);
373 fillDiff(aRight, aDStep, Standard_False);
375 aLeft->FilterPoints(aRight);
376 performNewton(aLeft, aRight);
385 //=======================================================================
386 //function : processPoint
388 //=======================================================================
389 Standard_Boolean GEOMImpl_Fillet1d::processPoint(GEOMImpl_Fillet1dPoint* theLeft,
390 GEOMImpl_Fillet1dPoint* theRight,
391 Standard_Real theParameter)
393 if (theParameter >= theLeft->GetParam() && theParameter < theRight->GetParam())
395 Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();
396 if (theParameter - theLeft->GetParam() < aDX / 100.)
398 theParameter = theLeft->GetParam() + aDX / 100.;
400 if (theRight->GetParam() - theParameter < aDX / 100.)
402 theParameter = theRight->GetParam() - aDX / 100.;
405 // Protection on infinite loop.
406 myDegreeOfRecursion++;
407 Standard_Real diffx = 0.001 * aDX;
408 if (myDegreeOfRecursion > 1000)
411 if (myDegreeOfRecursion > 10000)
414 if (myDegreeOfRecursion > 100000)
416 return Standard_True;
421 GEOMImpl_Fillet1dPoint* aPoint1 = theLeft->Copy();
422 GEOMImpl_Fillet1dPoint* aPoint2 = new GEOMImpl_Fillet1dPoint(theParameter);
424 fillDiff(aPoint2, diffx, Standard_True);
426 aPoint1->FilterPoints(aPoint2);
427 performNewton(aPoint1, aPoint2);
428 aPoint2->FilterPoints(theRight);
429 performNewton(aPoint2, theRight);
433 return Standard_True;
436 return Standard_False;
439 //=======================================================================
440 //function : performNewton
442 //=======================================================================
443 void GEOMImpl_Fillet1d::performNewton(GEOMImpl_Fillet1dPoint* theLeft,
444 GEOMImpl_Fillet1dPoint* theRight)
447 // check the left: if this is solution store it and remove it from the list of researching points of theLeft
448 a = theLeft->HasSolution(myRadius);
451 if (theLeft->IsValid(a))
453 myResultParams.Append(theLeft->GetParam());
454 myResultOrientation.Append(myStartSide);
459 Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();
460 if ( aDX < Precision::Confusion() / 1000000.)
462 a = theRight->HasSolution(myRadius);
464 if (theRight->IsValid(a))
466 myResultParams.Append(theRight->GetParam());
467 myResultOrientation.Append(myStartSide);
472 for(a = 1; a <= theLeft->GetNBValues(); a++)
474 Standard_Integer aNear = theLeft->GetNear(a);
476 Standard_Real aA = (theRight->GetDiff(aNear) - theLeft->GetDiff(a)) / aDX;
477 Standard_Real aB = theLeft->GetDiff(a) - aA * theLeft->GetParam();
478 Standard_Real aC = theLeft->GetValue(a) - theLeft->GetDiff(a) * theLeft->GetParam() +
479 aA * theLeft->GetParam() * theLeft->GetParam() / 2.0;
480 Standard_Real aDet = aB * aB - 2.0 * aA * aC;
482 if ( fabs(aDet) < gp::Resolution() )
485 if (fabs(aA) < Precision::Confusion())
487 if (fabs(aB) > 10e-20)
489 Standard_Real aX0 = - aC / aB; // use extremum
490 if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())
491 processPoint(theLeft, theRight, aX0);
495 processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
500 if (fabs(aB) > fabs(aDet * 1000000.))
501 { // possible floating point operations accuracy errors
502 processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
509 Standard_Boolean aRes = processPoint(theLeft, theRight, (- aB + aDet) / aA);
511 aRes = processPoint(theLeft, theRight, (- aB - aDet) / aA);
513 processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
517 Standard_Real aX0 = - aB / aA; // use extremum
518 if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())
519 processPoint(theLeft, theRight, aX0);
521 processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
528 //=======================================================================
531 //=======================================================================
532 TopoDS_Edge GEOMImpl_Fillet1d::Result(const gp_Pnt& thePoint,
533 TopoDS_Edge& theEdge1,
534 TopoDS_Edge& theEdge2)
537 gp_Pnt2d aTargetPoint2d;
538 Standard_Real aX, aY;
539 ElSLib::PlaneParameters(myPlane->Pln().Position(), thePoint, aX, aY);
540 aTargetPoint2d.SetCoord(aX, aY);
542 // choose the nearest circle
543 Standard_Real aDistance, aP;
544 GEOMImpl_Fillet1dPoint *aNearest;
546 TColStd_ListIteratorOfListOfReal anIter(myResultParams);
547 for(aNearest = NULL, a = 1; anIter.More(); anIter.Next(), a++)
549 myStartSide = (myResultOrientation.Value(a)) ? Standard_True : Standard_False;
550 GEOMImpl_Fillet1dPoint *aPoint = new GEOMImpl_Fillet1dPoint(anIter.Value());
552 if (!aPoint->HasSolution(myRadius))
554 aP = fabs(aPoint->GetCenter().Distance(aTargetPoint2d) - myRadius);
555 if (!aNearest || aP < aDistance)
569 // create circle edge
570 gp_Pnt aCenter = ElSLib::PlaneValue(aNearest->GetCenter().X(),
571 aNearest->GetCenter().Y(),
572 myPlane->Pln().Position());
573 Handle(Geom_Circle) aCircle =
574 new Geom_Circle(gp_Ax2(aCenter, myPlane->Pln().Axis().Direction()), myRadius);
575 gp_Pnt2d aPoint2d1, aPoint2d2;
576 myCurve1->D0(aNearest->GetParam(), aPoint2d1);
577 myCurve2->D0(aNearest->GetParam2(), aPoint2d2);
578 gp_Pnt aPoint1 = ElSLib::PlaneValue(aPoint2d1.X(), aPoint2d1.Y(), myPlane->Pln().Position());
579 gp_Pnt aPoint2 = ElSLib::PlaneValue(aPoint2d2.X(), aPoint2d2.Y(), myPlane->Pln().Position());
581 GeomAPI_ProjectPointOnCurve aProj(thePoint, aCircle);
582 Standard_Real aTarGetParam = aProj.LowerDistanceParameter();
583 gp_Pnt aPointOnCircle = aProj.NearestPoint();
585 // Check extrema point manually, because there is a bug in Open CASCADE
586 // in calculation of nearest point to a circle near the parameter 0.0
587 gp_Pnt p0 = ElCLib::Value(0.0, aCircle->Circ());
588 if (p0.Distance(thePoint) < aPointOnCircle.Distance(thePoint))
594 aProj.Perform(aPoint1);
595 Standard_Real aParam1 = aProj.LowerDistanceParameter();
596 aProj.Perform(aPoint2);
597 Standard_Real aParam2 = aProj.LowerDistanceParameter();
598 Standard_Boolean aIsOut = ((aParam1 < aTarGetParam && aParam2 < aTarGetParam) ||
599 (aParam1 > aTarGetParam && aParam2 > aTarGetParam));
600 if (aParam1 > aParam2)
602 BRepBuilderAPI_MakeEdge aBuilder(aCircle->Circ(),
603 aIsOut ? aParam2 : aParam1,
604 aIsOut? aParam1 : aParam2);
605 aResult = aBuilder.Edge();
608 Standard_Real aStart, anEnd;
609 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(myEdge1, aStart, anEnd);
611 aCurve->D1(aNearest->GetParam(), aPoint1, aDir);
614 aCircle->D1(aParam1, aPoint1, aCircleDir);
615 if ((aCircleDir.Angle(aDir) > M_PI / 2.0) ^ aIsOut)
616 aStart = aNearest->GetParam();
618 anEnd = aNearest->GetParam();
620 if (fabs(aStart - anEnd) > Precision::Confusion())
623 BRepBuilderAPI_MakeEdge aDivider1(aCurve, aStart, anEnd);
625 theEdge2 = aDivider1.Edge();
627 theEdge1 = aDivider1.Edge();
630 aCurve = BRep_Tool::Curve(myEdge2, aStart, anEnd);
631 aCurve->D1(aNearest->GetParam2(), aPoint2, aDir);
633 aCircle->D1(aParam2, aPoint2, aCircleDir);
634 if ((aCircleDir.Angle(aDir) > M_PI / 2.0) ^ (!aIsOut))
635 aStart = aNearest->GetParam2();
637 anEnd = aNearest->GetParam2();
639 if (fabs(aStart - anEnd) > Precision::Confusion())
641 BRepBuilderAPI_MakeEdge aDivider2(aCurve, aStart, anEnd);
643 theEdge1 = aDivider2.Edge();
645 theEdge2 = aDivider2.Edge();
652 //=======================================================================
653 //function : AddValue
655 //=======================================================================
656 void GEOMImpl_Fillet1dPoint::AddValue(Standard_Real theValue, Standard_Boolean theValid)
659 for(a = 1; a <= myV.Length(); a++)
661 if (theValue < myV.Value(a))
663 myV.InsertBefore(a, theValue);
664 myValid.InsertBefore(a, (Standard_Integer)theValid);
668 myV.Append(theValue);
669 myValid.Append((Standard_Integer)theValid);
672 //=======================================================================
673 //function : ComputeDifference
675 //=======================================================================
676 Standard_Boolean GEOMImpl_Fillet1dPoint::ComputeDifference(GEOMImpl_Fillet1dPoint* thePoint)
679 Standard_Boolean aDiffsSet = (myD.Length() != 0);
680 Standard_Real aDX = thePoint->GetParam() - myParam, aDY;
681 if (thePoint->myV.Length() == myV.Length())
682 { // absolutely the same points
683 for(a = 1; a <= myV.Length(); a++)
685 aDY = thePoint->myV.Value(a) - myV.Value(a);
687 myD.SetValue(a, fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);
689 myD.Append( fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);
691 return Standard_True;
693 // between the diffeerent points searching for nearest analogs
695 for(a = 1; a <= myV.Length(); a++)
697 for(b = 1; b <= thePoint->myV.Length(); b++)
699 if (b == 1 || fabs(thePoint->myV.Value(b) - myV.Value(a)) < fabs(aDY))
700 aDY = thePoint->myV.Value(b) - myV.Value(a);
704 if ( fabs(aDX) > gp::Resolution() && fabs(aDY / aDX) < fabs(myD.Value(a)))
705 myD.SetValue(a, aDY / aDX);
711 myD.Append( fabs(aDX) > gp::Resolution() ? aDY/aDX : 0);
715 return Standard_False;
718 //=======================================================================
719 //function : FilterPoints
721 //=======================================================================
722 void GEOMImpl_Fillet1dPoint::FilterPoints(GEOMImpl_Fillet1dPoint* thePoint)
724 Standard_Integer a, b;
725 TColStd_SequenceOfReal aDiffs;
726 Standard_Real aY, aY2, aDX = thePoint->GetParam() - myParam;
727 for(a = 1; a <= myV.Length(); a++)
729 // searching for near point from thePoint
730 Standard_Integer aNear = 0;
731 Standard_Real aDiff = aDX * 10000.;
732 aY = myV.Value(a) + myD.Value(a) * aDX;
733 for(b = 1; b <= thePoint->myV.Length(); b++)
735 // calculate hypothesis value of the Y2 with the constant first and second derivative
736 aY2 = aY + aDX * (thePoint->myD.Value(b) - myD.Value(a)) / 2.0;
737 if (aNear == 0 || fabs(aY2 - thePoint->myV.Value(b)) < fabs(aDiff))
740 aDiff = aY2 - thePoint->myV.Value(b);
746 if (myV.Value(a) * thePoint->myV.Value(aNear) > 0)
747 {// the same sign at the same sides of the interval
748 if (myV.Value(a) * myD.Value(a) > 0)
750 if (fabs(myD.Value(a)) > Precision::Confusion())
755 if (fabs(myV.Value(a)) > fabs(thePoint->myV.Value(aNear)))
756 if (thePoint->myV.Value(aNear) * thePoint->myD.Value(aNear) < 0 &&
757 fabs(thePoint->myD.Value(aNear)) > Precision::Confusion())
767 if (myV.Value(a) * thePoint->myV.Value(aNear) > 0)
769 if ((myV.Value(a) + myD.Value(a) * aDX) * myV.Value(a) > Precision::Confusion() &&
770 (thePoint->myV.Value(aNear) + thePoint->myD.Value(aNear) * aDX) * thePoint->myV.Value(aNear) > Precision::Confusion())
779 if ( fabs(aDX) < gp::Resolution() || fabs(aDiff / aDX) > 1.e+7)
786 { // there is no near: remove it from the list
794 Standard_Boolean aFound = Standard_False;
795 for(b = 1; b <= myNear.Length(); b++)
797 if (myNear.Value(b) == aNear)
799 if (fabs(aDiffs.Value(b)) < fabs(aDiff))
800 { // return this 'near'
801 aFound = Standard_True;
809 { // remove the old 'near'
822 myNear.Append(aNear);
823 aDiffs.Append(aDiff);
829 //=======================================================================
832 //=======================================================================
833 GEOMImpl_Fillet1dPoint* GEOMImpl_Fillet1dPoint::Copy()
835 GEOMImpl_Fillet1dPoint* aCopy = new GEOMImpl_Fillet1dPoint(myParam);
837 for(a = 1; a <= myV.Length(); a++)
839 aCopy->myV.Append(myV.Value(a));
840 aCopy->myD.Append(myD.Value(a));
841 aCopy->myValid.Append(myValid.Value(a));
846 //=======================================================================
847 //function : HasSolution
849 //=======================================================================
850 Standard_Integer GEOMImpl_Fillet1dPoint::HasSolution(const Standard_Real theRadius)
853 for(a = 1; a <= myV.Length(); a++)
855 if (fabs(sqrt(fabs(fabs(myV.Value(a)) + theRadius * theRadius)) - theRadius) < Precision::Confusion() / 10.)
861 //=======================================================================
862 //function : RemoveSolution
864 //=======================================================================
865 void GEOMImpl_Fillet1dPoint::RemoveSolution(Standard_Integer theIndex)
867 myV.Remove(theIndex);
868 myD.Remove(theIndex);
869 myValid.Remove(theIndex);
870 myNear.Remove(theIndex);