1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +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:
Roman Lygin
2013-04-17 15:26:49 +04:00
parent 973f1c39ac
commit 06be28a4f1
10 changed files with 221 additions and 207 deletions

View File

@@ -74,63 +74,6 @@ static void CheckCurveData
Standard_ConstructionError::Raise();
}
//=======================================================================
//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
@@ -1181,7 +1124,7 @@ void Geom_BSplineCurve::UpdateKnots()
rational = !weights.IsNull();
Standard_Integer MaxKnotMult = 0;
KnotAnalysis (deg,
BSplCLib::KnotAnalysis (deg,
periodic,
knots->Array1(),
mults->Array1(),

View File

@@ -87,60 +87,6 @@ static void CheckSurfaceData
Standard_ConstructionError::Raise("Geom_BSplineSurface");
}
//=======================================================================
//function : KnotAnalysis
//purpose : Internal use only.
//=======================================================================
static void KnotAnalysis
(const Standard_Integer Degree,
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 = BSplCLib::FirstUKnotIndex (Degree, CMults);
Standard_Integer LastKM = 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 : Internal use only.
@@ -1297,7 +1243,7 @@ void Geom_BSplineSurface::UpdateUKnots()
{
Standard_Integer MaxKnotMult = 0;
KnotAnalysis (udeg,
BSplCLib::KnotAnalysis (udeg, uperiodic,
uknots->Array1(),
umults->Array1(),
uknotSet, MaxKnotMult);
@@ -1337,7 +1283,7 @@ void Geom_BSplineSurface::UpdateUKnots()
void Geom_BSplineSurface::UpdateVKnots()
{
Standard_Integer MaxKnotMult = 0;
KnotAnalysis (vdeg,
BSplCLib::KnotAnalysis (vdeg, vperiodic,
vknots->Array1(),
vmults->Array1(),
vknotSet, MaxKnotMult);

View File

@@ -89,14 +89,12 @@ Handle(Geom_Geometry) Geom_OffsetCurve::Copy () const {
Geom_OffsetCurve::Geom_OffsetCurve (const Handle(Curve)& C,
const Standard_Real Offset,
const Dir& V )
: direction(V), offsetValue(Offset) {
: direction(V), offsetValue(Offset)
{
if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve)) {
Handle(OffsetCurve) OC = Handle(OffsetCurve)::DownCast(C);
if ((OC->BasisCurve())->Continuity() == GeomAbs_C0)
Standard_ConstructionError::Raise();
SetBasisCurve (OC->BasisCurve());
basisCurve = Handle(Curve)::DownCast((OC->BasisCurve())->Copy());
Standard_Real PrevOff = OC->Offset();
gp_Vec V1(OC->Direction());
gp_Vec V2(direction);
@@ -109,9 +107,9 @@ Geom_OffsetCurve::Geom_OffsetCurve (const Handle(Curve)& C,
offsetValue = -Vdir.Magnitude();
direction.SetXYZ((-Vdir).XYZ());
}
} else {
if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
basisCurve = Handle(Curve)::DownCast(C->Copy()); // DownCast: 10-03-93
}
else {
SetBasisCurve(C);
}
}
@@ -188,10 +186,36 @@ Standard_Real Geom_OffsetCurve::Period () const
//purpose :
//=======================================================================
void Geom_OffsetCurve::SetBasisCurve (const Handle(Curve)& C) {
void Geom_OffsetCurve::SetBasisCurve (const Handle(Curve)& C)
{
Handle(Curve) aBasisCurve = Handle(Curve)::DownCast(C->Copy());
if (C->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
basisCurve = Handle(Curve)::DownCast(C->Copy()); // DownCast: 10-03-93
// 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(Geom_BSplineCurve)))
{
Handle(Geom_BSplineCurve) aBCurve = Handle(Geom_BSplineCurve)::DownCast(aBasisCurve);
Standard_Integer degree = aBCurve->Degree();
Standard_Real Toler = Precision::Confusion();
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;
}

View File

@@ -229,19 +229,16 @@ Geom_OffsetSurface::Geom_OffsetSurface ( const Handle(Surface)& S,
const Standard_Real Offset )
: offsetValue (Offset)
{
Handle(Geom_OffsetSurface) Off_S;
Off_S = Handle(Geom_OffsetSurface)::DownCast(S);
if (!Off_S.IsNull()) {
offsetValue += Off_S->Offset();
basisSurf = Handle(Surface)::DownCast(Off_S->BasisSurface()->Copy());
}
else {
basisSurf = Handle(Surface)::DownCast(S->Copy());
if (S->Continuity() == GeomAbs_C0)
Standard_ConstructionError::Raise("Offset with no C1 Surface");
offsetValue += Off_S->Offset();
SetBasisSurface (Off_S->BasisSurface());
}
equivSurf = Surface();
else {
SetBasisSurface(S);
}
//
// Tolerance en dur pour l'instant ,mais on devrait la proposer dans le constructeur
// et la mettre en champ, on pourrait utiliser par exemple pour l'extraction d'iso
@@ -258,11 +255,45 @@ Geom_OffsetSurface::Geom_OffsetSurface ( const Handle(Surface)& S,
//purpose :
//=======================================================================
void Geom_OffsetSurface::SetBasisSurface (const Handle(Surface)& S) {
void Geom_OffsetSurface::SetBasisSurface (const Handle(Surface)& S)
{
Handle(Surface) aBasisSurf = Handle(Surface)::DownCast(S->Copy());
basisSurf = Handle(Surface)::DownCast(S->Copy());
// Basis surface must be at least C1
if (aBasisSurf->Continuity() == GeomAbs_C0)
{
// For B-splines it is sometimes possible to increase continuity by removing
// unnecessarily duplicated knots
if (aBasisSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface)))
{
Handle(Geom_BSplineSurface) aBSurf = Handle(Geom_BSplineSurface)::DownCast(aBasisSurf);
Standard_Integer uDegree = aBSurf->UDegree(), vDegree = aBSurf->VDegree();
Standard_Real Toler = Precision::Confusion();
Standard_Integer start = aBSurf->IsUPeriodic() ? 1 : aBSurf->FirstUKnotIndex(),
finish = aBSurf->IsUPeriodic() ? aBSurf->NbUKnots() : aBSurf->LastUKnotIndex();
for (Standard_Integer i = start; i <= finish; i++)
{
Standard_Integer mult = aBSurf->UMultiplicity(i);
if ( mult == uDegree )
aBSurf->RemoveUKnot(i,uDegree - 1, Toler);
}
start = aBSurf->IsVPeriodic() ? 1 : aBSurf->FirstVKnotIndex();
finish = aBSurf->IsVPeriodic() ? aBSurf->NbVKnots() : aBSurf->LastVKnotIndex();
for (Standard_Integer i = start; i <= finish; i++)
{
Standard_Integer mult = aBSurf->VMultiplicity(i);
if ( mult == vDegree )
aBSurf->RemoveVKnot(i,vDegree - 1, Toler);
}
}
// Raise exception if still C0
if (aBasisSurf->Continuity() == GeomAbs_C0)
Standard_ConstructionError::Raise("Offset with no C1 Surface");
}
basisSurf = aBasisSurf;
equivSurf = Surface();
if (S->Continuity() == GeomAbs_C0) Standard_ConstructionError::Raise();
}