mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0025124: [Feature request] Removal of continuity checks for offset geometries
Sometimes curve or surface, which is defined as C0, has continuity G1 or above. Offset can be built from these shapes. Therefore, this extended checking was added into SetBasisCurve and SetBasisSurface methods. Main changes in function BRepOffset_Tool::ExtentFace(...): * "return" is added if intersection (in 2D-space) between two edges in a face cannot be found. Basis curve/surface continuity value found (if G1-checking is OK) is set up as BasisContinuity (see myBasisCurveContinuity and myBasisSurfContinuity members which is returned by GetBasisCurveContinuity and GetBasisSurfContinuity() methods). This fact is used in Geom2dAdaptor and in GeomAdaptor classes. Possibility is entered, which allows for basis elements of offset curve/surface to avoid of C0-checking. Test cases were changed according to their new behavior. Test-cases for issue #25124
This commit is contained in:
@@ -614,6 +614,14 @@ is
|
||||
-- Exceptions Standard_RangeError if N is negative.
|
||||
raises RangeError;
|
||||
|
||||
IsG1 (me; theTf, theTl, theAngTol : Real) returns Boolean;
|
||||
---Purpose :
|
||||
-- Check if curve has at least G1 continuity in interval [theTf, theTl]
|
||||
-- Returns true if IsCN(1)
|
||||
-- or
|
||||
-- angle betweem "left" and "right" first derivatives at
|
||||
-- knots with C0 continuity is less then theAngTol
|
||||
-- only knots in interval [theTf, theTl] is checked
|
||||
|
||||
IsClosed (me) returns Boolean;
|
||||
--- Purpose :
|
||||
|
@@ -61,6 +61,87 @@ Standard_Boolean Geom2d_BSplineCurve::IsCN ( const Standard_Integer N) const
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
//=======================================================================
|
||||
//function : IsG1
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2d_BSplineCurve::IsG1 ( const Standard_Real theTf,
|
||||
const Standard_Real theTl,
|
||||
const Standard_Real theAngTol) const
|
||||
{
|
||||
|
||||
if(IsCN(1))
|
||||
{
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
Standard_Integer start = FirstUKnotIndex()+1,
|
||||
finish = LastUKnotIndex()-1;
|
||||
Standard_Integer aDeg = Degree();
|
||||
for(Standard_Integer aNKnot = start; aNKnot <= finish; aNKnot++)
|
||||
{
|
||||
const Standard_Real aTpar = Knot(aNKnot);
|
||||
|
||||
if(aTpar < theTf)
|
||||
continue;
|
||||
if(aTpar > theTl)
|
||||
break;
|
||||
|
||||
Standard_Integer mult = Multiplicity(aNKnot);
|
||||
if (mult < aDeg)
|
||||
continue;
|
||||
|
||||
gp_Pnt2d aP1, aP2;
|
||||
gp_Vec2d aV1, aV2;
|
||||
LocalD1(aTpar, aNKnot-1, aNKnot, aP1, aV1);
|
||||
LocalD1(aTpar, aNKnot, aNKnot+1, aP2, aV2);
|
||||
|
||||
if((aV1.SquareMagnitude() <= gp::Resolution()) ||
|
||||
aV2.SquareMagnitude() <= gp::Resolution())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if(Abs(aV1.Angle(aV2)) > theAngTol)
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if(!IsPeriodic())
|
||||
return Standard_True;
|
||||
|
||||
const Standard_Real aFirstParam = FirstParameter(),
|
||||
aLastParam = LastParameter();
|
||||
|
||||
if( ((aFirstParam - theTf)*(theTl - aFirstParam) < 0.0) &&
|
||||
((aLastParam - theTf)*(theTl - aLastParam) < 0.0))
|
||||
{
|
||||
//Range [theTf, theTl] does not intersect curve bounadries
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//Curve is closed or periodic and range [theTf, theTl]
|
||||
//intersect curve boundary. Therefore, it is necessary to
|
||||
//check if curve is smooth in its first and last point.
|
||||
|
||||
gp_Pnt2d aP;
|
||||
gp_Vec2d aV1, aV2;
|
||||
D1(Knot(FirstUKnotIndex()), aP, aV1);
|
||||
D1(Knot(LastUKnotIndex()), aP, aV2);
|
||||
|
||||
if((aV1.SquareMagnitude() <= gp::Resolution()) ||
|
||||
aV2.SquareMagnitude() <= gp::Resolution())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if(Abs(aV1.Angle(aV2)) > theAngTol)
|
||||
return Standard_False;
|
||||
|
||||
|
||||
return Standard_True;
|
||||
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IsClosed
|
||||
|
@@ -77,7 +77,11 @@ raises ConstructionError from Standard,
|
||||
is
|
||||
|
||||
|
||||
Create (C : Curve from Geom2d; Offset : Real) returns OffsetCurve
|
||||
Create (C : Curve from Geom2d;
|
||||
Offset : Real;
|
||||
isNotCheckC0 : Boolean = Standard_False)
|
||||
|
||||
returns OffsetCurve
|
||||
--- Purpose : Constructs a curve offset from the basis curve C,
|
||||
-- where Offset is the distance between the offset
|
||||
-- curve and the basis curve at any point.
|
||||
@@ -89,11 +93,14 @@ is
|
||||
-- the offset value is measured is indicated by this
|
||||
-- normal vector if Offset is positive, or in the inverse
|
||||
-- sense if Offset is negative.
|
||||
-- If isNotCheckC0 = TRUE checking if basis curve has C0-continuity
|
||||
-- is not made.
|
||||
-- Warnings :
|
||||
-- In this package the entities are not shared. The OffsetCurve is
|
||||
-- built with a copy of the curve C. So when C is modified the
|
||||
-- OffsetCurve is not modified
|
||||
-- Warning! ConstructionError raised if the basis curve C is not at least C1.
|
||||
-- Warning! if isNotCheckC0 = false,
|
||||
-- ConstructionError raised if the basis curve C is not at least C1.
|
||||
-- No check is done to know if ||V^Z|| != 0.0 at any point.
|
||||
raises ConstructionError;
|
||||
|
||||
@@ -115,11 +122,16 @@ is
|
||||
-- the point of parameter U on this offset curve.
|
||||
|
||||
|
||||
SetBasisCurve (me : mutable; C : Curve from Geom2d)
|
||||
SetBasisCurve ( me : mutable;
|
||||
C : Curve from Geom2d;
|
||||
isNotCheckC0 : Boolean = Standard_False)
|
||||
raises ConstructionError;
|
||||
--- Purpose : Changes this offset curve by assigning C as the
|
||||
-- basis curve from which it is built.
|
||||
-- If isNotCheckC0 = TRUE checking if basis curve has C0-continuity
|
||||
-- is not made.
|
||||
-- Exceptions
|
||||
-- if isNotCheckC0 = false,
|
||||
-- Standard_ConstructionError if the curve C is not at least "C1" continuous.
|
||||
|
||||
SetOffsetValue (me : mutable; D : Real);
|
||||
@@ -329,10 +341,17 @@ is
|
||||
|
||||
|
||||
Copy (me) returns like me;
|
||||
---Purpose: Creates a new object, which is a copy of this offset curve.
|
||||
---Purpose: Creates a new object, which is a copy of this offset curve.
|
||||
|
||||
GetBasisCurveContinuity(me)
|
||||
returns Shape from GeomAbs;
|
||||
---Purpose: Returns continuity of the basis curve.
|
||||
|
||||
|
||||
fields
|
||||
|
||||
basisCurve : Curve from Geom2d;
|
||||
offsetValue : Real;
|
||||
myBasisCurveContinuity : Shape from GeomAbs;
|
||||
|
||||
end;
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <gp_XY.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
typedef Handle(Geom2d_OffsetCurve) Handle(OffsetCurve);
|
||||
typedef Geom2d_OffsetCurve OffsetCurve;
|
||||
@@ -51,7 +52,7 @@ typedef gp_XY XY;
|
||||
//derivee non nulle
|
||||
static const int maxDerivOrder = 3;
|
||||
static const Standard_Real MinStep = 1e-7;
|
||||
|
||||
static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
|
||||
|
||||
//=======================================================================
|
||||
//function : Copy
|
||||
@@ -68,21 +69,16 @@ Handle(Geom2d_Geometry) Geom2d_OffsetCurve::Copy () const
|
||||
|
||||
//=======================================================================
|
||||
//function : Geom2d_OffsetCurve
|
||||
//purpose :
|
||||
//purpose : Basis curve cannot be an Offset curve or trimmed from
|
||||
// offset curve.
|
||||
//=======================================================================
|
||||
|
||||
Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Curve)& C,
|
||||
const Standard_Real Offset)
|
||||
: offsetValue (Offset)
|
||||
Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Geom2d_Curve)& theCurve,
|
||||
const Standard_Real theOffset,
|
||||
const Standard_Boolean isTheNotCheckC0)
|
||||
: offsetValue (theOffset)
|
||||
{
|
||||
if (C->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)) {
|
||||
Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C);
|
||||
SetBasisCurve (OC->BasisCurve());
|
||||
offsetValue += OC->Offset();
|
||||
}
|
||||
else {
|
||||
SetBasisCurve(C);
|
||||
}
|
||||
SetBasisCurve (theCurve, isTheNotCheckC0);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -111,36 +107,65 @@ Standard_Real Geom2d_OffsetCurve::ReversedParameter( const Standard_Real U) cons
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C)
|
||||
void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C,
|
||||
const Standard_Boolean isNotCheckC0)
|
||||
{
|
||||
Handle(Geom2d_Curve) aBasisCurve = Handle(Geom2d_Curve)::DownCast(C->Copy());
|
||||
const Standard_Real aUf = C->FirstParameter(),
|
||||
aUl = C->LastParameter();
|
||||
Handle(Geom2d_Curve) aCheckingCurve = C;
|
||||
Standard_Boolean isTrimmed = Standard_False;
|
||||
|
||||
while(aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) ||
|
||||
aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
|
||||
{
|
||||
if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
|
||||
{
|
||||
Handle(Geom2d_TrimmedCurve) aTrimC =
|
||||
Handle(Geom2d_TrimmedCurve)::DownCast(aCheckingCurve);
|
||||
aCheckingCurve = aTrimC->BasisCurve();
|
||||
isTrimmed = Standard_True;
|
||||
}
|
||||
|
||||
if (aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
|
||||
{
|
||||
Handle(Geom2d_OffsetCurve) aOC =
|
||||
Handle(Geom2d_OffsetCurve)::DownCast(aCheckingCurve);
|
||||
aCheckingCurve = aOC->BasisCurve();
|
||||
offsetValue += aOC->Offset();
|
||||
}
|
||||
}
|
||||
|
||||
myBasisCurveContinuity = aCheckingCurve->Continuity();
|
||||
|
||||
Standard_Boolean isC0 = !isNotCheckC0 &&
|
||||
(myBasisCurveContinuity == GeomAbs_C0);
|
||||
|
||||
// Basis curve must be at least C1
|
||||
if (aBasisCurve->Continuity() == GeomAbs_C0)
|
||||
if (isC0 && aCheckingCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
|
||||
{
|
||||
// For B-splines it is sometimes possible to increase continuity by removing
|
||||
// unnecessarily duplicated knots
|
||||
if (aBasisCurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)))
|
||||
Handle(Geom2d_BSplineCurve) aBC = Handle(Geom2d_BSplineCurve)::DownCast(aCheckingCurve);
|
||||
if(aBC->IsG1(aUf, aUl, MyAngularToleranceForG1))
|
||||
{
|
||||
Handle(Geom2d_BSplineCurve) aBCurve = Handle(Geom2d_BSplineCurve)::DownCast(aBasisCurve);
|
||||
Standard_Integer degree = aBCurve->Degree();
|
||||
Standard_Real Toler = 1e-7;
|
||||
Standard_Integer start = aBCurve->IsPeriodic() ? 1 : aBCurve->FirstUKnotIndex(),
|
||||
finish = aBCurve->IsPeriodic() ? aBCurve->NbKnots() : aBCurve->LastUKnotIndex();
|
||||
for (Standard_Integer i = start; i <= finish; i++)
|
||||
{
|
||||
Standard_Integer mult = aBCurve->Multiplicity(i);
|
||||
if ( mult == degree )
|
||||
aBCurve->RemoveKnot(i,degree - 1, Toler);
|
||||
}
|
||||
//Checking if basis curve has more smooth (C1, G2 and above) is not done.
|
||||
//It can be done in case of need.
|
||||
myBasisCurveContinuity = GeomAbs_G1;
|
||||
isC0 = Standard_False;
|
||||
}
|
||||
|
||||
// Raise exception if still C0
|
||||
if (aBasisCurve->Continuity() == GeomAbs_C0)
|
||||
if (isC0)
|
||||
Standard_ConstructionError::Raise("Offset on C0 curve");
|
||||
}
|
||||
//
|
||||
if(isTrimmed)
|
||||
{
|
||||
basisCurve = new Geom2d_TrimmedCurve(aCheckingCurve, aUf, aUl);
|
||||
}
|
||||
else
|
||||
{
|
||||
basisCurve = aCheckingCurve;
|
||||
}
|
||||
|
||||
basisCurve = aBasisCurve;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -168,7 +193,7 @@ Handle(Curve) Geom2d_OffsetCurve::BasisCurve () const
|
||||
GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const
|
||||
{
|
||||
GeomAbs_Shape OffsetShape=GeomAbs_C0;
|
||||
switch (basisCurve->Continuity()) {
|
||||
switch (myBasisCurveContinuity) {
|
||||
case GeomAbs_C0 : OffsetShape = GeomAbs_C0; break;
|
||||
case GeomAbs_C1 : OffsetShape = GeomAbs_C0; break;
|
||||
case GeomAbs_C2 : OffsetShape = GeomAbs_C1; break;
|
||||
@@ -177,6 +202,7 @@ GeomAbs_Shape Geom2d_OffsetCurve::Continuity () const
|
||||
case GeomAbs_G1 : OffsetShape = GeomAbs_G1; break;
|
||||
case GeomAbs_G2 : OffsetShape = GeomAbs_G2; break;
|
||||
}
|
||||
|
||||
return OffsetShape;
|
||||
}
|
||||
|
||||
@@ -926,3 +952,12 @@ Standard_Real Geom2d_OffsetCurve::ParametricTransformation(const gp_Trsf2d& T) c
|
||||
{
|
||||
return basisCurve->ParametricTransformation(T);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetBasisCurveContinuity
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
GeomAbs_Shape Geom2d_OffsetCurve::GetBasisCurveContinuity() const
|
||||
{
|
||||
return myBasisCurveContinuity;
|
||||
}
|
||||
|
Reference in New Issue
Block a user