mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
CR23683: Geom_BSplineSurface incorrectly determines continuity for periodic cases
Add a checking into files Geom_OffsetSurface.cxx, Geom_OffsetCurve.cxx, Geom2d_OffsetCurve.cxx , which try to make continuity of bspline surfaces and curves more than C0 to build offset. Delete duplicate code and checkings Prevent change of offset curve / surface when exception is raised due to attempt to set new C0 basis curve / surface Added new QA command OCC23683. Added test case bugs/moddata_3/bug23683
This commit is contained in:
@@ -71,63 +71,6 @@ static void CheckCurveData
|
||||
Standard_ConstructionError::Raise("BSpline curve : # Poles and degree mismatch");
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : KnotAnalysis
|
||||
//purpose : Internal use only
|
||||
//=======================================================================
|
||||
|
||||
static void KnotAnalysis
|
||||
(const Standard_Integer Degree,
|
||||
const Standard_Boolean Periodic,
|
||||
const TColStd_Array1OfReal& CKnots,
|
||||
const TColStd_Array1OfInteger& CMults,
|
||||
GeomAbs_BSplKnotDistribution& KnotForm,
|
||||
Standard_Integer& MaxKnotMult)
|
||||
{
|
||||
KnotForm = GeomAbs_NonUniform;
|
||||
|
||||
BSplCLib_KnotDistribution KSet =
|
||||
BSplCLib::KnotForm (CKnots, 1, CKnots.Length());
|
||||
|
||||
|
||||
if (KSet == BSplCLib_Uniform) {
|
||||
BSplCLib_MultDistribution MSet =
|
||||
BSplCLib::MultForm (CMults, 1, CMults.Length());
|
||||
switch (MSet) {
|
||||
case BSplCLib_NonConstant :
|
||||
break;
|
||||
case BSplCLib_Constant :
|
||||
if (CKnots.Length() == 2) {
|
||||
KnotForm = GeomAbs_PiecewiseBezier;
|
||||
}
|
||||
else {
|
||||
if (CMults (1) == 1) KnotForm = GeomAbs_Uniform;
|
||||
}
|
||||
break;
|
||||
case BSplCLib_QuasiConstant :
|
||||
if (CMults (1) == Degree + 1) {
|
||||
Standard_Real M = CMults (2);
|
||||
if (M == Degree ) KnotForm = GeomAbs_PiecewiseBezier;
|
||||
else if (M == 1) KnotForm = GeomAbs_QuasiUniform;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Integer FirstKM =
|
||||
Periodic ? CKnots.Lower() : BSplCLib::FirstUKnotIndex (Degree,CMults);
|
||||
Standard_Integer LastKM =
|
||||
Periodic ? CKnots.Upper() : BSplCLib::LastUKnotIndex (Degree,CMults);
|
||||
MaxKnotMult = 0;
|
||||
if (LastKM - FirstKM != 1) {
|
||||
Standard_Integer Multi;
|
||||
for (Standard_Integer i = FirstKM + 1; i < LastKM; i++) {
|
||||
Multi = CMults (i);
|
||||
MaxKnotMult = Max (MaxKnotMult, Multi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Rational
|
||||
//purpose : check rationality of an array of weights
|
||||
@@ -1298,7 +1241,7 @@ void Geom2d_BSplineCurve::UpdateKnots()
|
||||
rational = !weights.IsNull();
|
||||
|
||||
Standard_Integer MaxKnotMult = 0;
|
||||
KnotAnalysis (deg,
|
||||
BSplCLib::KnotAnalysis (deg,
|
||||
periodic,
|
||||
knots->Array1(),
|
||||
mults->Array1(),
|
||||
|
@@ -84,16 +84,11 @@ Geom2d_OffsetCurve::Geom2d_OffsetCurve (const Handle(Curve)& C,
|
||||
{
|
||||
if (C->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)) {
|
||||
Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C);
|
||||
if ((OC->BasisCurve())->Continuity() == GeomAbs_C0)
|
||||
Standard_ConstructionError::Raise();
|
||||
|
||||
basisCurve = Handle(Curve)::DownCast((OC->BasisCurve())->Copy());
|
||||
SetBasisCurve (OC->BasisCurve());
|
||||
offsetValue += OC->Offset();
|
||||
} else {
|
||||
if (C->Continuity() == GeomAbs_C0)
|
||||
Standard_ConstructionError::Raise();
|
||||
|
||||
basisCurve = Handle(Curve)::DownCast(C->Copy());
|
||||
}
|
||||
else {
|
||||
SetBasisCurve(C);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,8 +120,34 @@ Standard_Real Geom2d_OffsetCurve::ReversedParameter( const Standard_Real U) cons
|
||||
|
||||
void Geom2d_OffsetCurve::SetBasisCurve (const Handle(Curve)& C)
|
||||
{
|
||||
if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
|
||||
basisCurve = Handle(Geom2d_Curve)::DownCast(C->Copy());
|
||||
Handle(Geom2d_Curve) aBasisCurve = Handle(Geom2d_Curve)::DownCast(C->Copy());
|
||||
|
||||
// Basis curve must be at least C1
|
||||
if (aBasisCurve->Continuity() == GeomAbs_C0)
|
||||
{
|
||||
// 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) 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Raise exception if still C0
|
||||
if (aBasisCurve->Continuity() == GeomAbs_C0)
|
||||
Standard_ConstructionError::Raise("Offset on C0 curve");
|
||||
}
|
||||
|
||||
basisCurve = aBasisCurve;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
Reference in New Issue
Block a user