-// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-
-// File : GEOMImpl_Fillet1d.cxx
-// Module : GEOMImpl
-//
-#include "GEOMImpl_Fillet1d.hxx"
-
-#include <BRep_Tool.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <BRepBuilderAPI_MakeEdge.hxx>
-#include <ElCLib.hxx>
-#include <ElSLib.hxx>
-#include <gp_Circ.hxx>
-#include <Geom2d_Line.hxx>
-#include <Geom2dAPI_ProjectPointOnCurve.hxx>
-#include <Geom2dAPI_InterCurveCurve.hxx>
-#include <GeomAPI_ProjectPointOnCurve.hxx>
-#include <GeomProjLib.hxx>
-#include <Geom_Circle.hxx>
-#include <Precision.hxx>
-#include <TColStd_ListIteratorOfListOfReal.hxx>
-
-/**
- * class GEOMImpl_Fillet1d
- */
-
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-GEOMImpl_Fillet1d::GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,
- const TopoDS_Edge& theEdge2,
- const gp_Pln& thePlane)
-: myEdgesExchnged( Standard_False )
-{
- myPlane = new Geom_Plane(thePlane);
-
- BRepAdaptor_Curve aBAC1(theEdge1);
- BRepAdaptor_Curve aBAC2(theEdge2);
- if (aBAC1.GetType() < aBAC2.GetType())
- { // first curve must be more complicated
- myEdge1 = theEdge2;
- myEdge2 = theEdge1;
- myEdgesExchnged = Standard_True;
- }
- else
- {
- myEdge1 = theEdge1;
- myEdge2 = theEdge2;
- }
-
- Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(myEdge1, myStart1, myEnd1);
- Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(myEdge2, myStart2, myEnd2);
-
- myCurve1 = GeomProjLib::Curve2d(aCurve1, myStart1, myEnd1, myPlane);
- myCurve2 = GeomProjLib::Curve2d(aCurve2, myStart2, myEnd2, myPlane);
-
- while (myCurve1->IsPeriodic() && myStart1 >= myEnd1)
- myEnd1 += myCurve1->Period();
- while (myCurve2->IsPeriodic() && myStart2 >= myEnd2)
- myEnd2 += myCurve2->Period();
-
- if (aBAC1.GetType() == aBAC2.GetType())
- {
- if (myEnd2 - myStart2 < myEnd1 - myStart1)
- { // first curve must be parametrically shorter
- TopoDS_Edge anEdge = myEdge1;
- myEdge1 = myEdge2;
- myEdge2 = anEdge;
- Handle(Geom2d_Curve) aCurve = myCurve1;
- myCurve1 = myCurve2;
- myCurve2 = aCurve;
- Standard_Real a = myStart1;
- myStart1 = myStart2;
- myStart2 = a;
- a = myEnd1;
- myEnd1 = myEnd2;
- myEnd2 = a;
- myEdgesExchnged = Standard_True;
- }
- }
-}
-
-//=======================================================================
-//function : isRadiusIntersected
-//purpose : local function
-//=======================================================================
-static Standard_Boolean isRadiusIntersected(const Handle(Geom2d_Curve)& theCurve,
- const gp_Pnt2d theStart,
- const gp_Pnt2d theEnd,
- const Standard_Boolean theStartConnected)
-{
- const Standard_Real aTol = Precision::Confusion();
- const Standard_Real anAngTol = Precision::Angular();
- Geom2dAPI_InterCurveCurve anInter(theCurve, new Geom2d_Line(theStart,
- gp_Dir2d(gp_Vec2d(theStart, theEnd))), aTol);
- Standard_Integer a;
- gp_Pnt2d aPoint;
- for(a = anInter.NbPoints(); a > 0; a--)
- {
- aPoint = anInter.Point(a);
- if ( aPoint.Distance(theStart) < aTol && !theStartConnected )
- return Standard_True;
- if (aPoint.Distance(theEnd) < aTol * 200)
- return Standard_True;
- if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
- return Standard_True;
- }
- Handle(Geom2d_Curve) aCurve;
- for(a = anInter.NbSegments(); a > 0; a--)
- {
- anInter.Segment(a, aCurve);
- aPoint = aCurve->Value(aCurve->FirstParameter());
- if (aPoint.Distance(theStart) < aTol)
- if (!theStartConnected)
- return Standard_True;
- if (aPoint.Distance(theEnd) < aTol)
- return Standard_True;
- if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
- return Standard_True;
- aPoint = aCurve->Value(aCurve->LastParameter());
- if (aPoint.Distance(theStart) < aTol)
- if (!theStartConnected)
- return Standard_True;
- if (aPoint.Distance(theEnd) < aTol)
- return Standard_True;
- if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol))
- return Standard_True;
- }
- return Standard_False;
-}
-
-
-//=======================================================================
-//function : fillPoint
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1d::fillPoint(GEOMImpl_Fillet1dPoint* thePoint)
-{
- gp_Pnt2d aPoint;
- gp_Vec2d aVec;
- const Standard_Real aTol = Precision::Confusion();
- myCurve1->D1(thePoint->GetParam(), aPoint, aVec);
- if (aVec.SquareMagnitude() < aTol)
- return;
-
- gp_Vec2d aPerp(((myStartSide)?-1:1) * aVec.Y(), ((myStartSide)?1:-1) * aVec.X());
- aPerp.Normalize();
- aPerp.Multiply(myRadius);
- gp_Pnt2d aCenter = aPoint.Translated(aPerp);
- thePoint->SetCenter(aCenter);
-
- // on the intersection point
- Standard_Boolean aValid = Standard_True;
- Geom2dAPI_ProjectPointOnCurve aProjInt(aPoint, myCurve2);
- if (aProjInt.NbPoints() && aPoint.Distance(aProjInt.NearestPoint()) < aTol)
- aValid = Standard_False;
- else
- aValid = !isRadiusIntersected(myCurve2, aPoint, aCenter, Standard_True);
-
- Geom2dAPI_ProjectPointOnCurve aProj(aCenter, myCurve2);
- Standard_Integer a, aNB = aProj.NbPoints();
- for(a = aNB; a > 0; a--)
- {
- if (aPoint.Distance(aProj.Point(a)) < aTol)
- continue;
-
- Standard_Boolean aValid2 = aValid;
- if (aValid2)
- aValid2 = !isRadiusIntersected(myCurve1, aCenter, aProj.Point(a), Standard_False);
-
- // checking the right parameter
- Standard_Real aParam = aProj.Parameter(a);
- while(myCurve2->IsPeriodic() && aParam < myStart2)
- aParam += myCurve2->Period();
-
- thePoint->AddValue(aProj.Distance(a) * aProj.Distance(a) - myRadius * myRadius,
- (aParam >= myStart2 && aParam <= myEnd2 && aValid2));
- if (fabs(fabs(aProj.Distance(a)) - myRadius) < aTol)
- thePoint->SetParam2(aParam);
- }
-}
-
-//=======================================================================
-//function : fillDiff
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1d::fillDiff(GEOMImpl_Fillet1dPoint* thePoint, Standard_Real theDiffStep, Standard_Boolean theFront)
-{
- GEOMImpl_Fillet1dPoint* aDiff =
- new GEOMImpl_Fillet1dPoint(thePoint->GetParam() + (theFront?(theDiffStep):(-theDiffStep)));
- fillPoint(aDiff);
- if (!thePoint->ComputeDifference(aDiff))
- {
- aDiff->SetParam(thePoint->GetParam() + (theFront?(-theDiffStep):(theDiffStep)));
- fillPoint(aDiff);
- thePoint->ComputeDifference(aDiff);
- }
- delete aDiff;
-}
-
-//=======================================================================
-//function : Perform
-//purpose :
-//=======================================================================
-Standard_Boolean GEOMImpl_Fillet1d::Perform(const Standard_Real theRadius)
-{
- myResultParams.Clear();
- myResultOrientation.Clear();
-
- Standard_Real aNBSteps = 100;
- Geom2dAdaptor_Curve aGAC(myCurve1);
- switch (aGAC.GetType())
- {
- case GeomAbs_Line:
- aNBSteps = 2;
- break;
- case GeomAbs_Circle:
- aNBSteps = 4;
- break;
- case GeomAbs_Ellipse:
- aNBSteps = 5;
- break;
- case GeomAbs_BezierCurve:
- case GeomAbs_BSplineCurve:
- aNBSteps = 2 + aGAC.Degree() * aGAC.NbPoles();
- break;
- default: // unknown: maximum
- aNBSteps = 100;
- }
-
- myRadius = theRadius;
- Standard_Real aParam, aStep, aDStep;
- aStep = (myEnd1 - myStart1) / aNBSteps;
- aDStep = aStep/1000.;
-
- Standard_Integer aCycle;
- for(aCycle = 2, myStartSide = Standard_False; aCycle; myStartSide = !myStartSide, aCycle--)
- {
- GEOMImpl_Fillet1dPoint *aLeft = NULL, *aRight = NULL;
-
- for(aParam = myStart1 + aStep; aParam < myEnd1 || fabs(myEnd1 - aParam) < Precision::Confusion(); aParam += aStep)
- {
- if (!aLeft)
- {
- aLeft = new GEOMImpl_Fillet1dPoint(aParam - aStep);
- fillPoint(aLeft);
- fillDiff(aLeft, aDStep, Standard_True);
- }
-
- aRight = new GEOMImpl_Fillet1dPoint(aParam);
- fillPoint(aRight);
- fillDiff(aRight, aDStep, Standard_False);
-
- aLeft->FilterPoints(aRight);
- performNewton(aLeft, aRight);
-
- delete aLeft;
- aLeft = aRight;
- }
- delete aLeft;
- }
-
- if (myResultParams.Extent())
- return Standard_True;
-
- return Standard_False;
-}
-
-//=======================================================================
-//function : processPoint
-//purpose :
-//=======================================================================
-Standard_Boolean GEOMImpl_Fillet1d::processPoint(GEOMImpl_Fillet1dPoint* theLeft,
- GEOMImpl_Fillet1dPoint* theRight,
- Standard_Real theParameter)
-{
- if (theParameter >= theLeft->GetParam() && theParameter < theRight->GetParam())
- {
- Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();
- if (theParameter - theLeft->GetParam() < aDX / 100.)
- {
- theParameter = theLeft->GetParam() + aDX / 100.;
- }
- if (theRight->GetParam() - theParameter < aDX / 100.)
- {
- theParameter = theRight->GetParam() - aDX / 100.;
- }
-
- GEOMImpl_Fillet1dPoint* aPoint1 = theLeft->Copy();
- GEOMImpl_Fillet1dPoint* aPoint2 = new GEOMImpl_Fillet1dPoint(theParameter);
- fillPoint(aPoint2);
- fillDiff(aPoint2, aDX / 10., Standard_True);
-
- aPoint1->FilterPoints(aPoint2);
- performNewton(aPoint1, aPoint2);
- aPoint2->FilterPoints(theRight);
- performNewton(aPoint2, theRight);
-
- delete aPoint1;
- delete aPoint2;
- return Standard_True;
- }
-
- return Standard_False;
-}
-
-//=======================================================================
-//function : performNewton
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1d::performNewton(GEOMImpl_Fillet1dPoint* theLeft,
- GEOMImpl_Fillet1dPoint* theRight)
-{
- Standard_Integer a;
- // check the left: if this is solution store it and remove it from the list of researching points of theLeft
- a = theLeft->HasSolution(myRadius);
- if (a)
- {
- if (theLeft->IsValid(a))
- {
- myResultParams.Append(theLeft->GetParam());
- myResultOrientation.Append(myStartSide);
- }
- return;
- }
-
- Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();
- if ( aDX < Precision::Confusion() / 1000000.)
- {
- a = theRight->HasSolution(myRadius);
- if (a)
- if (theRight->IsValid(a))
- {
- myResultParams.Append(theRight->GetParam());
- myResultOrientation.Append(myStartSide);
- }
- return;
- }
-
- for(a = 1; a <= theLeft->GetNBValues(); a++)
- {
- Standard_Integer aNear = theLeft->GetNear(a);
-
- Standard_Real aA = (theRight->GetDiff(aNear) - theLeft->GetDiff(a)) / aDX;
- Standard_Real aB = theLeft->GetDiff(a) - aA * theLeft->GetParam();
- Standard_Real aC = theLeft->GetValue(a) - theLeft->GetDiff(a) * theLeft->GetParam() +
- aA * theLeft->GetParam() * theLeft->GetParam() / 2.0;
- Standard_Real aDet = aB * aB - 2.0 * aA * aC;
-
- if ( fabs(aDet) < gp::Resolution() )
- continue;
-
- if (fabs(aA) < Precision::Confusion())
- { // linear case
- if (fabs(aB) > 10e-20)
- {
- Standard_Real aX0 = - aC / aB; // use extremum
- if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())
- processPoint(theLeft, theRight, aX0);
- }
- else
- {
- processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
- }
- }
- else
- {
- if (fabs(aB) > fabs(aDet * 1000000.))
- { // possible floating point operations accurancy errors
- processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
- }
- else
- {
- if (aDet > 0)
- { // two solutions
- aDet = sqrt(aDet);
- Standard_Boolean aRes = processPoint(theLeft, theRight, (- aB + aDet) / aA);
- if (!aRes)
- aRes = processPoint(theLeft, theRight, (- aB - aDet) / aA);
- if (!aRes)
- processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
- }
- else
- {
- Standard_Real aX0 = - aB / aA; // use extremum
- if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())
- processPoint(theLeft, theRight, aX0);
- else
- processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise
- }
- }
- }
- }
-}
-
-//=======================================================================
-//function : Result
-//purpose :
-//=======================================================================
-TopoDS_Edge GEOMImpl_Fillet1d::Result(const gp_Pnt& thePoint,
- TopoDS_Edge& theEdge1,
- TopoDS_Edge& theEdge2)
-{
- TopoDS_Edge aResult;
- gp_Pnt2d aTargetPoint2d;
- Standard_Real aX, aY;
- ElSLib::PlaneParameters(myPlane->Pln().Position(), thePoint, aX, aY);
- aTargetPoint2d.SetCoord(aX, aY);
-
- // choose the nearest circle
- Standard_Real aDistance, aP;
- GEOMImpl_Fillet1dPoint *aNearest;
- Standard_Integer a;
- TColStd_ListIteratorOfListOfReal anIter(myResultParams);
- for(aNearest = NULL, a = 1; anIter.More(); anIter.Next(), a++)
- {
- myStartSide = (myResultOrientation.Value(a)) ? Standard_True : Standard_False;
- GEOMImpl_Fillet1dPoint *aPoint = new GEOMImpl_Fillet1dPoint(anIter.Value());
- fillPoint(aPoint);
- if (!aPoint->HasSolution(myRadius))
- continue;
- aP = fabs(aPoint->GetCenter().Distance(aTargetPoint2d) - myRadius);
- if (!aNearest || aP < aDistance)
- {
- aNearest = aPoint;
- aDistance = aP;
- }
- else
- {
- delete aPoint;
- }
- }
-
- if (!aNearest)
- return aResult;
-
- // create circle edge
- gp_Pnt aCenter = ElSLib::PlaneValue(aNearest->GetCenter().X(),
- aNearest->GetCenter().Y(),
- myPlane->Pln().Position());
- Handle(Geom_Circle) aCircle =
- new Geom_Circle(gp_Ax2(aCenter, myPlane->Pln().Axis().Direction()), myRadius);
- gp_Pnt2d aPoint2d1, aPoint2d2;
- myCurve1->D0(aNearest->GetParam(), aPoint2d1);
- myCurve2->D0(aNearest->GetParam2(), aPoint2d2);
- gp_Pnt aPoint1 = ElSLib::PlaneValue(aPoint2d1.X(), aPoint2d1.Y(), myPlane->Pln().Position());
- gp_Pnt aPoint2 = ElSLib::PlaneValue(aPoint2d2.X(), aPoint2d2.Y(), myPlane->Pln().Position());
-
- GeomAPI_ProjectPointOnCurve aProj(thePoint, aCircle);
- Standard_Real aTarGetParam = aProj.LowerDistanceParameter();
- gp_Pnt aPointOnCircle = aProj.NearestPoint();
-
- // Check extrema point manually, because there is a bug in Open CASCADE
- // in calculation of nearest point to a circle near the parameter 0.0
- gp_Pnt p0 = ElCLib::Value(0.0, aCircle->Circ());
- if (p0.Distance(thePoint) < aPointOnCircle.Distance(thePoint))
- {
- aTarGetParam = 0.0;
- aPointOnCircle = p0;
- }
-
- aProj.Perform(aPoint1);
- Standard_Real aParam1 = aProj.LowerDistanceParameter();
- aProj.Perform(aPoint2);
- Standard_Real aParam2 = aProj.LowerDistanceParameter();
- Standard_Boolean aIsOut = ((aParam1 < aTarGetParam && aParam2 < aTarGetParam) ||
- (aParam1 > aTarGetParam && aParam2 > aTarGetParam));
- if (aParam1 > aParam2)
- aIsOut = !aIsOut;
- BRepBuilderAPI_MakeEdge aBuilder(aCircle->Circ(),
- aIsOut ? aParam2 : aParam1,
- aIsOut? aParam1 : aParam2);
- aResult = aBuilder.Edge();
-
- // divide edges
- Standard_Real aStart, anEnd;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(myEdge1, aStart, anEnd);
- gp_Vec aDir;
- aCurve->D1(aNearest->GetParam(), aPoint1, aDir);
-
- gp_Vec aCircleDir;
- aCircle->D1(aParam1, aPoint1, aCircleDir);
- if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ aIsOut)
- aStart = aNearest->GetParam();
- else
- anEnd = aNearest->GetParam();
-
- if (fabs(aStart - anEnd) > Precision::Confusion())
- {
- //Divide edge
- BRepBuilderAPI_MakeEdge aDivider1(aCurve, aStart, anEnd);
- if (myEdgesExchnged)
- theEdge2 = aDivider1.Edge();
- else
- theEdge1 = aDivider1.Edge();
- }
-
- aCurve = BRep_Tool::Curve(myEdge2, aStart, anEnd);
- aCurve->D1(aNearest->GetParam2(), aPoint2, aDir);
-
- aCircle->D1(aParam2, aPoint2, aCircleDir);
- if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ (!aIsOut))
- aStart = aNearest->GetParam2();
- else
- anEnd = aNearest->GetParam2();
-
- if (fabs(aStart - anEnd) > Precision::Confusion())
- {
- BRepBuilderAPI_MakeEdge aDivider2(aCurve, aStart, anEnd);
- if (myEdgesExchnged)
- theEdge1 = aDivider2.Edge();
- else
- theEdge2 = aDivider2.Edge();
- }
-
- delete aNearest;
- return aResult;
-}
-
-//=======================================================================
-//function : AddValue
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1dPoint::AddValue(Standard_Real theValue, Standard_Boolean theValid)
-{
- Standard_Integer a;
- for(a = 1; a <= myV.Length(); a++)
- {
- if (theValue < myV.Value(a))
- {
- myV.InsertBefore(a, theValue);
- myValid.InsertBefore(a, (Standard_Integer)theValid);
- return;
- }
- }
- myV.Append(theValue);
- myValid.Append((Standard_Integer)theValid);
-}
-
-//=======================================================================
-//function : ComputeDifference
-//purpose :
-//=======================================================================
-Standard_Boolean GEOMImpl_Fillet1dPoint::ComputeDifference(GEOMImpl_Fillet1dPoint* thePoint)
-{
- Standard_Integer a;
- Standard_Boolean aDiffsSet = (myD.Length() != 0);
- Standard_Real aDX = thePoint->GetParam() - myParam, aDY;
- if (thePoint->myV.Length() == myV.Length())
- { // absolutely the same points
- for(a = 1; a <= myV.Length(); a++)
- {
- aDY = thePoint->myV.Value(a) - myV.Value(a);
- if ( aDiffsSet )
- myD.SetValue(a, fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);
- else
- myD.Append( fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);
- }
- return Standard_True;
- }
- // between the diffeerent points searching for nearest analogs
- Standard_Integer b;
- for(a = 1; a <= myV.Length(); a++)
- {
- for(b = 1; b <= thePoint->myV.Length(); b++)
- {
- if (b == 1 || fabs(thePoint->myV.Value(b) - myV.Value(a)) < fabs(aDY))
- aDY = thePoint->myV.Value(b) - myV.Value(a);
- }
- if (aDiffsSet)
- {
- if ( fabs(aDX) > gp::Resolution() && fabs(aDY / aDX) < fabs(myD.Value(a)))
- myD.SetValue(a, aDY / aDX);
- else
- myD.SetValue(a, 0);
- }
- else
- {
- myD.Append( fabs(aDX) > gp::Resolution() ? aDY/aDX : 0);
- }
- }
-
- return Standard_False;
-}
-
-//=======================================================================
-//function : FilterPoints
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1dPoint::FilterPoints(GEOMImpl_Fillet1dPoint* thePoint)
-{
- Standard_Integer a, b;
- TColStd_SequenceOfReal aDiffs;
- Standard_Real aY, aY2, aDX = thePoint->GetParam() - myParam;
- for(a = 1; a <= myV.Length(); a++)
- {
- // searching for near point from thePoint
- Standard_Integer aNear = 0;
- Standard_Real aDiff = aDX * 10000.;
- aY = myV.Value(a) + myD.Value(a) * aDX;
- for(b = 1; b <= thePoint->myV.Length(); b++)
- {
- // calculate hypothesis value of the Y2 with the constant first and second derivative
- aY2 = aY + aDX * (thePoint->myD.Value(b) - myD.Value(a)) / 2.0;
- if (aNear == 0 || fabs(aY2 - thePoint->myV.Value(b)) < fabs(aDiff))
- {
- aNear = b;
- aDiff = aY2 - thePoint->myV.Value(b);
- }
- }//for b...
-
- if (aNear)
- {
- if (myV.Value(a) * thePoint->myV.Value(aNear) > 0)
- {// the same sign at the same sides of the interval
- if (myV.Value(a) * myD.Value(a) > 0)
- {
- if (fabs(myD.Value(a)) > Precision::Confusion())
- aNear = 0;
- }
- else
- {
- if (fabs(myV.Value(a)) > fabs(thePoint->myV.Value(aNear)))
- if (thePoint->myV.Value(aNear) * thePoint->myD.Value(aNear) < 0 &&
- fabs(thePoint->myD.Value(aNear)) > Precision::Confusion())
- {
- aNear = 0;
- }
- }
- }
- }
-
- if (aNear)
- {
- if (myV.Value(a) * thePoint->myV.Value(aNear) > 0)
- {
- if ((myV.Value(a) + myD.Value(a) * aDX) * myV.Value(a) > Precision::Confusion() &&
- (thePoint->myV.Value(aNear) + thePoint->myD.Value(aNear) * aDX) * thePoint->myV.Value(aNear) > Precision::Confusion())
- {
- aNear = 0;
- }
- }
- }
-
- if (aNear)
- {
- if ( fabs(aDX) < gp::Resolution() || fabs(aDiff / aDX) > 1.e+7)
- {
- aNear = 0;
- }
- }
-
- if (aNear == 0)
- { // there is no near: remove it from the list
- myV.Remove(a);
- myD.Remove(a);
- myValid.Remove(a);
- a--;
- }
- else
- {
- Standard_Boolean aFound = Standard_False;
- for(b = 1; b <= myNear.Length(); b++)
- {
- if (myNear.Value(b) == aNear)
- {
- if (fabs(aDiffs.Value(b)) < fabs(aDiff))
- { // return this 'near'
- aFound = Standard_True;
- myV.Remove(a);
- myD.Remove(a);
- myValid.Remove(a);
- a--;
- break;
- }
- else
- { // remove the old 'near'
- myV.Remove(b);
- myD.Remove(b);
- myValid.Remove(b);
- myNear.Remove(b);
- aDiffs.Remove(b);
- a--;
- break;
- }
- }
- }//for b...
- if (!aFound)
- {
- myNear.Append(aNear);
- aDiffs.Append(aDiff);
- }
- }
- }//for a...
-}
-
-//=======================================================================
-//function : Copy
-//purpose :
-//=======================================================================
-GEOMImpl_Fillet1dPoint* GEOMImpl_Fillet1dPoint::Copy()
-{
- GEOMImpl_Fillet1dPoint* aCopy = new GEOMImpl_Fillet1dPoint(myParam);
- Standard_Integer a;
- for(a = 1; a <= myV.Length(); a++)
- {
- aCopy->myV.Append(myV.Value(a));
- aCopy->myD.Append(myD.Value(a));
- aCopy->myValid.Append(myValid.Value(a));
- }
- return aCopy;
-}
-
-//=======================================================================
-//function : HasSolution
-//purpose :
-//=======================================================================
-Standard_Integer GEOMImpl_Fillet1dPoint::HasSolution(const Standard_Real theRadius)
-{
- Standard_Integer a;
- for(a = 1; a <= myV.Length(); a++)
- {
- if (fabs(sqrt(fabs(fabs(myV.Value(a)) + theRadius * theRadius)) - theRadius) < Precision::Confusion() / 10.)
- return a;
- }
- return 0;
-}
-
-//=======================================================================
-//function : RemoveSolution
-//purpose :
-//=======================================================================
-void GEOMImpl_Fillet1dPoint::RemoveSolution(Standard_Integer theIndex)
-{
- myV.Remove(theIndex);
- myD.Remove(theIndex);
- myValid.Remove(theIndex);
- myNear.Remove(theIndex);
-}
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE\r
+//\r
+// This library is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU Lesser General Public\r
+// License as published by the Free Software Foundation; either\r
+// version 2.1 of the License.\r
+//\r
+// This library is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+// Lesser General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU Lesser General Public\r
+// License along with this library; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+//\r
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com\r
+//\r
+\r
+// File : GEOMImpl_Fillet1d.cxx\r
+// Module : GEOMImpl\r
+//\r
+#include "GEOMImpl_Fillet1d.hxx"\r
+\r
+#include <BRep_Tool.hxx>\r
+#include <BRepAdaptor_Curve.hxx>\r
+#include <BRepBuilderAPI_MakeEdge.hxx>\r
+#include <ElCLib.hxx>\r
+#include <ElSLib.hxx>\r
+#include <gp_Circ.hxx>\r
+#include <Geom2d_Line.hxx>\r
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>\r
+#include <Geom2dAPI_InterCurveCurve.hxx>\r
+#include <GeomAPI_ProjectPointOnCurve.hxx>\r
+#include <GeomProjLib.hxx>\r
+#include <Geom_Circle.hxx>\r
+#include <Precision.hxx>\r
+#include <TColStd_ListIteratorOfListOfReal.hxx>\r
+\r
+/**\r
+ * class GEOMImpl_Fillet1d\r
+ */\r
+\r
+\r
+//=======================================================================\r
+//function : Constructor\r
+//purpose : \r
+//=======================================================================\r
+GEOMImpl_Fillet1d::GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,\r
+ const TopoDS_Edge& theEdge2,\r
+ const gp_Pln& thePlane)\r
+: myEdgesExchnged( Standard_False )\r
+{\r
+ myPlane = new Geom_Plane(thePlane);\r
+\r
+ BRepAdaptor_Curve aBAC1(theEdge1);\r
+ BRepAdaptor_Curve aBAC2(theEdge2);\r
+ if (aBAC1.GetType() < aBAC2.GetType()) \r
+ { // first curve must be more complicated\r
+ myEdge1 = theEdge2;\r
+ myEdge2 = theEdge1;\r
+ myEdgesExchnged = Standard_True;\r
+ } \r
+ else\r
+ {\r
+ myEdge1 = theEdge1;\r
+ myEdge2 = theEdge2;\r
+ }\r
+\r
+ Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(myEdge1, myStart1, myEnd1);\r
+ Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(myEdge2, myStart2, myEnd2);\r
+\r
+ myCurve1 = GeomProjLib::Curve2d(aCurve1, myStart1, myEnd1, myPlane);\r
+ myCurve2 = GeomProjLib::Curve2d(aCurve2, myStart2, myEnd2, myPlane);\r
+\r
+ while (myCurve1->IsPeriodic() && myStart1 >= myEnd1)\r
+ myEnd1 += myCurve1->Period();\r
+ while (myCurve2->IsPeriodic() && myStart2 >= myEnd2)\r
+ myEnd2 += myCurve2->Period();\r
+ \r
+ if (aBAC1.GetType() == aBAC2.GetType()) \r
+ {\r
+ if (myEnd2 - myStart2 < myEnd1 - myStart1) \r
+ { // first curve must be parametrically shorter\r
+ TopoDS_Edge anEdge = myEdge1;\r
+ myEdge1 = myEdge2;\r
+ myEdge2 = anEdge;\r
+ Handle(Geom2d_Curve) aCurve = myCurve1;\r
+ myCurve1 = myCurve2;\r
+ myCurve2 = aCurve;\r
+ Standard_Real a = myStart1;\r
+ myStart1 = myStart2;\r
+ myStart2 = a;\r
+ a = myEnd1;\r
+ myEnd1 = myEnd2;\r
+ myEnd2 = a;\r
+ myEdgesExchnged = Standard_True;\r
+ }\r
+ }\r
+}\r
+\r
+//=======================================================================\r
+//function : isRadiusIntersected\r
+//purpose : local function\r
+//=======================================================================\r
+static Standard_Boolean isRadiusIntersected(const Handle(Geom2d_Curve)& theCurve,\r
+ const gp_Pnt2d theStart,\r
+ const gp_Pnt2d theEnd,\r
+ const Standard_Boolean theStartConnected) \r
+{\r
+ const Standard_Real aTol = Precision::Confusion();\r
+ const Standard_Real anAngTol = Precision::Angular();\r
+ Geom2dAPI_InterCurveCurve anInter(theCurve, new Geom2d_Line(theStart,\r
+ gp_Dir2d(gp_Vec2d(theStart, theEnd))), aTol);\r
+ Standard_Integer a;\r
+ gp_Pnt2d aPoint;\r
+ for(a = anInter.NbPoints(); a > 0; a--) \r
+ {\r
+ aPoint = anInter.Point(a);\r
+ if ( aPoint.Distance(theStart) < aTol && !theStartConnected )\r
+ return Standard_True;\r
+ if (aPoint.Distance(theEnd) < aTol * 200)\r
+ return Standard_True;\r
+ if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) \r
+ return Standard_True;\r
+ }\r
+ Handle(Geom2d_Curve) aCurve;\r
+ for(a = anInter.NbSegments(); a > 0; a--) \r
+ {\r
+ anInter.Segment(a, aCurve);\r
+ aPoint = aCurve->Value(aCurve->FirstParameter());\r
+ if (aPoint.Distance(theStart) < aTol) \r
+ if (!theStartConnected) \r
+ return Standard_True;\r
+ if (aPoint.Distance(theEnd) < aTol) \r
+ return Standard_True;\r
+ if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) \r
+ return Standard_True;\r
+ aPoint = aCurve->Value(aCurve->LastParameter());\r
+ if (aPoint.Distance(theStart) < aTol) \r
+ if (!theStartConnected) \r
+ return Standard_True;\r
+ if (aPoint.Distance(theEnd) < aTol) \r
+ return Standard_True;\r
+ if (gp_Vec2d(aPoint, theStart).IsOpposite(gp_Vec2d(aPoint, theEnd), anAngTol)) \r
+ return Standard_True;\r
+ }\r
+ return Standard_False;\r
+}\r
+\r
+\r
+//=======================================================================\r
+//function : fillPoint\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1d::fillPoint(GEOMImpl_Fillet1dPoint* thePoint) \r
+{\r
+ gp_Pnt2d aPoint;\r
+ gp_Vec2d aVec;\r
+ const Standard_Real aTol = Precision::Confusion();\r
+ myCurve1->D1(thePoint->GetParam(), aPoint, aVec);\r
+ if (aVec.SquareMagnitude() < aTol) \r
+ return;\r
+ \r
+ gp_Vec2d aPerp(((myStartSide)?-1:1) * aVec.Y(), ((myStartSide)?1:-1) * aVec.X());\r
+ aPerp.Normalize();\r
+ aPerp.Multiply(myRadius);\r
+ gp_Pnt2d aCenter = aPoint.Translated(aPerp);\r
+ thePoint->SetCenter(aCenter);\r
+\r
+ // on the intersection point\r
+ Standard_Boolean aValid = Standard_True;\r
+ Geom2dAPI_ProjectPointOnCurve aProjInt(aPoint, myCurve2);\r
+ if (aProjInt.NbPoints() && aPoint.Distance(aProjInt.NearestPoint()) < aTol) \r
+ aValid = Standard_False;\r
+ else \r
+ aValid = !isRadiusIntersected(myCurve2, aPoint, aCenter, Standard_True);\r
+ \r
+ Geom2dAPI_ProjectPointOnCurve aProj(aCenter, myCurve2);\r
+ Standard_Integer a, aNB = aProj.NbPoints();\r
+ for(a = aNB; a > 0; a--) \r
+ {\r
+ if (aPoint.Distance(aProj.Point(a)) < aTol) \r
+ continue;\r
+ \r
+ Standard_Boolean aValid2 = aValid;\r
+ if (aValid2) \r
+ aValid2 = !isRadiusIntersected(myCurve1, aCenter, aProj.Point(a), Standard_False);\r
+\r
+ // checking the right parameter\r
+ Standard_Real aParam = aProj.Parameter(a);\r
+ while(myCurve2->IsPeriodic() && aParam < myStart2)\r
+ aParam += myCurve2->Period();\r
+\r
+ thePoint->AddValue(aProj.Distance(a) * aProj.Distance(a) - myRadius * myRadius,\r
+ (aParam >= myStart2 && aParam <= myEnd2 && aValid2));\r
+ if (fabs(fabs(aProj.Distance(a)) - myRadius) < aTol)\r
+ thePoint->SetParam2(aParam);\r
+ }\r
+}\r
+\r
+//=======================================================================\r
+//function : fillDiff\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1d::fillDiff(GEOMImpl_Fillet1dPoint* thePoint, Standard_Real theDiffStep, Standard_Boolean theFront) \r
+{\r
+ GEOMImpl_Fillet1dPoint* aDiff =\r
+ new GEOMImpl_Fillet1dPoint(thePoint->GetParam() + (theFront?(theDiffStep):(-theDiffStep)));\r
+ fillPoint(aDiff);\r
+ if (!thePoint->ComputeDifference(aDiff))\r
+ {\r
+ aDiff->SetParam(thePoint->GetParam() + (theFront?(-theDiffStep):(theDiffStep)));\r
+ fillPoint(aDiff);\r
+ thePoint->ComputeDifference(aDiff);\r
+ }\r
+ delete aDiff;\r
+}\r
+\r
+//=======================================================================\r
+//function : Perform\r
+//purpose : \r
+//=======================================================================\r
+Standard_Boolean GEOMImpl_Fillet1d::Perform(const Standard_Real theRadius) \r
+{\r
+ myDegreeOfRecursion = 0;\r
+ myResultParams.Clear();\r
+ myResultOrientation.Clear();\r
+\r
+ Standard_Real aNBSteps = 100;\r
+ Geom2dAdaptor_Curve aGAC(myCurve1);\r
+ switch (aGAC.GetType()) \r
+ {\r
+ case GeomAbs_Line:\r
+ aNBSteps = 2;\r
+ break;\r
+ case GeomAbs_Circle:\r
+ aNBSteps = 4;\r
+ break;\r
+ case GeomAbs_Ellipse:\r
+ aNBSteps = 5;\r
+ break;\r
+ case GeomAbs_BezierCurve:\r
+ case GeomAbs_BSplineCurve:\r
+ aNBSteps = 2 + aGAC.Degree() * aGAC.NbPoles();\r
+ break;\r
+ default: // unknown: maximum\r
+ aNBSteps = 100;\r
+ }\r
+\r
+ myRadius = theRadius;\r
+ Standard_Real aParam, aStep, aDStep;\r
+ aStep = (myEnd1 - myStart1) / aNBSteps;\r
+ aDStep = aStep/1000.;\r
+\r
+ Standard_Integer aCycle;\r
+ for(aCycle = 2, myStartSide = Standard_False; aCycle; myStartSide = !myStartSide, aCycle--) \r
+ {\r
+ GEOMImpl_Fillet1dPoint *aLeft = NULL, *aRight = NULL;\r
+ \r
+ for(aParam = myStart1 + aStep; aParam < myEnd1 || fabs(myEnd1 - aParam) < Precision::Confusion(); aParam += aStep) \r
+ {\r
+ if (!aLeft) \r
+ {\r
+ aLeft = new GEOMImpl_Fillet1dPoint(aParam - aStep);\r
+ fillPoint(aLeft);\r
+ fillDiff(aLeft, aDStep, Standard_True);\r
+ }\r
+ \r
+ aRight = new GEOMImpl_Fillet1dPoint(aParam);\r
+ fillPoint(aRight);\r
+ fillDiff(aRight, aDStep, Standard_False);\r
+ \r
+ aLeft->FilterPoints(aRight);\r
+ performNewton(aLeft, aRight);\r
+ \r
+ delete aLeft;\r
+ aLeft = aRight;\r
+ }\r
+ delete aLeft;\r
+ }\r
+\r
+ if (myResultParams.Extent()) \r
+ return Standard_True;\r
+ \r
+ return Standard_False;\r
+}\r
+\r
+//=======================================================================\r
+//function : processPoint\r
+//purpose : \r
+//=======================================================================\r
+Standard_Boolean GEOMImpl_Fillet1d::processPoint(GEOMImpl_Fillet1dPoint* theLeft,\r
+ GEOMImpl_Fillet1dPoint* theRight,\r
+ Standard_Real theParameter) \r
+{\r
+ if (theParameter >= theLeft->GetParam() && theParameter < theRight->GetParam()) \r
+ {\r
+ Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();\r
+ if (theParameter - theLeft->GetParam() < aDX / 100.) \r
+ {\r
+ theParameter = theLeft->GetParam() + aDX / 100.;\r
+ }\r
+ if (theRight->GetParam() - theParameter < aDX / 100.)\r
+ {\r
+ theParameter = theRight->GetParam() - aDX / 100.;\r
+ }\r
+\r
+ // Protection on infinite loop.\r
+ myDegreeOfRecursion++;\r
+ Standard_Real diffx = 0.001 * aDX;\r
+ if (myDegreeOfRecursion > 1000)\r
+ {\r
+ diffx *= 10.0;\r
+ if (myDegreeOfRecursion > 10000)\r
+ {\r
+ diffx *= 10.0;\r
+ if (myDegreeOfRecursion > 100000)\r
+ {\r
+ return Standard_True;\r
+ }\r
+ }\r
+ }\r
+\r
+ GEOMImpl_Fillet1dPoint* aPoint1 = theLeft->Copy();\r
+ GEOMImpl_Fillet1dPoint* aPoint2 = new GEOMImpl_Fillet1dPoint(theParameter);\r
+ fillPoint(aPoint2);\r
+ fillDiff(aPoint2, diffx, Standard_True);\r
+ \r
+ aPoint1->FilterPoints(aPoint2);\r
+ performNewton(aPoint1, aPoint2);\r
+ aPoint2->FilterPoints(theRight);\r
+ performNewton(aPoint2, theRight);\r
+\r
+ delete aPoint1;\r
+ delete aPoint2;\r
+ return Standard_True;\r
+ }\r
+\r
+ return Standard_False;\r
+}\r
+\r
+//=======================================================================\r
+//function : performNewton\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1d::performNewton(GEOMImpl_Fillet1dPoint* theLeft,\r
+ GEOMImpl_Fillet1dPoint* theRight)\r
+{\r
+ Standard_Integer a;\r
+ // check the left: if this is solution store it and remove it from the list of researching points of theLeft\r
+ a = theLeft->HasSolution(myRadius);\r
+ if (a) \r
+ {\r
+ if (theLeft->IsValid(a)) \r
+ {\r
+ myResultParams.Append(theLeft->GetParam());\r
+ myResultOrientation.Append(myStartSide);\r
+ }\r
+ return;\r
+ }\r
+\r
+ Standard_Real aDX = theRight->GetParam() - theLeft->GetParam();\r
+ if ( aDX < Precision::Confusion() / 1000000.) \r
+ {\r
+ a = theRight->HasSolution(myRadius);\r
+ if (a)\r
+ if (theRight->IsValid(a)) \r
+ {\r
+ myResultParams.Append(theRight->GetParam());\r
+ myResultOrientation.Append(myStartSide);\r
+ }\r
+ return;\r
+ }\r
+\r
+ for(a = 1; a <= theLeft->GetNBValues(); a++) \r
+ {\r
+ Standard_Integer aNear = theLeft->GetNear(a);\r
+ \r
+ Standard_Real aA = (theRight->GetDiff(aNear) - theLeft->GetDiff(a)) / aDX;\r
+ Standard_Real aB = theLeft->GetDiff(a) - aA * theLeft->GetParam();\r
+ Standard_Real aC = theLeft->GetValue(a) - theLeft->GetDiff(a) * theLeft->GetParam() + \r
+ aA * theLeft->GetParam() * theLeft->GetParam() / 2.0;\r
+ Standard_Real aDet = aB * aB - 2.0 * aA * aC;\r
+\r
+ if ( fabs(aDet) < gp::Resolution() )\r
+ continue;\r
+ \r
+ if (fabs(aA) < Precision::Confusion()) \r
+ { // linear case\r
+ if (fabs(aB) > 10e-20) \r
+ {\r
+ Standard_Real aX0 = - aC / aB; // use extremum\r
+ if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())\r
+ processPoint(theLeft, theRight, aX0);\r
+ }\r
+ else \r
+ {\r
+ processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise\r
+ }\r
+ } \r
+ else\r
+ {\r
+ if (fabs(aB) > fabs(aDet * 1000000.)) \r
+ { // possible floating point operations accurancy errors\r
+ processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise\r
+ } \r
+ else\r
+ {\r
+ if (aDet > 0) \r
+ { // two solutions\r
+ aDet = sqrt(aDet);\r
+ Standard_Boolean aRes = processPoint(theLeft, theRight, (- aB + aDet) / aA);\r
+ if (!aRes) \r
+ aRes = processPoint(theLeft, theRight, (- aB - aDet) / aA);\r
+ if (!aRes) \r
+ processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise\r
+ } \r
+ else \r
+ {\r
+ Standard_Real aX0 = - aB / aA; // use extremum\r
+ if (aX0 > theLeft->GetParam() && aX0 < theRight->GetParam())\r
+ processPoint(theLeft, theRight, aX0);\r
+ else \r
+ processPoint(theLeft, theRight, theLeft->GetParam() + aDX / 2.0); // linear division otherwise\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+//=======================================================================\r
+//function : Result\r
+//purpose : \r
+//=======================================================================\r
+TopoDS_Edge GEOMImpl_Fillet1d::Result(const gp_Pnt& thePoint,\r
+ TopoDS_Edge& theEdge1,\r
+ TopoDS_Edge& theEdge2) \r
+{\r
+ TopoDS_Edge aResult;\r
+ gp_Pnt2d aTargetPoint2d;\r
+ Standard_Real aX, aY;\r
+ ElSLib::PlaneParameters(myPlane->Pln().Position(), thePoint, aX, aY);\r
+ aTargetPoint2d.SetCoord(aX, aY);\r
+ \r
+ // choose the nearest circle\r
+ Standard_Real aDistance, aP;\r
+ GEOMImpl_Fillet1dPoint *aNearest;\r
+ Standard_Integer a;\r
+ TColStd_ListIteratorOfListOfReal anIter(myResultParams);\r
+ for(aNearest = NULL, a = 1; anIter.More(); anIter.Next(), a++) \r
+ {\r
+ myStartSide = (myResultOrientation.Value(a)) ? Standard_True : Standard_False;\r
+ GEOMImpl_Fillet1dPoint *aPoint = new GEOMImpl_Fillet1dPoint(anIter.Value());\r
+ fillPoint(aPoint);\r
+ if (!aPoint->HasSolution(myRadius)) \r
+ continue;\r
+ aP = fabs(aPoint->GetCenter().Distance(aTargetPoint2d) - myRadius);\r
+ if (!aNearest || aP < aDistance) \r
+ {\r
+ aNearest = aPoint;\r
+ aDistance = aP;\r
+ } \r
+ else \r
+ {\r
+ delete aPoint;\r
+ }\r
+ }\r
+ \r
+ if (!aNearest) \r
+ return aResult;\r
+ \r
+ // create circle edge\r
+ gp_Pnt aCenter = ElSLib::PlaneValue(aNearest->GetCenter().X(),\r
+ aNearest->GetCenter().Y(),\r
+ myPlane->Pln().Position());\r
+ Handle(Geom_Circle) aCircle =\r
+ new Geom_Circle(gp_Ax2(aCenter, myPlane->Pln().Axis().Direction()), myRadius);\r
+ gp_Pnt2d aPoint2d1, aPoint2d2;\r
+ myCurve1->D0(aNearest->GetParam(), aPoint2d1);\r
+ myCurve2->D0(aNearest->GetParam2(), aPoint2d2);\r
+ gp_Pnt aPoint1 = ElSLib::PlaneValue(aPoint2d1.X(), aPoint2d1.Y(), myPlane->Pln().Position());\r
+ gp_Pnt aPoint2 = ElSLib::PlaneValue(aPoint2d2.X(), aPoint2d2.Y(), myPlane->Pln().Position());\r
+\r
+ GeomAPI_ProjectPointOnCurve aProj(thePoint, aCircle);\r
+ Standard_Real aTarGetParam = aProj.LowerDistanceParameter();\r
+ gp_Pnt aPointOnCircle = aProj.NearestPoint();\r
+\r
+ // Check extrema point manually, because there is a bug in Open CASCADE\r
+ // in calculation of nearest point to a circle near the parameter 0.0\r
+ gp_Pnt p0 = ElCLib::Value(0.0, aCircle->Circ());\r
+ if (p0.Distance(thePoint) < aPointOnCircle.Distance(thePoint))\r
+ {\r
+ aTarGetParam = 0.0;\r
+ aPointOnCircle = p0;\r
+ }\r
+\r
+ aProj.Perform(aPoint1);\r
+ Standard_Real aParam1 = aProj.LowerDistanceParameter();\r
+ aProj.Perform(aPoint2);\r
+ Standard_Real aParam2 = aProj.LowerDistanceParameter();\r
+ Standard_Boolean aIsOut = ((aParam1 < aTarGetParam && aParam2 < aTarGetParam) || \r
+ (aParam1 > aTarGetParam && aParam2 > aTarGetParam));\r
+ if (aParam1 > aParam2) \r
+ aIsOut = !aIsOut;\r
+ BRepBuilderAPI_MakeEdge aBuilder(aCircle->Circ(),\r
+ aIsOut ? aParam2 : aParam1,\r
+ aIsOut? aParam1 : aParam2);\r
+ aResult = aBuilder.Edge();\r
+\r
+ // divide edges\r
+ Standard_Real aStart, anEnd;\r
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(myEdge1, aStart, anEnd);\r
+ gp_Vec aDir;\r
+ aCurve->D1(aNearest->GetParam(), aPoint1, aDir);\r
+\r
+ gp_Vec aCircleDir;\r
+ aCircle->D1(aParam1, aPoint1, aCircleDir);\r
+ if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ aIsOut)\r
+ aStart = aNearest->GetParam();\r
+ else\r
+ anEnd = aNearest->GetParam();\r
+\r
+ if (fabs(aStart - anEnd) > Precision::Confusion())\r
+ {\r
+ //Divide edge\r
+ BRepBuilderAPI_MakeEdge aDivider1(aCurve, aStart, anEnd);\r
+ if (myEdgesExchnged) \r
+ theEdge2 = aDivider1.Edge();\r
+ else \r
+ theEdge1 = aDivider1.Edge();\r
+ }\r
+\r
+ aCurve = BRep_Tool::Curve(myEdge2, aStart, anEnd);\r
+ aCurve->D1(aNearest->GetParam2(), aPoint2, aDir);\r
+ \r
+ aCircle->D1(aParam2, aPoint2, aCircleDir);\r
+ if ((aCircleDir.Angle(aDir) > PI / 2.0) ^ (!aIsOut))\r
+ aStart = aNearest->GetParam2();\r
+ else\r
+ anEnd = aNearest->GetParam2();\r
+\r
+ if (fabs(aStart - anEnd) > Precision::Confusion())\r
+ {\r
+ BRepBuilderAPI_MakeEdge aDivider2(aCurve, aStart, anEnd);\r
+ if (myEdgesExchnged) \r
+ theEdge1 = aDivider2.Edge();\r
+ else \r
+ theEdge2 = aDivider2.Edge();\r
+ }\r
+\r
+ delete aNearest;\r
+ return aResult;\r
+}\r
+\r
+//=======================================================================\r
+//function : AddValue\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1dPoint::AddValue(Standard_Real theValue, Standard_Boolean theValid) \r
+{\r
+ Standard_Integer a;\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ if (theValue < myV.Value(a)) \r
+ {\r
+ myV.InsertBefore(a, theValue);\r
+ myValid.InsertBefore(a, (Standard_Integer)theValid);\r
+ return;\r
+ }\r
+ }\r
+ myV.Append(theValue);\r
+ myValid.Append((Standard_Integer)theValid);\r
+}\r
+\r
+//=======================================================================\r
+//function : ComputeDifference\r
+//purpose : \r
+//=======================================================================\r
+Standard_Boolean GEOMImpl_Fillet1dPoint::ComputeDifference(GEOMImpl_Fillet1dPoint* thePoint) \r
+{\r
+ Standard_Integer a;\r
+ Standard_Boolean aDiffsSet = (myD.Length() != 0);\r
+ Standard_Real aDX = thePoint->GetParam() - myParam, aDY;\r
+ if (thePoint->myV.Length() == myV.Length()) \r
+ { // absolutely the same points\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ aDY = thePoint->myV.Value(a) - myV.Value(a);\r
+ if ( aDiffsSet ) \r
+ myD.SetValue(a, fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);\r
+ else\r
+ myD.Append( fabs(aDX) > gp::Resolution() ? (aDY/aDX) : 0);\r
+ }\r
+ return Standard_True;\r
+ }\r
+ // between the diffeerent points searching for nearest analogs\r
+ Standard_Integer b;\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ for(b = 1; b <= thePoint->myV.Length(); b++) \r
+ {\r
+ if (b == 1 || fabs(thePoint->myV.Value(b) - myV.Value(a)) < fabs(aDY))\r
+ aDY = thePoint->myV.Value(b) - myV.Value(a);\r
+ }\r
+ if (aDiffsSet) \r
+ {\r
+ if ( fabs(aDX) > gp::Resolution() && fabs(aDY / aDX) < fabs(myD.Value(a)))\r
+ myD.SetValue(a, aDY / aDX);\r
+ else\r
+ myD.SetValue(a, 0);\r
+ } \r
+ else \r
+ {\r
+ myD.Append( fabs(aDX) > gp::Resolution() ? aDY/aDX : 0);\r
+ }\r
+ }\r
+ \r
+ return Standard_False;\r
+}\r
+\r
+//=======================================================================\r
+//function : FilterPoints\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1dPoint::FilterPoints(GEOMImpl_Fillet1dPoint* thePoint) \r
+{\r
+ Standard_Integer a, b;\r
+ TColStd_SequenceOfReal aDiffs;\r
+ Standard_Real aY, aY2, aDX = thePoint->GetParam() - myParam;\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ // searching for near point from thePoint\r
+ Standard_Integer aNear = 0;\r
+ Standard_Real aDiff = aDX * 10000.;\r
+ aY = myV.Value(a) + myD.Value(a) * aDX;\r
+ for(b = 1; b <= thePoint->myV.Length(); b++) \r
+ {\r
+ // calculate hypothesis value of the Y2 with the constant first and second derivative\r
+ aY2 = aY + aDX * (thePoint->myD.Value(b) - myD.Value(a)) / 2.0;\r
+ if (aNear == 0 || fabs(aY2 - thePoint->myV.Value(b)) < fabs(aDiff)) \r
+ {\r
+ aNear = b;\r
+ aDiff = aY2 - thePoint->myV.Value(b);\r
+ }\r
+ }//for b...\r
+\r
+ if (aNear) \r
+ {\r
+ if (myV.Value(a) * thePoint->myV.Value(aNear) > 0) \r
+ {// the same sign at the same sides of the interval\r
+ if (myV.Value(a) * myD.Value(a) > 0) \r
+ {\r
+ if (fabs(myD.Value(a)) > Precision::Confusion()) \r
+ aNear = 0;\r
+ } \r
+ else \r
+ {\r
+ if (fabs(myV.Value(a)) > fabs(thePoint->myV.Value(aNear)))\r
+ if (thePoint->myV.Value(aNear) * thePoint->myD.Value(aNear) < 0 &&\r
+ fabs(thePoint->myD.Value(aNear)) > Precision::Confusion())\r
+ {\r
+ aNear = 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (aNear) \r
+ {\r
+ if (myV.Value(a) * thePoint->myV.Value(aNear) > 0) \r
+ {\r
+ if ((myV.Value(a) + myD.Value(a) * aDX) * myV.Value(a) > Precision::Confusion() &&\r
+ (thePoint->myV.Value(aNear) + thePoint->myD.Value(aNear) * aDX) * thePoint->myV.Value(aNear) > Precision::Confusion())\r
+ {\r
+ aNear = 0;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (aNear)\r
+ {\r
+ if ( fabs(aDX) < gp::Resolution() || fabs(aDiff / aDX) > 1.e+7) \r
+ {\r
+ aNear = 0;\r
+ }\r
+ }\r
+\r
+ if (aNear == 0) \r
+ { // there is no near: remove it from the list\r
+ myV.Remove(a);\r
+ myD.Remove(a);\r
+ myValid.Remove(a);\r
+ a--;\r
+ } \r
+ else \r
+ {\r
+ Standard_Boolean aFound = Standard_False;\r
+ for(b = 1; b <= myNear.Length(); b++) \r
+ {\r
+ if (myNear.Value(b) == aNear) \r
+ {\r
+ if (fabs(aDiffs.Value(b)) < fabs(aDiff)) \r
+ { // return this 'near'\r
+ aFound = Standard_True;\r
+ myV.Remove(a);\r
+ myD.Remove(a);\r
+ myValid.Remove(a);\r
+ a--;\r
+ break;\r
+ } \r
+ else \r
+ { // remove the old 'near'\r
+ myV.Remove(b);\r
+ myD.Remove(b);\r
+ myValid.Remove(b);\r
+ myNear.Remove(b);\r
+ aDiffs.Remove(b);\r
+ a--;\r
+ break;\r
+ }\r
+ }\r
+ }//for b...\r
+ if (!aFound) \r
+ {\r
+ myNear.Append(aNear);\r
+ aDiffs.Append(aDiff);\r
+ }\r
+ }\r
+ }//for a...\r
+}\r
+\r
+//=======================================================================\r
+//function : Copy\r
+//purpose : \r
+//=======================================================================\r
+GEOMImpl_Fillet1dPoint* GEOMImpl_Fillet1dPoint::Copy() \r
+{\r
+ GEOMImpl_Fillet1dPoint* aCopy = new GEOMImpl_Fillet1dPoint(myParam);\r
+ Standard_Integer a;\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ aCopy->myV.Append(myV.Value(a));\r
+ aCopy->myD.Append(myD.Value(a));\r
+ aCopy->myValid.Append(myValid.Value(a));\r
+ }\r
+ return aCopy;\r
+}\r
+\r
+//=======================================================================\r
+//function : HasSolution\r
+//purpose : \r
+//=======================================================================\r
+Standard_Integer GEOMImpl_Fillet1dPoint::HasSolution(const Standard_Real theRadius) \r
+{\r
+ Standard_Integer a;\r
+ for(a = 1; a <= myV.Length(); a++) \r
+ {\r
+ if (fabs(sqrt(fabs(fabs(myV.Value(a)) + theRadius * theRadius)) - theRadius) < Precision::Confusion() / 10.) \r
+ return a;\r
+ }\r
+ return 0;\r
+}\r
+\r
+//=======================================================================\r
+//function : RemoveSolution\r
+//purpose : \r
+//=======================================================================\r
+void GEOMImpl_Fillet1dPoint::RemoveSolution(Standard_Integer theIndex)\r
+{\r
+ myV.Remove(theIndex);\r
+ myD.Remove(theIndex);\r
+ myValid.Remove(theIndex);\r
+ myNear.Remove(theIndex);\r
+}\r
-// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-
-// File : GEOMImpl_Fillet1d.hxx
-// Module : GEOMImpl
-//
-#ifndef _GEOMImpl_Fillet1d_HeaderFile
-#define _GEOMImpl_Fillet1d_HeaderFile
-
-#include <gp_Pnt.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom2d_Curve.hxx>
-
-#include <TopoDS_Edge.hxx>
-#include <TColStd_ListOfReal.hxx>
-#include <TColStd_SequenceOfReal.hxx>
-#include <TColStd_SequenceOfInteger.hxx>
-
-class GEOMImpl_Fillet1dPoint;
-
-/**
-* GEOMImpl_Fillet1d is 1D fillet algorithm on two planar edges with given radius
-*/
-
-class GEOMImpl_Fillet1d
-{
-public:
- //! Constructor
- //! The fillet 1D algorithm initialise by two edges and plane
- Standard_EXPORT GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,
- const TopoDS_Edge& theEdge2,
- const gp_Pln& thePlane);
- //! Makes fillet with given radius
- //! @returns Standard_True, if at least one result computed
- Standard_EXPORT Standard_Boolean Perform(const Standard_Real theRadius);
- //! Returns result fillet edge and modified edges as out parameters
- Standard_EXPORT TopoDS_Edge Result(const gp_Pnt& thePoint, TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2);
-
-private:
- //! private methods
- void fillPoint(GEOMImpl_Fillet1dPoint*);
- void fillDiff(GEOMImpl_Fillet1dPoint*, Standard_Real, Standard_Boolean);
- void performNewton(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*);
- Standard_Boolean processPoint(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*, Standard_Real);
-
-
-private:
- //! private fields
- TopoDS_Edge myEdge1, myEdge2;
- Handle(Geom_Plane) myPlane;
- Handle(Geom2d_Curve) myCurve1, myCurve2;
- Standard_Real myStart1, myEnd1, myStart2, myEnd2, myRadius;
- TColStd_ListOfReal myResultParams;
- TColStd_SequenceOfInteger myResultOrientation;
- Standard_Boolean myStartSide, myEdgesExchnged;
-};
-
-
-/**
-* GEOMImpl_Fillet1dPoint is an internal class for 1D fillet algorithm
-* to store and compare computed solutions on edges
-*/
-
-class GEOMImpl_Fillet1dPoint
-{
-public:
- //! Puiblic methods
-
- //! Constructor
- Standard_EXPORT GEOMImpl_Fillet1dPoint(Standard_Real theParam)
- {myParam = theParam;}
-
- //! Make copy of point
- //!WARNING: Copies only field values: myParam, myV, myD, myValid
- Standard_EXPORT GEOMImpl_Fillet1dPoint* Copy(); // warning: this is not the full copy!
-
- //! Set/Get parameter
- Standard_EXPORT inline void SetParam(Standard_Real theParam)
- {myParam = theParam;}
- Standard_EXPORT inline Standard_Real GetParam() const
- {return myParam;}
- Standard_EXPORT inline void SetParam2(const Standard_Real theParam2)
- {myParam2 = theParam2;}
- Standard_EXPORT inline Standard_Real GetParam2()
- { return myParam2 ; }
-
- //! Returns validity
- Standard_EXPORT inline Standard_Boolean IsValid(int theIndex)
- {return (Standard_Boolean)myValid.Value(theIndex);}
-
- //! Get values
- Standard_EXPORT inline Standard_Integer GetNBValues() {return myV.Length();}
- Standard_EXPORT inline Standard_Real GetValue(Standard_Integer theIndex)
- {return myV.Value(theIndex);}
- Standard_EXPORT inline Standard_Real GetDiff(Standard_Integer theIndex)
- {return myD.Value(theIndex);}
- Standard_EXPORT inline Standard_Integer GetNear(Standard_Integer theIndex)
- {return myNear.Value(theIndex);}
-
- //! Set/Get center point
- Standard_EXPORT inline void SetCenter(const gp_Pnt2d thePoint)
- {myCenter = thePoint;}
- Standard_EXPORT inline const gp_Pnt2d GetCenter()
- {return myCenter;}
-
- Standard_EXPORT void AddValue(Standard_Real theValue, Standard_Boolean theIsValid);
-
- //! compute difference between this and given point
- Standard_EXPORT Standard_Boolean ComputeDifference(GEOMImpl_Fillet1dPoint*);
- Standard_EXPORT void FilterPoints(GEOMImpl_Fillet1dPoint*);
-
- //! Check is point contains solution and returns the index of them if any
- Standard_EXPORT Standard_Integer HasSolution(Standard_Real theRadius);
- //! Remove solution by index
- void RemoveSolution(Standard_Integer theIndex);
-
-private:
- //! Private fields
- gp_Pnt2d myCenter;
- Standard_Real myParam, myParam2;
- TColStd_SequenceOfReal myV, myD;
- TColStd_SequenceOfInteger myValid, myNear;
-};
-
-#endif
+// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE\r
+//\r
+// This library is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU Lesser General Public\r
+// License as published by the Free Software Foundation; either\r
+// version 2.1 of the License.\r
+//\r
+// This library is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+// Lesser General Public License for more details.\r
+//\r
+// You should have received a copy of the GNU Lesser General Public\r
+// License along with this library; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+//\r
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com\r
+//\r
+\r
+// File : GEOMImpl_Fillet1d.hxx\r
+// Module : GEOMImpl\r
+//\r
+#ifndef _GEOMImpl_Fillet1d_HeaderFile\r
+#define _GEOMImpl_Fillet1d_HeaderFile\r
+\r
+#include <gp_Pnt.hxx>\r
+#include <Geom_Plane.hxx>\r
+#include <Geom2d_Curve.hxx>\r
+\r
+#include <TopoDS_Edge.hxx>\r
+#include <TColStd_ListOfReal.hxx>\r
+#include <TColStd_SequenceOfReal.hxx>\r
+#include <TColStd_SequenceOfInteger.hxx>\r
+\r
+class GEOMImpl_Fillet1dPoint;\r
+\r
+/**\r
+* GEOMImpl_Fillet1d is 1D fillet algorithm on two planar edges with given radius\r
+*/\r
+\r
+class GEOMImpl_Fillet1d \r
+{\r
+public:\r
+ //! Constructor\r
+ //! The fillet 1D algorithm initialise by two edges and plane\r
+ Standard_EXPORT GEOMImpl_Fillet1d(const TopoDS_Edge& theEdge1,\r
+ const TopoDS_Edge& theEdge2,\r
+ const gp_Pln& thePlane);\r
+ //! Makes fillet with given radius\r
+ //! @returns Standard_True, if at least one result computed\r
+ Standard_EXPORT Standard_Boolean Perform(const Standard_Real theRadius);\r
+ //! Returns result fillet edge and modified edges as out parameters\r
+ Standard_EXPORT TopoDS_Edge Result(const gp_Pnt& thePoint, TopoDS_Edge& theEdge1, TopoDS_Edge& theEdge2);\r
+\r
+private:\r
+ //! private methods\r
+ void fillPoint(GEOMImpl_Fillet1dPoint*);\r
+ void fillDiff(GEOMImpl_Fillet1dPoint*, Standard_Real, Standard_Boolean);\r
+ void performNewton(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*);\r
+ Standard_Boolean processPoint(GEOMImpl_Fillet1dPoint*, GEOMImpl_Fillet1dPoint*, Standard_Real);\r
+\r
+\r
+private:\r
+ //! private fields\r
+ TopoDS_Edge myEdge1, myEdge2;\r
+ Handle(Geom_Plane) myPlane;\r
+ Handle(Geom2d_Curve) myCurve1, myCurve2;\r
+ Standard_Real myStart1, myEnd1, myStart2, myEnd2, myRadius;\r
+ TColStd_ListOfReal myResultParams;\r
+ TColStd_SequenceOfInteger myResultOrientation;\r
+ Standard_Boolean myStartSide, myEdgesExchnged;\r
+ Standard_Integer myDegreeOfRecursion;\r
+};\r
+\r
+\r
+/**\r
+* GEOMImpl_Fillet1dPoint is an internal class for 1D fillet algorithm\r
+* to store and compare computed solutions on edges\r
+*/\r
+\r
+class GEOMImpl_Fillet1dPoint\r
+{\r
+public:\r
+ //! Puiblic methods\r
+\r
+ //! Constructor\r
+ Standard_EXPORT GEOMImpl_Fillet1dPoint(Standard_Real theParam)\r
+ {myParam = theParam;}\r
+ \r
+ //! Make copy of point\r
+ //!WARNING: Copies only field values: myParam, myV, myD, myValid\r
+ Standard_EXPORT GEOMImpl_Fillet1dPoint* Copy(); // warning: this is not the full copy! \r
+\r
+ //! Set/Get parameter\r
+ Standard_EXPORT inline void SetParam(Standard_Real theParam)\r
+ {myParam = theParam;}\r
+ Standard_EXPORT inline Standard_Real GetParam() const\r
+ {return myParam;}\r
+ Standard_EXPORT inline void SetParam2(const Standard_Real theParam2)\r
+ {myParam2 = theParam2;}\r
+ Standard_EXPORT inline Standard_Real GetParam2()\r
+ { return myParam2 ; }\r
+\r
+ //! Returns validity \r
+ Standard_EXPORT inline Standard_Boolean IsValid(int theIndex)\r
+ {return (Standard_Boolean)myValid.Value(theIndex);}\r
+\r
+ //! Get values\r
+ Standard_EXPORT inline Standard_Integer GetNBValues() {return myV.Length();}\r
+ Standard_EXPORT inline Standard_Real GetValue(Standard_Integer theIndex)\r
+ {return myV.Value(theIndex);}\r
+ Standard_EXPORT inline Standard_Real GetDiff(Standard_Integer theIndex)\r
+ {return myD.Value(theIndex);}\r
+ Standard_EXPORT inline Standard_Integer GetNear(Standard_Integer theIndex)\r
+ {return myNear.Value(theIndex);}\r
+\r
+ //! Set/Get center point\r
+ Standard_EXPORT inline void SetCenter(const gp_Pnt2d thePoint)\r
+ {myCenter = thePoint;}\r
+ Standard_EXPORT inline const gp_Pnt2d GetCenter()\r
+ {return myCenter;}\r
+\r
+ Standard_EXPORT void AddValue(Standard_Real theValue, Standard_Boolean theIsValid);\r
+\r
+ //! compute difference between this and given point\r
+ Standard_EXPORT Standard_Boolean ComputeDifference(GEOMImpl_Fillet1dPoint*);\r
+ Standard_EXPORT void FilterPoints(GEOMImpl_Fillet1dPoint*);\r
+ \r
+ //! Check is point contains solution and returns the index of them if any\r
+ Standard_EXPORT Standard_Integer HasSolution(Standard_Real theRadius); \r
+ //! Remove solution by index\r
+ void RemoveSolution(Standard_Integer theIndex);\r
+\r
+private:\r
+ //! Private fields\r
+ gp_Pnt2d myCenter;\r
+ Standard_Real myParam, myParam2;\r
+ TColStd_SequenceOfReal myV, myD;\r
+ TColStd_SequenceOfInteger myValid, myNear;\r
+};\r
+\r
+#endif\r