#include <Geom2d_BSplineCurve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Geom_BSplineCurve.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAdaptor_HCurve.hxx>
#include <GeomAdaptor_HSurface.hxx>
gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter());
gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter());
+ Standard_Boolean isToTrim = Standard_True;
+ Standard_Real U1, U2, V1, V2;
+ aSurf->Bounds(U1, U2, V1, V2);
+
if (theIsU)
{
+ Standard_Real aV1Param = Min(aF2d.Y(), aL2d.Y());
+ Standard_Real aV2Param = Max(aF2d.Y(), aL2d.Y());
+ if (aV2Param < V1 - myTol || aV1Param > V2 + myTol)
+ {
+ return Standard_False;
+ }
+ else if (Precision::IsInfinite(V1) || Precision::IsInfinite(V2))
+ {
+ if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+ {
+ return Standard_False;
+ }
+ aSurf = new Geom_RectangularTrimmedSurface(aSurf, U1, U2, aV1Param, aV2Param);
+ isToTrim = Standard_False;
+ }
+ else
+ {
+ aV1Param = Max(aV1Param, V1);
+ aV2Param = Min(aV2Param, V2);
+ if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+ {
+ return Standard_False;
+ }
+ }
aC3d = aSurf->UIso(theParam);
- aC3d = new Geom_TrimmedCurve(aC3d, aF2d.Y(), aL2d.Y());
+ if (isToTrim)
+ aC3d = new Geom_TrimmedCurve(aC3d, aV1Param, aV2Param);
}
else
{
+ Standard_Real aU1Param = Min(aF2d.X(), aL2d.X());
+ Standard_Real aU2Param = Max(aF2d.X(), aL2d.X());
+ if (aU2Param < U1 - myTol || aU1Param > U2 + myTol)
+ {
+ return Standard_False;
+ }
+ else if (Precision::IsInfinite(U1) || Precision::IsInfinite(U2))
+ {
+ if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+ {
+ return Standard_False;
+ }
+ aSurf = new Geom_RectangularTrimmedSurface(aSurf, aU1Param, aU2Param, V1, V2);
+ isToTrim = Standard_False;
+ }
+ else
+ {
+ aU1Param = Max(aU1Param, U1);
+ aU2Param = Min(aU2Param, U2);
+ if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+ {
+ return Standard_False;
+ }
+ }
aC3d = aSurf->VIso(theParam);
- aC3d = new Geom_TrimmedCurve(aC3d, aF2d.X(), aL2d.X());
+ if (isToTrim)
+ aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
}
// Convert arbitrary curve type to the b-spline.
#include <Adaptor3d_HSurface.hxx>
#include <AdvApprox_ApproxAFunction.hxx>
#include <AdvApprox_PrefAndRec.hxx>
+#include <Approx_CurveOnSurface.hxx>
#include <BSplCLib.hxx>
#include <BSplSLib.hxx>
#include <CSLib.hxx>
{
- Standard_Integer curve_not_computed = 1 ;
MaxDeviation = 0.0e0 ;
AverageDeviation = 0.0e0 ;
Handle(GeomAdaptor_HSurface) geom_adaptor_surface_ptr (Handle(GeomAdaptor_HSurface)::DownCast(Curve.GetSurface()) );
NewCurvePtr =
GeomLib::To3d(axes,
geom2d_curve.Curve());
- curve_not_computed = 0 ;
+ return;
}
+
+ Handle(Adaptor2d_HCurve2d) TrimmedC2D = geom_adaptor_curve_ptr->Trim (FirstParameter, LastParameter, Precision::PConfusion());
+
+ Standard_Boolean isU, isForward;
+ Standard_Real aParam;
+ if (isIsoLine(TrimmedC2D, isU, aParam, isForward))
+ {
+ NewCurvePtr = buildC3dOnIsoLine (TrimmedC2D, geom_adaptor_surface_ptr, FirstParameter, LastParameter, Tolerance, isU, aParam, isForward);
+ if (!NewCurvePtr.IsNull())
+ {
+ return;
+ }
+ }
}
- if (curve_not_computed) {
//
// Entree
AverageDeviation = anApproximator.AverageError(3,1) ;
NewCurvePtr = aCurvePtr ;
}
- }
}
//=======================================================================
//
return Standard_True;
}
+
+//=============================================================================
+//function : isIsoLine
+//purpose :
+//=============================================================================
+Standard_Boolean GeomLib::isIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+ Standard_Boolean& theIsU,
+ Standard_Real& theParam,
+ Standard_Boolean& theIsForward)
+{
+ // These variables are used to check line state (vertical or horizontal).
+ Standard_Boolean isAppropriateType = Standard_False;
+ gp_Pnt2d aLoc2d;
+ gp_Dir2d aDir2d;
+
+ // Test type.
+ const GeomAbs_CurveType aType = theC2D->GetType();
+ if (aType == GeomAbs_Line)
+ {
+ gp_Lin2d aLin2d = theC2D->Line();
+ aLoc2d = aLin2d.Location();
+ aDir2d = aLin2d.Direction();
+ isAppropriateType = Standard_True;
+ }
+ else if (aType == GeomAbs_BSplineCurve)
+ {
+ Handle(Geom2d_BSplineCurve) aBSpline2d = theC2D->BSpline();
+ if (aBSpline2d->Degree() != 1 || aBSpline2d->NbPoles() != 2)
+ return Standard_False; // Not a line or uneven parameterization.
+
+ aLoc2d = aBSpline2d->Pole(1);
+
+ // Vector should be non-degenerated.
+ gp_Vec2d aVec2d(aBSpline2d->Pole(1), aBSpline2d->Pole(2));
+ if (aVec2d.SquareMagnitude() < Precision::Confusion())
+ return Standard_False; // Degenerated spline.
+ aDir2d = aVec2d;
+
+ isAppropriateType = Standard_True;
+ }
+ else if (aType == GeomAbs_BezierCurve)
+ {
+ Handle(Geom2d_BezierCurve) aBezier2d = theC2D->Bezier();
+ if (aBezier2d->Degree() != 1 || aBezier2d->NbPoles() != 2)
+ return Standard_False; // Not a line or uneven parameterization.
+
+ aLoc2d = aBezier2d->Pole(1);
+
+ // Vector should be non-degenerated.
+ gp_Vec2d aVec2d(aBezier2d->Pole(1), aBezier2d->Pole(2));
+ if (aVec2d.SquareMagnitude() < Precision::Confusion())
+ return Standard_False; // Degenerated spline.
+ aDir2d = aVec2d;
+
+ isAppropriateType = Standard_True;
+ }
+
+ if (!isAppropriateType)
+ return Standard_False;
+
+ // Check line to be vertical or horizontal.
+ if (aDir2d.IsParallel(gp::DX2d(), Precision::Angular()))
+ {
+ // Horizontal line. V = const.
+ theIsU = Standard_False;
+ theParam = aLoc2d.Y();
+ theIsForward = aDir2d.Dot(gp::DX2d()) > 0.0;
+ return Standard_True;
+ }
+ else if (aDir2d.IsParallel(gp::DY2d(), Precision::Angular()))
+ {
+ // Vertical line. U = const.
+ theIsU = Standard_True;
+ theParam = aLoc2d.X();
+ theIsForward = aDir2d.Dot(gp::DY2d()) > 0.0;
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+//=============================================================================
+//function : buildC3dOnIsoLine
+//purpose :
+//=============================================================================
+Handle(Geom_Curve) GeomLib::buildC3dOnIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+ const Handle(Adaptor3d_HSurface) theSurf,
+ const Standard_Real theFirst,
+ const Standard_Real theLast,
+ const Standard_Real theTolerance,
+ const Standard_Boolean theIsU,
+ const Standard_Real theParam,
+ const Standard_Boolean theIsForward)
+{
+ // Convert adapter to the appropriate type.
+ Handle(GeomAdaptor_HSurface) aGeomAdapter = Handle(GeomAdaptor_HSurface)::DownCast(theSurf);
+ if (aGeomAdapter.IsNull())
+ return Handle(Geom_Curve)();
+
+ if (theSurf->GetType() == GeomAbs_Sphere)
+ return Handle(Geom_Curve)();
+
+ // Extract isoline
+ Handle(Geom_Surface) aSurf = aGeomAdapter->ChangeSurface().Surface();
+ Handle(Geom_Curve) aC3d;
+
+ gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter());
+ gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter());
+
+ Standard_Boolean isToTrim = Standard_True;
+ Standard_Real U1, U2, V1, V2;
+ aSurf->Bounds(U1, U2, V1, V2);
+
+ if (theIsU)
+ {
+ Standard_Real aV1Param = Min(aF2d.Y(), aL2d.Y());
+ Standard_Real aV2Param = Max(aF2d.Y(), aL2d.Y());
+ if (aV2Param < V1 - theTolerance || aV1Param > V2 + theTolerance)
+ {
+ return Handle(Geom_Curve)();
+ }
+ else if (Precision::IsInfinite(V1) || Precision::IsInfinite(V2))
+ {
+ if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+ {
+ return Handle(Geom_Curve)();
+ }
+ aSurf = new Geom_RectangularTrimmedSurface(aSurf, U1, U2, aV1Param, aV2Param);
+ isToTrim = Standard_False;
+ }
+ else
+ {
+ aV1Param = Max(aV1Param, V1);
+ aV2Param = Min(aV2Param, V2);
+ if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
+ {
+ return Handle(Geom_Curve)();
+ }
+ }
+ aC3d = aSurf->UIso(theParam);
+ if (isToTrim)
+ aC3d = new Geom_TrimmedCurve(aC3d, aV1Param, aV2Param);
+ }
+ else
+ {
+ Standard_Real aU1Param = Min(aF2d.X(), aL2d.X());
+ Standard_Real aU2Param = Max(aF2d.X(), aL2d.X());
+ if (aU2Param < U1 - theTolerance || aU1Param > U2 + theTolerance)
+ {
+ return Handle(Geom_Curve)();
+ }
+ else if (Precision::IsInfinite(U1) || Precision::IsInfinite(U2))
+ {
+ if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+ {
+ return Handle(Geom_Curve)();
+ }
+ aSurf = new Geom_RectangularTrimmedSurface(aSurf, aU1Param, aU2Param, V1, V2);
+ isToTrim = Standard_False;
+ }
+ else
+ {
+ aU1Param = Max(aU1Param, U1);
+ aU2Param = Min(aU2Param, U2);
+ if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
+ {
+ return Handle(Geom_Curve)();
+ }
+ }
+ aC3d = aSurf->VIso(theParam);
+ if (isToTrim)
+ aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
+ }
+
+ // Convert arbitrary curve type to the b-spline.
+ Handle(Geom_BSplineCurve) aCurve3d = GeomConvert::CurveToBSplineCurve(aC3d, Convert_QuasiAngular);
+ if (!theIsForward)
+ aCurve3d->Reverse();
+
+ // Rebuild parameterization for the 3d curve to have the same parameterization with
+ // a two-dimensional curve.
+ TColStd_Array1OfReal aKnots = aCurve3d->Knots();
+ BSplCLib::Reparametrize(theC2D->FirstParameter(), theC2D->LastParameter(), aKnots);
+ aCurve3d->SetKnots(aKnots);
+
+ // Evaluate error.
+ Standard_Real anError3d = 0.0;
+
+ const Standard_Real aParF = theFirst;
+ const Standard_Real aParL = theLast;
+ const Standard_Integer aNbPnt = 23;
+ for (Standard_Integer anIdx = 0; anIdx <= aNbPnt; ++anIdx)
+ {
+ const Standard_Real aPar = aParF + ((aParL - aParF) * anIdx) / aNbPnt;
+
+ const gp_Pnt2d aPnt2d = theC2D->Value(aPar);
+
+ const gp_Pnt aPntC3D = aCurve3d->Value(aPar);
+ const gp_Pnt aPntC2D = theSurf->Value(aPnt2d.X(), aPnt2d.Y());
+
+ const Standard_Real aSqDeviation = aPntC3D.SquareDistance(aPntC2D);
+ anError3d = Max (aSqDeviation, anError3d);
+ }
+
+ anError3d = Sqrt(anError3d);
+
+ // Target tolerance is not obtained. This situation happens for isolines on the sphere.
+ // OCCT is unable to convert it keeping original parameterization, while the geometric
+ // form of the result is entirely identical. In that case, it is better to utilize
+ // a general-purpose approach.
+ if (anError3d > theTolerance)
+ return Handle(Geom_Curve)();
+
+ return aCurve3d;
+}
class Geom2d_Curve;
class gp_GTrsf2d;
class Adaptor3d_CurveOnSurface;
+class Adaptor2d_HCurve2d;
+class Adaptor3d_HSurface;
class Geom_BoundedCurve;
class gp_Pnt;
class gp_Vec;
const Standard_Real V2,
const Standard_Real Tol);
-protected:
-
+ //! Checks whether the 2d curve is a isoline. It can be represented by b-spline, bezier,
+ //! or geometric line. This line should have natural parameterization.
+ //! @param theC2D Trimmed curve to be checked.
+ //! @param theIsU Flag indicating that line is u const.
+ //! @param theParam Line parameter.
+ //! @param theIsForward Flag indicating forward parameterization on a isoline.
+ //! @return Standard_True when 2d curve is a line and Standard_False otherwise.
+ Standard_EXPORT static Standard_Boolean isIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+ Standard_Boolean& theIsU,
+ Standard_Real& theParam,
+ Standard_Boolean& theIsForward);
+ //! Builds 3D curve for a isoline. This method takes corresponding isoline from
+ //! the input surface.
+ //! @param theC2D Trimmed curve to be approximated.
+ //! @param theIsU Flag indicating that line is u const.
+ //! @param theParam Line parameter.
+ //! @param theIsForward Flag indicating forward parameterization on a isoline.
+ //! @return Standard_True when 3d curve is built and Standard_False otherwise.
+ Standard_EXPORT static Handle(Geom_Curve) buildC3dOnIsoLine (const Handle(Adaptor2d_HCurve2d) theC2D,
+ const Handle(Adaptor3d_HSurface) theSurf,
+ const Standard_Real theFirst,
+ const Standard_Real theLast,
+ const Standard_Real theTolerance,
+ const Standard_Boolean theIsU,
+ const Standard_Real theParam,
+ const Standard_Boolean theIsForward);
+protected:
private: