1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-24 13:50:49 +03:00

Compare commits

...

3 Commits

Author SHA1 Message Date
anv
79f96e0c04 0030889: ACIS Import - Incorrect result reading SAT and SAB files
Adapting CR30932 fix for a GeomLib approximator.

# Conflicts:
#	tests/bugs/iges/bug306
#	tests/de/iges_1/C8
2019-12-12 13:22:39 +03:00
aml
21fa699a4f 0030932: Modeling Algorithms - Invalid result on 2d curve on surface approximation
New method generating 3D curve is added when 2D curve is linear isoline.
2019-12-12 13:05:06 +03:00
anv
930f157783 0031202: Shape Healing - FixMissingSeam creates degenerated edge
Adding tolerance to prevent degenerated cuts in cases where all vertex tolerance is covered by distance of the edge curve from vertex point.
2019-12-12 13:03:08 +03:00
20 changed files with 681 additions and 69 deletions

View File

@@ -27,8 +27,11 @@
#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>
#include <GeomConvert.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
@@ -300,6 +303,10 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
}
}
//=============================================================================
//function : Approx_CurveOnSurface
//purpose : Constructor
//=============================================================================
Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D,
const Handle(Adaptor3d_HSurface)& Surf,
const Standard_Real First,
@@ -310,14 +317,75 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
const Standard_Integer MaxSegments,
const Standard_Boolean only3d,
const Standard_Boolean only2d)
: myC2D(C2D),
mySurf(Surf),
myFirst(First),
myLast(Last),
myTol(Tol),
myIsDone(Standard_False),
myHasResult(Standard_False),
myError3d(0.0),
myError2dU(0.0),
myError2dV(0.0)
{
Perform(MaxSegments, MaxDegree, S, only3d, only2d);
}
//=============================================================================
//function : Approx_CurveOnSurface
//purpose : Constructor
//=============================================================================
Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& theC2D,
const Handle(Adaptor3d_HSurface)& theSurf,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Real theTol)
: myC2D(theC2D),
mySurf(theSurf),
myFirst(theFirst),
myLast(theLast),
myTol(theTol),
myIsDone(Standard_False),
myHasResult(Standard_False),
myError3d(0.0),
myError2dU(0.0),
myError2dV(0.0)
{
}
//=============================================================================
//function : Perform
//purpose :
//=============================================================================
void Approx_CurveOnSurface::Perform(const Standard_Integer theMaxSegments,
const Standard_Integer theMaxDegree,
const GeomAbs_Shape theContinuity,
const Standard_Boolean theOnly3d,
const Standard_Boolean theOnly2d)
{
myIsDone = Standard_False;
if(only3d && only2d) throw Standard_ConstructionError();
GeomAbs_Shape Order = S;
myHasResult = Standard_False;
myError2dU = 0.0;
myError2dV = 0.0;
myError3d = 0.0;
Handle( Adaptor2d_HCurve2d ) TrimmedC2D = C2D->Trim( First, Last, Precision::PConfusion() );
if(theOnly3d && theOnly2d) throw Standard_ConstructionError();
Adaptor3d_CurveOnSurface COnS( TrimmedC2D, Surf );
Handle( Adaptor2d_HCurve2d ) TrimmedC2D = myC2D->Trim( myFirst, myLast, Precision::PConfusion() );
Standard_Boolean isU, isForward;
Standard_Real aParam;
if (theOnly3d && isIsoLine(TrimmedC2D, isU, aParam, isForward))
{
if (buildC3dOnIsoLine(TrimmedC2D, isU, aParam, isForward))
{
myIsDone = Standard_True;
myHasResult = Standard_True;
return;
}
}
Adaptor3d_CurveOnSurface COnS( TrimmedC2D, mySurf );
Handle(Adaptor3d_HCurveOnSurface) HCOnS = new Adaptor3d_HCurveOnSurface();
HCOnS->Set(COnS);
@@ -327,37 +395,34 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
Handle(TColStd_HArray1OfReal) ThreeDTol;
// create evaluators and choose appropriate one
Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, First, Last);
Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, First, Last);
Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, First, Last);
Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, myFirst, myLast);
Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, myFirst, myLast);
Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, myFirst, myLast);
AdvApprox_EvaluatorFunction* EvalPtr;
if ( only3d ) EvalPtr = &Eval3dCvOnSurf;
else if ( only2d ) EvalPtr = &Eval2dCvOnSurf;
if ( theOnly3d ) EvalPtr = &Eval3dCvOnSurf;
else if ( theOnly2d ) EvalPtr = &Eval2dCvOnSurf;
else EvalPtr = &EvalCvOnSurf;
// Initialization for 2d approximation
if(!only3d) {
if(!theOnly3d) {
Num1DSS = 2;
OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
Standard_Real TolU, TolV;
TolU = Surf->UResolution(Tol)/2;
TolV = Surf->VResolution(Tol)/2;
TolU = mySurf->UResolution(myTol)/2;
TolV = mySurf->VResolution(myTol)/2;
OneDTol->SetValue(1,TolU);
OneDTol->SetValue(2,TolV);
}
if(!only2d) {
if(!theOnly2d) {
Num3DSS=1;
ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
ThreeDTol->Init(Tol/2);
ThreeDTol->Init(myTol/2);
}
myError2dU = 0;
myError2dV = 0;
myError3d = 0;
Standard_Integer NbInterv_C2 = HCOnS->NbIntervals(GeomAbs_C2);
TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2 + 1);
@@ -369,8 +434,8 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
OneDTol, TwoDTolNul, ThreeDTol,
First, Last, Order,
MaxDegree, MaxSegments,
myFirst, myLast, theContinuity,
theMaxDegree, theMaxSegments,
*EvalPtr, CutTool);
myIsDone = aApprox.IsDone();
@@ -381,14 +446,14 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
Standard_Integer Degree = aApprox.Degree();
if(!only2d)
if(!theOnly2d)
{
TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
aApprox.Poles(1,Poles);
myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
myError3d = aApprox.MaxError(3, 1);
}
if(!only3d)
if(!theOnly3d)
{
TColgp_Array1OfPnt2d Poles2d(1,aApprox.NbPoles());
TColStd_Array1OfReal Poles1dU(1,aApprox.NbPoles());
@@ -404,8 +469,6 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
}
}
// }
}
Standard_Boolean Approx_CurveOnSurface::IsDone() const
@@ -443,3 +506,215 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
return myError2dV;
}
//=============================================================================
//function : isIsoLine
//purpose :
//=============================================================================
Standard_Boolean Approx_CurveOnSurface::isIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
Standard_Boolean& theIsU,
Standard_Real& theParam,
Standard_Boolean& theIsForward) const
{
// 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;
}
#include <GeomLib.hxx>
//=============================================================================
//function : buildC3dOnIsoLine
//purpose :
//=============================================================================
Standard_Boolean Approx_CurveOnSurface::buildC3dOnIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
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(mySurf);
if (aGeomAdapter.IsNull())
return Standard_False;
if (mySurf->GetType() == GeomAbs_Sphere)
return Standard_False;
// 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 - 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);
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);
if (isToTrim)
aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
}
// Convert arbitrary curve type to the b-spline.
myCurve3d = GeomConvert::CurveToBSplineCurve(aC3d, Convert_QuasiAngular);
if (!theIsForward)
myCurve3d->Reverse();
// Rebuild parameterization for the 3d curve to have the same parameterization with
// a two-dimensional curve.
TColStd_Array1OfReal aKnots = myCurve3d->Knots();
BSplCLib::Reparametrize(theC2D->FirstParameter(), theC2D->LastParameter(), aKnots);
myCurve3d->SetKnots(aKnots);
// Evaluate error.
myError3d = 0.0;
const Standard_Real aParF = myFirst;
const Standard_Real aParL = myLast;
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 = myCurve3d->Value(aPar);
const gp_Pnt aPntC2D = mySurf->Value(aPnt2d.X(), aPnt2d.Y());
const Standard_Real aSqDeviation = aPntC3D.SquareDistance(aPntC2D);
myError3d = Max(aSqDeviation, myError3d);
}
myError3d = Sqrt(myError3d);
// 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 (myError3d > myTol)
return Standard_False;
return Standard_True;
}

View File

@@ -40,9 +40,22 @@ public:
DEFINE_STANDARD_ALLOC
//! This constructor calls perform method. This constructor is deprecated.
Standard_DEPRECATED("This constructor is deprecated. Use other constructor and perform method instead.")
Standard_EXPORT Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D, const Handle(Adaptor3d_HSurface)& Surf, const Standard_Real First, const Standard_Real Last, const Standard_Real Tol, const GeomAbs_Shape Continuity, const Standard_Integer MaxDegree, const Standard_Integer MaxSegments, const Standard_Boolean Only3d = Standard_False, const Standard_Boolean Only2d = Standard_False);
//! This constructor does not call perform method.
//! @param theC2D 2D Curve to be approximated in 3D.
//! @param theSurf Surface where 2D curve is located.
//! @param theFirst First parameter of resulting curve.
//! @param theFirst Last parameter of resulting curve.
//! @param theTol Computation tolerance.
Standard_EXPORT Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& theC2D,
const Handle(Adaptor3d_HSurface)& theSurf,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Real theTol);
Standard_EXPORT Standard_Boolean IsDone() const;
Standard_EXPORT Standard_Boolean HasResult() const;
@@ -59,18 +72,64 @@ public:
//! 2d Curve
Standard_EXPORT Standard_Real MaxError2dV() const;
//! Constructs the 3d curve. Input parameters are ignored when the input curve is
//! U-isoline or V-isoline.
//! @param theMaxSegments Maximal number of segments in the resulting spline.
//! @param theMaxDegree Maximal degree of the result.
//! @param theContinuity Resulting continuity.
//! @param theOnly3d Determines building only 3D curve.
//! @param theOnly2d Determines building only 2D curve.
Standard_EXPORT void Perform(const Standard_Integer theMaxSegments,
const Standard_Integer theMaxDegree,
const GeomAbs_Shape theContinuity,
const Standard_Boolean theOnly3d = Standard_False,
const Standard_Boolean theOnly2d = Standard_False);
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_Boolean isIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
Standard_Boolean& theIsU,
Standard_Real& theParam,
Standard_Boolean& theIsForward) const;
//! 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_Boolean buildC3dOnIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
const Standard_Boolean theIsU,
const Standard_Real theParam,
const Standard_Boolean theIsForward);
private:
Approx_CurveOnSurface& operator= (const Approx_CurveOnSurface&);
private:
//! Input curve.
const Handle(Adaptor2d_HCurve2d) myC2D;
//! Input surface.
const Handle(Adaptor3d_HSurface) mySurf;
//! First parameter of the result.
const Standard_Real myFirst;
//! Last parameter of the result.
const Standard_Real myLast;
//! Tolerance.
Standard_Real myTol;
Handle(Geom2d_BSplineCurve) myCurve2d;
Handle(Geom_BSplineCurve) myCurve3d;

View File

@@ -366,9 +366,8 @@ void BRepAlgo_NormalProjection::SetDefaultParams()
#ifdef OCCT_DEBUG_CHRONO
InitChron(chr_approx);
#endif
Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d,
myContinuity, myMaxDegree, myMaxSeg,
Only3d, Only2d);
Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d);
appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d);
#ifdef OCCT_DEBUG_CHRONO
ResultChron(chr_approx,t_approx);
approx_count++;

View File

@@ -329,8 +329,9 @@ static Standard_Boolean SameParameter(TopoDS_Edge& E,
if (!HasPCurves(E))
{
Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( Pcurv );
Approx_CurveOnSurface AppCurve(HC2d, S, HC2d->FirstParameter(), HC2d->LastParameter(),
Precision::Confusion(), GeomAbs_C1, 10, 10, Standard_True);
Approx_CurveOnSurface AppCurve(HC2d, S, HC2d->FirstParameter(), HC2d->LastParameter(),
Precision::Confusion());
AppCurve.Perform(10, 10, GeomAbs_C1, Standard_True);
if (AppCurve.IsDone() && AppCurve.HasResult())
{
C3d = AppCurve.Curve3d();

View File

@@ -2169,9 +2169,8 @@ static Standard_Real SmartParameter(Draft_EdgeInfo& Einf,
Standard_Real Udeb, Ufin;
ProjCurve.Bounds(1, Udeb, Ufin);
Standard_Integer MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
Approx_CurveOnSurface appr( HProjector, hsur2, Udeb, Ufin, Tol,
GeomAbs_C1, 10, MaxSeg,
Standard_False, Standard_False );
Approx_CurveOnSurface appr(HProjector, hsur2, Udeb, Ufin, Tol);
appr.Perform(MaxSeg, 10, GeomAbs_C1, Standard_False, Standard_False);
Einf.ChangeSecondPC() = appr.Curve2d();
Einf.ChangeGeometry() = appr.Curve3d();
Einf.SetNewGeometry( Standard_True );

View File

@@ -1031,9 +1031,8 @@ void GeomInt_IntSS::TreatRLine(const Handle(IntPatch_RLine)& theRL,
//approximation of curve on surface.
Standard_Integer aMaxDeg = 8;
Standard_Integer aMaxSeg = 1000;
Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion(),
GeomAbs_C1, aMaxDeg, aMaxSeg,
Standard_True, Standard_False);
Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion());
anApp.Perform(aMaxSeg, aMaxDeg, GeomAbs_C1, Standard_True, Standard_False);
if(!anApp.HasResult())
return;

View File

@@ -48,6 +48,7 @@
#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>
@@ -1095,7 +1096,6 @@ void GeomLib::BuildCurve3d(const Standard_Real Tolerance,
{
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()) );
@@ -1126,11 +1126,23 @@ void GeomLib::BuildCurve3d(const Standard_Real Tolerance,
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
@@ -1182,7 +1194,6 @@ void GeomLib::BuildCurve3d(const Standard_Real Tolerance,
AverageDeviation = anApproximator.AverageError(3,1) ;
NewCurvePtr = aCurvePtr ;
}
}
}
//=======================================================================
@@ -2783,3 +2794,218 @@ static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1,
//
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;
}

View File

@@ -34,6 +34,8 @@ class gp_Ax2;
class Geom2d_Curve;
class gp_GTrsf2d;
class Adaptor3d_CurveOnSurface;
class Adaptor2d_HCurve2d;
class Adaptor3d_HSurface;
class Geom_BoundedCurve;
class gp_Pnt;
class gp_Vec;
@@ -223,12 +225,37 @@ public:
const Standard_Real V2,
const Standard_Real Tol);
//! 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:

View File

@@ -307,10 +307,9 @@ Handle(Geom2d_Curve) GeomPlate_BuildPlateSurface::ProjectCurve(const Handle(Ada
Projector.Bounds(1, Udeb, Ufin);
MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
Approx_CurveOnSurface appr(HProjector, hsur, Udeb, Ufin, myTol3d,
Continuity, MaxDegree, MaxSeg,
Standard_False, Standard_True);
Approx_CurveOnSurface appr(HProjector, hsur, Udeb, Ufin, myTol3d);
appr.Perform(MaxSeg, MaxDegree, Continuity, Standard_False, Standard_True);
Curve2d = appr.Curve2d();
}
#if DRAW

View File

@@ -340,8 +340,8 @@ Handle(Geom_Curve) GeomProjLib::Project( const Handle(Geom_Curve)& C,
Standard_Real f,l;
Proj.Bounds(1,f,l);
Handle(Adaptor2d_HCurve2d) HC2d = Proj.Trim(f,l,TolU);
Approx_CurveOnSurface Approx(HC2d, HS, f, l, Tol,
GeomAbs_C2,14,16,Standard_True);
Approx_CurveOnSurface Approx(HC2d, HS, f, l, Tol);
Approx.Perform(16, 14, GeomAbs_C2, Standard_True);
// ici, on a toujours un type BSpline.
if (Approx.IsDone() && Approx.HasResult())

View File

@@ -367,9 +367,8 @@ static Standard_Integer gproject(Draw_Interpretor& di, Standard_Integer n, const
return 0;
}
else {
Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d,
myContinuity, myMaxDegree, myMaxSeg,
Only3d, Only2d);
Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d);
appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d);
if(!Only3d) {
PCur2d = appr.Curve2d();
di << " Error in 2d is " << appr.MaxError2dU()

View File

@@ -1497,9 +1497,8 @@ static Standard_Integer approxcurveonsurf(Draw_Interpretor& di, Standard_Integer
Handle(Geom2dAdaptor_HCurve) A2d = new (Geom2dAdaptor_HCurve)(curve2d);
Handle(GeomAdaptor_HSurface) AS = new (GeomAdaptor_HSurface)(Surf);
Approx_CurveOnSurface App(A2d, AS, A2d->FirstParameter(), A2d->LastParameter(),
Tol, Continuity, MaxDeg, MaxSeg,
Standard_True, Standard_False);
Approx_CurveOnSurface App(A2d, AS, A2d->FirstParameter(), A2d->LastParameter(), Tol);
App.Perform(MaxSeg, MaxDeg, Continuity, Standard_True, Standard_False);
if(App.HasResult()) {
Handle(Geom_BSplineCurve) BSCurve = App.Curve3d();

View File

@@ -647,9 +647,8 @@ void ProjLib_ProjectedCurve::Perform(const Handle(Adaptor3d_HCurve)& C)
MaxSeg = myMaxSegments;
}
Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin,
myTolerance, Continuity, MaxDegree, MaxSeg,
Only3d, Only2d);
Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, myTolerance);
appr.Perform(MaxSeg, MaxDegree, Continuity, Only3d, Only2d);
Handle(Geom2d_BSplineCurve) aRes = appr.Curve2d();

View File

@@ -979,8 +979,11 @@ ShapeFix_WireSegment ShapeFix_ComposeShell::SplitWire (ShapeFix_WireSegment &wir
currPnt = myGrid->Value ( currPnt2d );
if ( currPnt.Distance ( lastVPnt ) <= lastVTol &&
lastPnt.Distance ( currPnt ) <= tol &&
// Tolerance is increased to prevent degenerated cuts in cases where all vertex
// tolerance is covered by distance of the edge curve from vertex point.
// Doubled to prevent edge being fully covered by its vertices tolerance (invalid edge).
CheckByCurve3d ( lastVPnt, c3d, f3d+(currPar-firstPar)*(l3d-f3d)/span2d,
T, lastVTol ) &&
T, lastVTol + 2 * Precision::Confusion() ) &&
lastPnt.Distance ( myGrid->Value ( C2d->Value(0.5*(currPar+lastPar)) ) ) <= tol ) {
V = lastV;
Standard_Real uRes = myUResolution;
@@ -999,8 +1002,11 @@ ShapeFix_WireSegment ShapeFix_ComposeShell::SplitWire (ShapeFix_WireSegment &wir
}
else if ( currPnt.Distance ( prevVPnt ) <= prevVTol &&
prevPnt.Distance ( currPnt ) <= tol &&
// Tolerance is increased to prevent degenerated cuts in cases where all vertex
// tolerance is covered by distance of the edge curve from vertex point.
// Doubled to prevent edge being fully covered by its vertices tolerance (invalid edge).
CheckByCurve3d ( prevVPnt, c3d, f3d+(currPar-firstPar)*(l3d-f3d)/span2d,
T, prevVTol ) &&
T, prevVTol + 2 * Precision::Confusion()) &&
prevPnt.Distance ( myGrid->Value ( C2d->Value(0.5*(currPar+prevPar)) ) ) <= tol ) {
V = prevV;
Standard_Real uRes = myUResolution;

4
tests/bugs/heal/bug31202 Normal file
View File

@@ -0,0 +1,4 @@
restore [locate_data_file bug31202.brep] shape
fixshape result shape 0.000001137 0.0001137
checkshape result
checknbshapes result -edge 4

View File

@@ -20,9 +20,9 @@ vsetdispmode result 1
vdisplay result
vfit
checktrinfo result -tri 9250 -nod 7593
checktrinfo result -tri 5812 -nod 5809
checkmaxtol result -ref 0.92213088179312575
checknbshapes result -shell 1
checkfreebounds result 265
checkfreebounds result 239
checkview -display result -3d -path ${imagedir}/${test_image}.png

View File

@@ -0,0 +1,20 @@
puts "================"
puts "0030932: Modeling Algorithms - Invalid result on 2d curve on surface approximation"
puts "================"
puts ""
# Prepare data.
restore [locate_data_file bug30932_c2d] c2d
restore [locate_data_file bug30932_sur] sur
# Approximate.
approxcurveonsurf res c2d sur
# Length check.
checklength res -l 150.02782767924231
# Visual check.
axo;
don res;
fit;
checkview -screenshot -2d -path ${imagedir}/${test_image}.png

View File

@@ -1,9 +1,11 @@
# !!!! This file is generated automatically, do not edit manually! See end script
puts "TODO CR30889 ALL: TPSTAT : Faulty"
set filename CTS21866.igs
set ref_data {
DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 1 ) Summary = 0 ( 1 )
TPSTAT : Faulties = 0 ( 0 ) Warnings = 82 ( 85 ) Summary = 82 ( 85 )
DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 11531 ) Summary = 0 ( 11531 )
TPSTAT : Faulties = 0 ( 0 ) Warnings = 92 ( 91 ) Summary = 92 ( 91 )
CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 )
NBSHAPES : Solid = 0 ( 0 ) Shell = 0 ( 0 ) Face = 1459 ( 1459 ) Summary = 19160 ( 19160 )
STATSHAPE : Solid = 0 ( 0 ) Shell = 0 ( 0 ) Face = 1459 ( 1459 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 8093 ( 8093 )

View File

@@ -1,6 +1,5 @@
# !!!! This file is generated automatically, do not edit manually! See end script
puts "TODO CR23096 ALL: TPSTAT : Faulty"
puts "TODO CR23096 ALL: CHECKSHAPE : Faulty"
set LinuxDiff 2
set filename bm1_sy_exhaust.stp

View File

@@ -6,4 +6,4 @@ set OffsetValue 10.0
# Reference data.
set ExpectedMass 178976
set ExpectedMaxTol 0.479111
set ExpectedMaxTol 0.470985