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

0023824: Bad results of sweep operation when a path curve has unpredictable torsion along its way.

Adding test cases for this fix
This commit is contained in:
jgv
2013-03-22 17:10:51 +04:00
parent 26347898a8
commit a31abc03d7
26 changed files with 1226 additions and 105 deletions

View File

@@ -67,7 +67,7 @@ is
enumeration Trihedron
is IsCorrectedFrenet, IsFixed, IsFrenet, IsConstantNormal, IsDarboux,
IsGuideAC, IsGuidePlan,
IsGuideACWithContact, IsGuidePlanWithContact end;
IsGuideACWithContact, IsGuidePlanWithContact, IsDiscreteTrihedron end;
class Filling;
---Purpose: Root class for Filling;
@@ -195,6 +195,13 @@ is
class SequenceOfTrsf
instantiates Sequence from TCollection (Trsf from gp);
class SequenceOfAx2
instantiates Sequence from TCollection (Ax2 from gp);
class HSequenceOfAx2
instantiates HSequence from TCollection (Ax2 from gp,
SequenceOfAx2 from GeomFill);
--
-- private classes
--
@@ -226,6 +233,7 @@ is
class Fixed;
class Frenet;
class CorrectedFrenet;
class DiscreteTrihedron;
class ConstantBiNormal;
class Darboux;
class DraftTrihedron;

View File

@@ -37,7 +37,8 @@ uses
HArray1OfReal from TColStd,
SequenceOfReal from TColStd,
HArray1OfVec from TColgp,
SequenceOfVec from TColgp
SequenceOfVec from TColgp,
Trihedron from GeomFill
raises
OutOfRange, ConstructionError
@@ -45,11 +46,14 @@ is
Create returns CorrectedFrenet from GeomFill;
Create (ForEvaluation: Boolean)
returns CorrectedFrenet from GeomFill;
Copy(me)
returns TrihedronLaw from GeomFill
is redefined;
Init(me: mutable)
Init(me: mutable)
is static private;
InitInterval(me; First, Last, Step: Real;
@@ -59,7 +63,7 @@ is
SeqPoles: out SequenceOfReal from TColStd;
SeqAngle: out SequenceOfReal from TColStd;
SeqTangent: out SequenceOfVec from TColgp;
SeqNormal: out SequenceOfVec from TColgp)
SeqNormal: out SequenceOfVec from TColgp)
returns Boolean
--- Purpose: Computes BSpline representation of Normal evolution at one
--- interval of continuity of Frenet. Returns True if FuncInt = 0
@@ -142,6 +146,20 @@ is
OutOfRange from Standard
is redefined;
-- =================== To define the best trihedron mode ===============
EvaluateBestMode(me : mutable)
returns Trihedron from GeomFill;
---Purpose: Tries to define the best trihedron mode
-- for the curve. It can be:
-- - Frenet
-- - CorrectedFrenet
-- - DiscreteTrihedron
-- Warning: the CorrectedFrenet must be constructed
-- with option ForEvaluation = True,
-- the curve must be set by method SetCurve.
-- =================== To help computation of Tolerance ===============
GetAverageLaw(me : mutable;
@@ -165,11 +183,13 @@ is
is redefined;
fields
frenet : Frenet from GeomFill;
EvolAroundT : Function from Law;
TLaw : Function from Law;
AT, AN : Vec from gp;
isFrenet : Boolean;
frenet : Frenet from GeomFill;
EvolAroundT : Function from Law;
TLaw : Function from Law;
AT, AN : Vec from gp;
isFrenet : Boolean;
myForEvaluation : Boolean;
---OCC78
HArrPoles : HArray1OfReal from TColStd;
HArrAngle : HArray1OfReal from TColStd;

View File

@@ -44,6 +44,7 @@
#include <Geom_BSplineCurve.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#ifdef DEB
static Standard_Boolean Affich=0;
#endif
@@ -90,6 +91,30 @@ static void draw(const Handle(Law_Function)& law)
}
#endif
static Standard_Real ComputeTorsion(const Standard_Real Param,
const Handle(Adaptor3d_HCurve)& aCurve)
{
Standard_Real Torsion;
gp_Pnt aPoint;
gp_Vec DC1, DC2, DC3;
aCurve->D3(Param, aPoint, DC1, DC2, DC3);
gp_Vec DC1crossDC2 = DC1 ^ DC2;
Standard_Real Norm_DC1crossDC2 = DC1crossDC2.Magnitude();
Standard_Real DC1DC2DC3 = DC1crossDC2 * DC3 ; //mixed product
Standard_Real Tol = gp::Resolution();
Standard_Real SquareNorm_DC1crossDC2 = Norm_DC1crossDC2 * Norm_DC1crossDC2;
if (SquareNorm_DC1crossDC2 <= Tol)
Torsion = 0.;
else
Torsion = DC1DC2DC3 / SquareNorm_DC1crossDC2 ;
return Torsion;
}
//===============================================================
// Function : smoothlaw
// Purpose : to smooth a law : Reduce the number of knots
@@ -280,13 +305,25 @@ static Standard_Boolean FindPlane ( const Handle(Adaptor3d_HCurve)& c,
}
//===============================================================
// Function :
// Function : Constructor
// Purpose :
//===============================================================
GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet()
: isFrenet(Standard_False)
{
frenet = new GeomFill_Frenet();
myForEvaluation = Standard_False;
}
//===============================================================
// Function : Constructor
// Purpose :
//===============================================================
GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet(const Standard_Boolean ForEvaluation)
: isFrenet(Standard_False)
{
frenet = new GeomFill_Frenet();
myForEvaluation = ForEvaluation;
}
Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
@@ -314,6 +351,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
{
// No probleme isFrenet
isFrenet = Standard_True;
break;
}
default :
{
@@ -382,8 +420,12 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
for(i = 1; i <= NbI; i++) {
NbStep = Max(Standard_Integer((T(i+1) - T(i))/AvStep), 3);
Step = (T(i+1) - T(i))/NbStep;
if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func, SeqPoles, SeqAngle, SeqTangent, SeqNormal))
if(isFrenet) isFrenet = Standard_False;
if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func,
SeqPoles, SeqAngle, SeqTangent, SeqNormal))
{
if(isFrenet)
isFrenet = Standard_False;
}
Handle(Law_Composite)::DownCast(EvolAroundT)->ChangeLaws().Append(Func);
}
if(myTrimmed->IsPeriodic())
@@ -402,7 +444,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
HArrTangent->ChangeValue(i) = SeqTangent(i);
HArrNormal->ChangeValue(i) = SeqNormal(i);
};
#if DRAW
if (Affich) {
draw(EvolAroundT);
@@ -431,6 +473,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
TColStd_SequenceOfReal EvolAT;
Standard_Real Param = First, LengthMin, L, norm;
Standard_Boolean isZero = Standard_True, isConst = Standard_True;
const Standard_Real minnorm = 1.e-16;
Standard_Integer i;
gp_Pnt PonC;
gp_Vec D1;
@@ -446,7 +489,9 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
Standard_Real angleAT, currParam, currStep = Step;
Handle( Geom_Plane ) aPlane;
Standard_Boolean isPlanar = FindPlane( myCurve, aPlane );
Standard_Boolean isPlanar = Standard_False;
if (!myForEvaluation)
isPlanar = FindPlane( myCurve, aPlane );
i = 1;
currParam = Param;
@@ -493,13 +538,21 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const
//Evaluate the Next step
CS.D1(Param, PonC, D1);
L = Max(PonC.XYZ().Modulus()/2, LengthMin);
L = PonC.XYZ().Modulus()/2;
norm = D1.Magnitude();
if (norm < Precision::Confusion()) {
norm = Precision::Confusion();
if (norm <= gp::Resolution())
{
//norm = 2.*gp::Resolution();
norm = minnorm;
}
currStep = L / norm;
if (currStep > Step) currStep = Step;//default value
if (currStep <= gp::Resolution()) //L = 0 => curvature = 0, linear segment
currStep = Step;
if (currStep < Precision::Confusion()) //too small step
currStep = Precision::Confusion();
if (currStep > Step) //too big step
currStep = Step;//default value
}
else
currStep /= 2; // Step too long !
@@ -887,6 +940,59 @@ Standard_Real GeomFill_CorrectedFrenet::GetAngleAT(const Standard_Real Param) co
Precision::PConfusion()/2);
}
//===============================================================
// Function : EvaluateBestMode
// Purpose :
//===============================================================
GeomFill_Trihedron GeomFill_CorrectedFrenet::EvaluateBestMode()
{
if (EvolAroundT.IsNull())
return GeomFill_IsFrenet; //Frenet
const Standard_Real MaxAngle = 3.*M_PI/4.;
const Standard_Real MaxTorsion = 100.;
Standard_Real Step, u, v, tmin, tmax;
Standard_Integer NbInt, i, j, k = 1;
NbInt = EvolAroundT->NbIntervals(GeomAbs_CN);
TColStd_Array1OfReal Int(1, NbInt+1);
EvolAroundT->Intervals(Int, GeomAbs_CN);
gp_Pnt2d old;
gp_Vec2d aVec, PrevVec;
Standard_Integer NbSamples = 10;
for(i = 1; i <= NbInt; i++){
tmin = Int(i);
tmax = Int(i+1);
Standard_Real Torsion = ComputeTorsion(tmin, myTrimmed);
if (Abs(Torsion) > MaxTorsion)
return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
Handle(Law_Function) trimmedlaw = EvolAroundT->Trim(tmin, tmax, Precision::PConfusion()/2);
Step = (Int(i+1)-Int(i))/NbSamples;
for (j = 0; j <= NbSamples; j++) {
u = tmin + j*Step;
v = trimmedlaw->Value(u);
gp_Pnt2d point2d(u,v);
if (j != 0)
{
aVec.SetXY(point2d.XY() - old.XY());
if (k > 2)
{
Standard_Real theAngle = PrevVec.Angle(aVec);
if (Abs(theAngle) > MaxAngle)
return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron
}
PrevVec = aVec;
}
old = point2d;
k++;
}
}
return GeomFill_IsCorrectedFrenet; //CorrectedFrenet
}
//===============================================================
// Function : GetAverageLaw
// Purpose :

View File

@@ -0,0 +1,154 @@
-- Created on: 2013-02-05
-- Created by: Julia GERASIMOVA
-- Copyright (c) 2001-2013 OPEN CASCADE SAS
--
-- The content of this file is subject to the Open CASCADE Technology Public
-- License Version 6.5 (the "License"). You may not use the content of this file
-- except in compliance with the License. Please obtain a copy of the License
-- at http://www.opencascade.org and read it completely before using this file.
--
-- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
--
-- The Original Code and all software distributed under the License is
-- distributed on an "AS IS" basis, without warranty of any kind, and the
-- Initial Developer hereby disclaims all such warranties, including without
-- limitation, any warranties of merchantability, fitness for a particular
-- purpose or non-infringement. Please see the License for the specific terms
-- and conditions governing the rights and limitations under the License.
class DiscreteTrihedron from GeomFill
inherits TrihedronLaw from GeomFill
---Purpose: Defined Discrete Trihedron Law.
-- The requirement for path curve is only G1.
-- The result is C0-continuous surface
-- that can be later approximated to C1.
uses
HCurve from Adaptor3d,
Shape from GeomAbs,
Pnt from gp,
Vec from gp,
Array1OfReal from TColStd,
Frenet from GeomFill,
HSequenceOfAx2 from GeomFill,
HSequenceOfReal from TColStd
raises
OutOfRange, ConstructionError
is
Create
returns DiscreteTrihedron from GeomFill
raises ConstructionError;
Copy(me)
returns TrihedronLaw from GeomFill
is redefined;
Init(me: mutable)
is static;
SetCurve(me : mutable; C : HCurve from Adaptor3d)
is redefined;
--
--
--========== To compute Location and derivatives Location
--
D0(me : mutable;
Param: Real;
Tangent : out Vec from gp;
Normal : out Vec from gp;
BiNormal : out Vec from gp)
---Purpose: compute Trihedron on curve at parameter <Param>
returns Boolean is redefined;
D1(me : mutable;
Param: Real;
Tangent : out Vec from gp;
DTangent : out Vec from gp;
Normal : out Vec from gp;
DNormal : out Vec from gp;
BiNormal : out Vec from gp;
DBiNormal : out Vec from gp)
---Purpose: compute Trihedron and derivative Trihedron on curve
-- at parameter <Param>
-- Warning : It used only for C1 or C2 aproximation
-- For the moment it returns null values for DTangent, DNormal
-- and DBiNormal.
returns Boolean
is redefined;
D2(me : mutable;
Param: Real;
Tangent : out Vec from gp;
DTangent : out Vec from gp;
D2Tangent : out Vec from gp;
Normal : out Vec from gp;
DNormal : out Vec from gp;
D2Normal : out Vec from gp;
BiNormal : out Vec from gp;
DBiNormal : out Vec from gp;
D2BiNormal : out Vec from gp)
---Purpose: compute Trihedron on curve
-- first and seconde derivatives.
-- Warning : It used only for C2 aproximation
-- For the moment it returns null values for DTangent, DNormal
-- DBiNormal, D2Tangent, D2Normal, D2BiNormal.
returns Boolean
is redefined;
--
-- =================== Management of continuity ===================
--
NbIntervals(me; S : Shape from GeomAbs)
---Purpose: Returns the number of intervals for continuity
-- <S>.
-- May be one if Continuity(me) >= <S>
returns Integer is redefined;
Intervals(me; T : in out Array1OfReal from TColStd;
S : Shape from GeomAbs)
---Purpose: Stores in <T> the parameters bounding the intervals
-- of continuity <S>.
--
-- The array must provide enough room to accomodate
-- for the parameters. i.e. T.Length() > NbIntervals()
raises
OutOfRange from Standard
is redefined;
-- =================== To help computation of Tolerance ===============
GetAverageLaw(me : mutable;
ATangent : out Vec from gp;
ANormal : out Vec from gp;
ABiNormal : out Vec from gp)
---Purpose: Get average value of Tangent(t) and Normal(t) it is usful to
-- make fast approximation of rational surfaces.
is redefined;
-- =================== To help Particular case ===============
IsConstant(me)
---Purpose: Say if the law is Constant.
returns Boolean
is redefined;
IsOnlyBy3dCurve(me)
---Purpose: Return True.
returns Boolean
is redefined;
fields
myPoint : Pnt from gp;
myTrihedrons : HSequenceOfAx2 from GeomFill;
myKnots : HSequenceOfReal from TColStd;
myFrenet : Frenet from GeomFill;
myUseFrenet : Boolean from Standard;
end DiscreteTrihedron;

View File

@@ -0,0 +1,392 @@
// Created on: 2013-02-05
// Created by: Julia GERASIMOVA
// Copyright (c) 2001-2013 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <GeomFill_DiscreteTrihedron.ixx>
#include <GeomFill_DiscreteTrihedron.hxx>
#include <GeomFill_Frenet.hxx>
#include <GeomAbs_CurveType.hxx>
#include <Adaptor3d_HCurve.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HSequenceOfReal.hxx>
#include <GeomFill_HSequenceOfAx2.hxx>
static const Standard_Real TolConf = Precision::Confusion();
//=======================================================================
//function : GeomFill_DiscreteTrihedron
//purpose : Constructor
//=======================================================================
GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron()
{
myFrenet = new GeomFill_Frenet();
myKnots = new TColStd_HSequenceOfReal();
myTrihedrons = new GeomFill_HSequenceOfAx2();
}
//=======================================================================
//function : Copy
//purpose :
//=======================================================================
Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const
{
Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)();
if (!myCurve.IsNull()) copy->SetCurve(myCurve);
return copy;
}
//=======================================================================
//function : SetCurve
//purpose :
//=======================================================================
void GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_HCurve)& C)
{
GeomFill_TrihedronLaw::SetCurve(C);
if (! C.IsNull()) {
GeomAbs_CurveType type;
type = C->GetType();
switch (type) {
case GeomAbs_Circle:
case GeomAbs_Ellipse:
case GeomAbs_Hyperbola:
case GeomAbs_Parabola:
case GeomAbs_Line:
{
// No probleme
myUseFrenet = Standard_True;
myFrenet->SetCurve(C);
break;
}
default :
{
myUseFrenet = Standard_False;
// We have to fill <myKnots> and <myTrihedrons>
Init();
break;
}
}
}
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void GeomFill_DiscreteTrihedron::Init()
{
Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN);
TColStd_Array1OfReal Knots(1, NbIntervals+1);
myTrimmed->Intervals(Knots, GeomAbs_CN);
//Standard_Real Tol = Precision::Confusion();
Standard_Integer NbSamples = 10;
Standard_Integer i, j;
for (i = 1; i <= NbIntervals; i++)
{
Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples;
for (j = 0; j < NbSamples; j++)
{
Standard_Real Param = Knots(i) + j*delta;
myKnots->Append(Param);
}
}
myKnots->Append(Knots(NbIntervals+1));
gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt;
gp_Vec Tangent;
gp_Dir TangDir;
Standard_Real norm;
for (i = 1; i <= myKnots->Length(); i++)
{
Standard_Real Param = myKnots->Value(i);
myTrimmed->D1(Param, Pnt, Tangent);
norm = Tangent.Magnitude();
if (norm < TolConf)
{
Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples;
if (subdelta < Precision::PConfusion())
subdelta = myKnots->Value(i+1) - myKnots->Value(i);
SubPnt = myTrimmed->Value(Param + subdelta);
Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ());
}
//Tangent.Normalize();
TangDir = Tangent; //normalize;
Tangent = TangDir;
if (i == 1) //first point
{
gp_Ax2 FirstAxis(Origin, TangDir);
myTrihedrons->Append(FirstAxis);
}
else
{
gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length());
gp_Vec LastTangent = LastAxis.Direction();
gp_Vec AxisOfRotation = LastTangent ^ Tangent;
if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite
{
Standard_Real ScalarProduct = LastTangent * Tangent;
if (ScalarProduct > 0.) //tangents are equal
myTrihedrons->Append(LastAxis);
else //tangents are opposite
{
Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.;
if (NewParam - myKnots->Value(i-1) < gp::Resolution())
Standard_ConstructionError::Raise("GeomFill_DiscreteTrihedron : impassable singularities on path curve");
myKnots->InsertBefore(i, NewParam);
i--;
}
}
else //good value of angle
{
Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation);
gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle);
NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
myTrihedrons->Append(NewAxis);
}
}
}
}
//=======================================================================
//function : D0
//purpose :
//=======================================================================
Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& Normal,
gp_Vec& BiNormal)
{
if (myUseFrenet)
{
myFrenet->D0(Param, Tangent, Normal, BiNormal);
}
else
{
//Locate <Param> in the sequence <myKnots>
Standard_Integer Index = -1;
Standard_Real TolPar = Precision::PConfusion();
//Standard_Real TolConf = Precision::Confusion();
Standard_Integer NbSamples = 10;
gp_Pnt Origin(0.,0.,0.);
Standard_Integer i;
//gp_Ax2 PrevAxis;
//Standard_Real PrevParam;
Standard_Integer I1, I2;
I1 = 1;
I2 = myKnots->Length();
for (;;)
{
i = (I1 + I2)/2;
if (Param <= myKnots->Value(i))
I2 = i;
else
I1 = i;
if (I2 - I1 <= 1)
break;
}
Index = I1;
if (Abs(Param - myKnots->Value(I2)) < TolPar)
Index = I2;
Standard_Real PrevParam = myKnots->Value(Index);
gp_Ax2 PrevAxis = myTrihedrons->Value(Index);
gp_Ax2 theAxis;
if (Abs(Param - PrevParam) < TolPar)
theAxis = PrevAxis;
else //<Param> is between knots
{
myTrimmed->D1(Param, myPoint, Tangent);
Standard_Real norm = Tangent.Magnitude();
if (norm < TolConf)
{
Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples;
if (subdelta < Precision::PConfusion())
subdelta = myKnots->Value(Index+1) - Param;
gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta);
Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ());
}
//Tangent.Normalize();
gp_Dir TangDir(Tangent); //normalize;
Tangent = TangDir;
gp_Vec PrevTangent = PrevAxis.Direction();
gp_Vec AxisOfRotation = PrevTangent ^ Tangent;
if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal
{
//we assume that tangents can not be opposite
theAxis = PrevAxis;
}
else //good value of angle
{
Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation);
gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle);
}
theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
} //end of else (Param is between knots)
Tangent = theAxis.Direction();
Normal = theAxis.XDirection();
BiNormal = theAxis.YDirection();
}
return Standard_True;
}
//=======================================================================
//function : D1
//purpose :
//=======================================================================
Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& DTangent,
gp_Vec& Normal,
gp_Vec& DNormal,
gp_Vec& BiNormal,
gp_Vec& DBiNormal)
{
if (myUseFrenet)
{
myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
}
else
{
D0(Param, Tangent, Normal, BiNormal);
DTangent.SetCoord(0.,0.,0.);
DNormal.SetCoord(0.,0.,0.);
DBiNormal.SetCoord(0.,0.,0.);
}
return Standard_True;
}
//=======================================================================
//function : D2
//purpose :
//=======================================================================
Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param,
gp_Vec& Tangent,
gp_Vec& DTangent,
gp_Vec& D2Tangent,
gp_Vec& Normal,
gp_Vec& DNormal,
gp_Vec& D2Normal,
gp_Vec& BiNormal,
gp_Vec& DBiNormal,
gp_Vec& D2BiNormal)
{
if (myUseFrenet)
{
myFrenet->D2(Param, Tangent, DTangent, D2Tangent,
Normal, DNormal, D2Normal,
BiNormal, DBiNormal, D2BiNormal);
}
else
{
D0(Param, Tangent, Normal, BiNormal);
DTangent.SetCoord(0.,0.,0.);
DNormal.SetCoord(0.,0.,0.);
DBiNormal.SetCoord(0.,0.,0.);
D2Tangent.SetCoord(0.,0.,0.);
D2Normal.SetCoord(0.,0.,0.);
D2BiNormal.SetCoord(0.,0.,0.);
}
return Standard_True;
}
//=======================================================================
//function : NbIntervals
//purpose :
//=======================================================================
Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape S) const
{
return (myTrimmed->NbIntervals(GeomAbs_CN));
}
//=======================================================================
//function : Intervals
//purpose :
//=======================================================================
void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T,
const GeomAbs_Shape S) const
{
myTrimmed->Intervals(T, GeomAbs_CN);
}
void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent,
gp_Vec& ANormal,
gp_Vec& ABiNormal)
{
Standard_Integer Num = 20; //order of digitalization
gp_Vec T, N, BN;
ATangent = gp_Vec(0, 0, 0);
ANormal = gp_Vec(0, 0, 0);
ABiNormal = gp_Vec(0, 0, 0);
Standard_Real Step = (myTrimmed->LastParameter() -
myTrimmed->FirstParameter()) / Num;
Standard_Real Param;
for (Standard_Integer i = 0; i <= Num; i++) {
Param = myTrimmed->FirstParameter() + i*Step;
if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
D0(Param, T, N, BN);
ATangent += T;
ANormal += N;
ABiNormal += BN;
}
ATangent /= Num + 1;
ANormal /= Num + 1;
ATangent.Normalize();
ABiNormal = ATangent.Crossed(ANormal).Normalized();
ANormal = ABiNormal.Crossed(ATangent);
}
//=======================================================================
//function : IsConstant
//purpose :
//=======================================================================
Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const
{
return (myCurve->GetType() == GeomAbs_Line);
}
//=======================================================================
//function : IsOnlyBy3dCurve
//purpose :
//=======================================================================
Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const
{
return Standard_True;
}

View File

@@ -141,7 +141,8 @@ is
DoSingular(me: mutable; U: Real; Index: Integer;
Tangent, BiNormal: out Vec from gp;
n, k, TFlag, BNFlag: out Integer)
n, k, TFlag, BNFlag: out Integer;
Delta: out Real)
returns Boolean
is private;
@@ -149,7 +150,8 @@ is
Param: Real; Index: Integer;
Tangent : out Vec from gp;
Normal : out Vec from gp;
BiNormal : out Vec from gp)
BiNormal : out Vec from gp;
Delta : out Real)
---Purpose: computes Triedrhon on curve at parameter <Param>
returns Boolean
is private;
@@ -161,7 +163,8 @@ is
Normal : out Vec from gp;
DNormal : out Vec from gp;
BiNormal : out Vec from gp;
DBiNormal : out Vec from gp)
DBiNormal : out Vec from gp;
Delta : out Real)
---Purpose: computes Triedrhon and derivative Trihedron on curve
-- at parameter <Param>
-- Warning : It used only for C1 or C2 aproximation
@@ -178,7 +181,8 @@ is
D2Normal : out Vec from gp;
BiNormal : out Vec from gp;
DBiNormal : out Vec from gp;
D2BiNormal : out Vec from gp)
D2BiNormal : out Vec from gp;
Delta : out Real)
---Purpose: computes Trihedron on curve
-- first and seconde derivatives.
-- Warning : It used only for C2 aproximation

View File

@@ -326,11 +326,13 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
{
Standard_Real norm;
Standard_Integer Index;
Standard_Real Delta = 0.;
if(IsSingular(Param, Index))
if (SingularD0(Param, Index, Tangent, Normal, BiNormal))
if (SingularD0(Param, Index, Tangent, Normal, BiNormal, Delta))
return Standard_True;
myTrimmed->D2(Param, P, Tangent, BiNormal);
Standard_Real theParam = Param + Delta;
myTrimmed->D2(theParam, P, Tangent, BiNormal);
Tangent.Normalize();
BiNormal = Tangent.Crossed(BiNormal);
norm = BiNormal.Magnitude();
@@ -360,13 +362,15 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
gp_Vec& DBiNormal)
{
Standard_Integer Index;
Standard_Real Delta = 0.;
if(IsSingular(Param, Index))
if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal))
if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal, Delta))
return Standard_True;
// Standard_Real Norma;
Standard_Real theParam = Param + Delta;
gp_Vec DC1, DC2, DC3;
myTrimmed->D3(Param, P, DC1, DC2, DC3);
myTrimmed->D3(theParam, P, DC1, DC2, DC3);
Tangent = DC1.Normalized();
//if (DC2.Magnitude() <= NullTol || Tangent.Crossed(DC2).Magnitude() <= NullTol) {
@@ -412,16 +416,19 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const
gp_Vec& D2BiNormal)
{
Standard_Integer Index;
Standard_Real Delta = 0.;
if(IsSingular(Param, Index))
if(SingularD2(Param, Index, Tangent, DTangent, D2Tangent,
Normal, DNormal, D2Normal,
BiNormal, DBiNormal, D2BiNormal))
BiNormal, DBiNormal, D2BiNormal,
Delta))
return Standard_True;
// Standard_Real Norma;
Standard_Real theParam = Param + Delta;
gp_Vec DC1, DC2, DC3, DC4;
myTrimmed->D3(Param, P, DC1, DC2, DC3);
DC4 = myTrimmed->DN(Param, 4);
myTrimmed->D3(theParam, P, DC1, DC2, DC3);
DC4 = myTrimmed->DN(theParam, 4);
Tangent = DC1.Normalized();
@@ -604,9 +611,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
Standard_Integer& n,
Standard_Integer& k,
Standard_Integer& TFlag,
Standard_Integer& BNFlag)
Standard_Integer& BNFlag,
Standard_Real& Delta)
{
Standard_Integer i, MaxN = 20;
Delta = 0.;
Standard_Real h;
h = 2*mySnglLen->Value(Index);
@@ -615,7 +624,8 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
TFlag = 1;
BNFlag = 1;
GetInterval(A, B);
if (U >= (A + B)/2) h = -h;
if (U >= (A + B)/2)
h = -h;
for(i = 1; i <= MaxN; i++) {
Tangent = myTrimmed->DN(U, i);
if(Tangent.Magnitude() > Precision::Confusion()) break;
@@ -641,7 +651,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
break;
}
}
if (i > MaxN) return Standard_False;
if (i > MaxN)
{
Delta = h;
return Standard_False;
}
BiNormal.Normalize();
k = i;
@@ -657,11 +672,14 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
const Standard_Integer Index,
gp_Vec& Tangent,
gp_Vec& Normal,
gp_Vec& BiNormal)
gp_Vec& BiNormal,
Standard_Real& Delta)
{
Standard_Integer n, k, TFlag, BNFlag;
if(!DoSingular(Param, Index, Tangent, BiNormal,
n, k, TFlag, BNFlag)) return Standard_False;
n, k, TFlag, BNFlag, Delta))
return Standard_False;
Tangent *= TFlag;
BiNormal *= BNFlag;
Normal = BiNormal;
@@ -674,10 +692,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
const Standard_Integer Index,
gp_Vec& Tangent,gp_Vec& DTangent,
gp_Vec& Normal,gp_Vec& DNormal,
gp_Vec& BiNormal,gp_Vec& DBiNormal)
gp_Vec& BiNormal,gp_Vec& DBiNormal,
Standard_Real& Delta)
{
Standard_Integer n, k, TFlag, BNFlag;
if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag)) return Standard_False;
if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta))
return Standard_False;
gp_Vec F, DF, Dtmp;
F = myTrimmed->DN(Param, n);
@@ -715,10 +735,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U,
gp_Vec& D2Normal,
gp_Vec& BiNormal,
gp_Vec& DBiNormal,
gp_Vec& D2BiNormal)
gp_Vec& D2BiNormal,
Standard_Real& Delta)
{
Standard_Integer n, k, TFlag, BNFlag;
if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag))
if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta))
return Standard_False;
gp_Vec F, DF, D2F, Dtmp1, Dtmp2;

View File

@@ -78,7 +78,12 @@ is
-- beetween tangents on the section law and
-- tangent of iso-v on approximed surface
SetForceApproxC1(me : in out;
ForceApproxC1 : Boolean from Standard);
---Purpose: Set the flag that indicates attempt to approximate
-- a C1-continuous surface if a swept surface proved
-- to be C0.
ExchangeUV(me)
---Purpose: returns true if sections are U-Iso
-- This can be produce in some cases when <WithKpart> is True.
@@ -184,8 +189,9 @@ fields
First, Last : Real;
SFirst, SLast: Real;
Tol3d, BoundTol, Tol2d, TolAngular : Real;
SError : Real;
SError : Real;
myForceApproxC1 : Boolean;
myLoc : LocationLaw from GeomFill;
mySec : SectionLaw from GeomFill;
mySurface : Surface from Geom;

View File

@@ -68,6 +68,7 @@
#include <Approx_SweepApproximation.hxx>
#include <AdvApprox_PrefAndRec.hxx>
#include <AdvApprox_ApproxAFunction.hxx>
#include <GeomConvert_ApproxSurface.hxx>
#include <Precision.hxx>
#include <ElCLib.hxx>
@@ -121,6 +122,7 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
myLoc = Location;
myKPart = WithKpart;
SetTolerance(1.e-4);
myForceApproxC1 = Standard_False;
myLoc->GetDomain(First, Last);
SFirst = SLast = 30.081996;
@@ -157,6 +159,18 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
TolAngular = ToleranceAngular;
}
//=======================================================================
//Function : SetForceApproxC1
//Purpose : Set the flag that indicates attempt to approximate
// a C1-continuous surface if a swept surface proved
// to be C0.
//=======================================================================
void GeomFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
{
myForceApproxC1 = ForceApproxC1;
}
//===============================================================
// Function : ExchangeUV
// Purpose :
@@ -298,56 +312,101 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location,
Approx.UDegree(), Approx.VDegree(),
mySec->IsUPeriodic());
SError = Approx. MaxErrorOnSurf();
if (myForceApproxC1 && !mySurface->IsCNv(1))
{
Standard_Real theTol = 1.e-4;
GeomAbs_Shape theUCont = GeomAbs_C1, theVCont = GeomAbs_C1;
Standard_Integer degU = 14, degV = 14;
Standard_Integer nmax = 16;
Standard_Integer thePrec = 1;
GeomConvert_ApproxSurface ConvertApprox(mySurface,theTol,theUCont,theVCont,
degU,degV,nmax,thePrec);
if (ConvertApprox.HasResult())
{
mySurface = ConvertApprox.Surface();
myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2);
CError = new (TColStd_HArray2OfReal) (1,2, 1,2);
const Handle(Geom_BSplineSurface)& BSplSurf =
Handle(Geom_BSplineSurface)::DownCast(mySurface);
gp_Dir2d D(0., 1.);
gp_Pnt2d P(BSplSurf->UKnot(1), 0);
Handle(Geom2d_Line) LC1 = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC1 =
new (Geom2d_TrimmedCurve) (LC1, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
myCurve2d->SetValue(1, TC1);
CError->SetValue(1, 1, 0.);
CError->SetValue(2, 1, 0.);
P.SetCoord(BSplSurf->UKnot(BSplSurf->NbUKnots()), 0);
Handle(Geom2d_Line) LC2 = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC2 =
new (Geom2d_TrimmedCurve) (LC2, 0, BSplSurf->VKnot(BSplSurf->NbVKnots()));
myCurve2d->SetValue(myCurve2d->Length(), TC2);
CError->SetValue(1, myCurve2d->Length(), 0.);
CError->SetValue(2, myCurve2d->Length(), 0.);
SError = theTol;
}
} //if (!mySurface->IsCNv(1))
// Les Courbes 2d
myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
CError = new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
Standard_Integer kk,ii, ifin = 1, ideb;
if (myLoc->HasFirstRestriction()) {
ideb = 1;
}
else {
ideb = 2;
}
ifin += myLoc->TraceNumber();
if (myLoc->HasLastRestriction()) ifin++;
for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
Handle(Geom2d_BSplineCurve) C
= new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
Approx.Curves2dKnots(),
Approx.Curves2dMults(),
Approx.Curves2dDegree());
myCurve2d->SetValue(ii, C);
CError->SetValue(1, ii, Approx.Max2dError(kk));
CError->SetValue(2, ii, Approx.Max2dError(kk));
}
// Si les courbes de restriction, ne sont pas calcules, on prend
// les iso Bords.
if (! myLoc->HasFirstRestriction()) {
gp_Dir2d D(0., 1.);
gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
(LC, First, Last);
myCurve2d->SetValue(1, TC);
CError->SetValue(1, 1, 0.);
CError->SetValue(2, 1, 0.);
}
if (! myLoc->HasLastRestriction()) {
gp_Dir2d D(0., 1.);
gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC =
new (Geom2d_TrimmedCurve) (LC, First, Last);
myCurve2d->SetValue(myCurve2d->Length(), TC);
CError->SetValue(1, myCurve2d->Length(), 0.);
CError->SetValue(2, myCurve2d->Length(), 0.);
}
if (myCurve2d.IsNull())
{
myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber());
CError = new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber());
Standard_Integer kk,ii, ifin = 1, ideb;
if (myLoc->HasFirstRestriction()) {
ideb = 1;
}
else {
ideb = 2;
}
ifin += myLoc->TraceNumber();
if (myLoc->HasLastRestriction()) ifin++;
for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) {
Handle(Geom2d_BSplineCurve) C
= new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk),
Approx.Curves2dKnots(),
Approx.Curves2dMults(),
Approx.Curves2dDegree());
myCurve2d->SetValue(ii, C);
CError->SetValue(1, ii, Approx.Max2dError(kk));
CError->SetValue(2, ii, Approx.Max2dError(kk));
}
// Si les courbes de restriction, ne sont pas calcules, on prend
// les iso Bords.
if (! myLoc->HasFirstRestriction()) {
gp_Dir2d D(0., 1.);
gp_Pnt2d P(UKnots(UKnots.Lower()), 0);
Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve)
(LC, First, Last);
myCurve2d->SetValue(1, TC);
CError->SetValue(1, 1, 0.);
CError->SetValue(2, 1, 0.);
}
if (! myLoc->HasLastRestriction()) {
gp_Dir2d D(0., 1.);
gp_Pnt2d P(UKnots(UKnots.Upper()), 0);
Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D);
Handle(Geom2d_TrimmedCurve) TC =
new (Geom2d_TrimmedCurve) (LC, First, Last);
myCurve2d->SetValue(myCurve2d->Length(), TC);
CError->SetValue(1, myCurve2d->Length(), 0.);
CError->SetValue(2, myCurve2d->Length(), 0.);
}
} //if (myCurve2d.IsNull())
}
return Ok;
}