mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
- Adds copy constructors for 9 geometry classes (Bezier/BSpline curves and surfaces, offset curves and surfaces in both 2D and 3D) - Updates Copy() methods to use the new copy constructors instead of recreating objects through standard constructors - Includes comprehensive test coverage for all new copy constructors
1407 lines
48 KiB
C++
1407 lines
48 KiB
C++
// Created on: 1993-03-09
|
|
// Created by: JCV
|
|
// Copyright (c) 1993-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
// 14-Mar-96 : xab portage hp
|
|
// pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
|
|
// pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
|
|
// et ajout des InvalideCache() dans les SetWeight*(PRO6833)
|
|
// RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537).
|
|
// jct : 19-01-99 ; permutation de urational et vrational dans Rational.
|
|
#define No_Standard_OutOfRange
|
|
|
|
#include <BSplCLib.hxx>
|
|
#include <BSplSLib.hxx>
|
|
#include <Geom_BSplineSurface.hxx>
|
|
#include <Geom_Geometry.hxx>
|
|
#include <Geom_UndefinedDerivative.hxx>
|
|
#include <gp.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Trsf.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_ConstructionError.hxx>
|
|
#include <Standard_DomainError.hxx>
|
|
#include <Standard_NotImplemented.hxx>
|
|
#include <Standard_OutOfRange.hxx>
|
|
#include <Standard_Type.hxx>
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineSurface, Geom_BoundedSurface)
|
|
|
|
//=================================================================================================
|
|
|
|
static void CheckSurfaceData(const TColgp_Array2OfPnt& SPoles,
|
|
const TColStd_Array1OfReal& SUKnots,
|
|
const TColStd_Array1OfReal& SVKnots,
|
|
const TColStd_Array1OfInteger& SUMults,
|
|
const TColStd_Array1OfInteger& SVMults,
|
|
const Standard_Integer UDegree,
|
|
const Standard_Integer VDegree,
|
|
const Standard_Boolean UPeriodic,
|
|
const Standard_Boolean VPeriodic)
|
|
{
|
|
if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree() || VDegree < 1
|
|
|| VDegree > Geom_BSplineSurface::MaxDegree())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: invalid degree");
|
|
}
|
|
if (SPoles.ColLength() < 2 || SPoles.RowLength() < 2)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: at least 2 poles required");
|
|
}
|
|
|
|
if (SUKnots.Length() != SUMults.Length() || SVKnots.Length() != SVMults.Length())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: Knot and Mult array size mismatch");
|
|
}
|
|
|
|
Standard_Integer i;
|
|
for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++)
|
|
{
|
|
if (SUKnots(i + 1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i))))
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: UKnots interval values too close");
|
|
}
|
|
}
|
|
|
|
for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++)
|
|
{
|
|
if (SVKnots(i + 1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i))))
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: VKnots interval values too close");
|
|
}
|
|
}
|
|
|
|
if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree, UPeriodic, SUMults))
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: # U Poles and degree mismatch");
|
|
|
|
if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree, VPeriodic, SVMults))
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: # V Poles and degree mismatch");
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
static void Rational(const TColStd_Array2OfReal& Weights,
|
|
Standard_Boolean& Urational,
|
|
Standard_Boolean& Vrational)
|
|
{
|
|
Standard_Integer I, J;
|
|
J = Weights.LowerCol();
|
|
Vrational = Standard_False;
|
|
while (!Vrational && J <= Weights.UpperCol())
|
|
{
|
|
I = Weights.LowerRow();
|
|
while (!Vrational && I <= Weights.UpperRow() - 1)
|
|
{
|
|
Vrational = (Abs(Weights(I, J) - Weights(I + 1, J)) > Epsilon(Abs(Weights(I, J))));
|
|
I++;
|
|
}
|
|
J++;
|
|
}
|
|
|
|
I = Weights.LowerRow();
|
|
Urational = Standard_False;
|
|
while (!Urational && I <= Weights.UpperRow())
|
|
{
|
|
J = Weights.LowerCol();
|
|
while (!Urational && J <= Weights.UpperCol() - 1)
|
|
{
|
|
Urational = (Abs(Weights(I, J) - Weights(I, J + 1)) > Epsilon(Abs(Weights(I, J))));
|
|
J++;
|
|
}
|
|
I++;
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Handle(Geom_Geometry) Geom_BSplineSurface::Copy() const
|
|
{
|
|
return new Geom_BSplineSurface(*this);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Geom_BSplineSurface::Geom_BSplineSurface(const Geom_BSplineSurface& theOther)
|
|
: urational(theOther.urational),
|
|
vrational(theOther.vrational),
|
|
uperiodic(theOther.uperiodic),
|
|
vperiodic(theOther.vperiodic),
|
|
uknotSet(theOther.uknotSet),
|
|
vknotSet(theOther.vknotSet),
|
|
Usmooth(theOther.Usmooth),
|
|
Vsmooth(theOther.Vsmooth),
|
|
udeg(theOther.udeg),
|
|
vdeg(theOther.vdeg),
|
|
umaxderivinv(theOther.umaxderivinv),
|
|
vmaxderivinv(theOther.vmaxderivinv),
|
|
maxderivinvok(Standard_False)
|
|
{
|
|
// Deep copy all data arrays without validation
|
|
poles = new TColgp_HArray2OfPnt(theOther.poles->LowerRow(),
|
|
theOther.poles->UpperRow(),
|
|
theOther.poles->LowerCol(),
|
|
theOther.poles->UpperCol());
|
|
poles->ChangeArray2() = theOther.poles->Array2();
|
|
|
|
uknots = new TColStd_HArray1OfReal(theOther.uknots->Lower(), theOther.uknots->Upper());
|
|
uknots->ChangeArray1() = theOther.uknots->Array1();
|
|
|
|
vknots = new TColStd_HArray1OfReal(theOther.vknots->Lower(), theOther.vknots->Upper());
|
|
vknots->ChangeArray1() = theOther.vknots->Array1();
|
|
|
|
umults = new TColStd_HArray1OfInteger(theOther.umults->Lower(), theOther.umults->Upper());
|
|
umults->ChangeArray1() = theOther.umults->Array1();
|
|
|
|
vmults = new TColStd_HArray1OfInteger(theOther.vmults->Lower(), theOther.vmults->Upper());
|
|
vmults->ChangeArray1() = theOther.vmults->Array1();
|
|
|
|
if (!theOther.ufknots.IsNull())
|
|
{
|
|
ufknots = new TColStd_HArray1OfReal(theOther.ufknots->Lower(), theOther.ufknots->Upper());
|
|
ufknots->ChangeArray1() = theOther.ufknots->Array1();
|
|
}
|
|
|
|
if (!theOther.vfknots.IsNull())
|
|
{
|
|
vfknots = new TColStd_HArray1OfReal(theOther.vfknots->Lower(), theOther.vfknots->Upper());
|
|
vfknots->ChangeArray1() = theOther.vfknots->Array1();
|
|
}
|
|
|
|
if (!theOther.weights.IsNull())
|
|
{
|
|
weights = new TColStd_HArray2OfReal(theOther.weights->LowerRow(),
|
|
theOther.weights->UpperRow(),
|
|
theOther.weights->LowerCol(),
|
|
theOther.weights->UpperCol());
|
|
weights->ChangeArray2() = theOther.weights->Array2();
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Geom_BSplineSurface::Geom_BSplineSurface(const TColgp_Array2OfPnt& Poles,
|
|
const TColStd_Array1OfReal& UKnots,
|
|
const TColStd_Array1OfReal& VKnots,
|
|
const TColStd_Array1OfInteger& UMults,
|
|
const TColStd_Array1OfInteger& VMults,
|
|
const Standard_Integer UDegree,
|
|
const Standard_Integer VDegree,
|
|
const Standard_Boolean UPeriodic,
|
|
const Standard_Boolean VPeriodic)
|
|
: urational(Standard_False),
|
|
vrational(Standard_False),
|
|
uperiodic(UPeriodic),
|
|
vperiodic(VPeriodic),
|
|
udeg(UDegree),
|
|
vdeg(VDegree),
|
|
maxderivinvok(0)
|
|
|
|
{
|
|
|
|
// check
|
|
|
|
CheckSurfaceData(Poles, UKnots, VKnots, UMults, VMults, UDegree, VDegree, UPeriodic, VPeriodic);
|
|
|
|
// copy arrays
|
|
|
|
poles = new TColgp_HArray2OfPnt(1, Poles.ColLength(), 1, Poles.RowLength());
|
|
poles->ChangeArray2() = Poles;
|
|
|
|
weights = new TColStd_HArray2OfReal(1, Poles.ColLength(), 1, Poles.RowLength(), 1.0);
|
|
|
|
uknots = new TColStd_HArray1OfReal(1, UKnots.Length());
|
|
uknots->ChangeArray1() = UKnots;
|
|
|
|
umults = new TColStd_HArray1OfInteger(1, UMults.Length());
|
|
umults->ChangeArray1() = UMults;
|
|
|
|
vknots = new TColStd_HArray1OfReal(1, VKnots.Length());
|
|
vknots->ChangeArray1() = VKnots;
|
|
|
|
vmults = new TColStd_HArray1OfInteger(1, VMults.Length());
|
|
vmults->ChangeArray1() = VMults;
|
|
|
|
UpdateUKnots();
|
|
UpdateVKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Geom_BSplineSurface::Geom_BSplineSurface(const TColgp_Array2OfPnt& Poles,
|
|
const TColStd_Array2OfReal& Weights,
|
|
const TColStd_Array1OfReal& UKnots,
|
|
const TColStd_Array1OfReal& VKnots,
|
|
const TColStd_Array1OfInteger& UMults,
|
|
const TColStd_Array1OfInteger& VMults,
|
|
const Standard_Integer UDegree,
|
|
const Standard_Integer VDegree,
|
|
const Standard_Boolean UPeriodic,
|
|
const Standard_Boolean VPeriodic)
|
|
: urational(Standard_False),
|
|
vrational(Standard_False),
|
|
uperiodic(UPeriodic),
|
|
vperiodic(VPeriodic),
|
|
udeg(UDegree),
|
|
vdeg(VDegree),
|
|
maxderivinvok(0)
|
|
{
|
|
// check weights
|
|
|
|
if (Weights.ColLength() != Poles.ColLength())
|
|
throw Standard_ConstructionError(
|
|
"Geom_BSplineSurface: U Weights and Poles array size mismatch");
|
|
|
|
if (Weights.RowLength() != Poles.RowLength())
|
|
throw Standard_ConstructionError(
|
|
"Geom_BSplineSurface: V Weights and Poles array size mismatch");
|
|
|
|
Standard_Integer i, j;
|
|
for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++)
|
|
{
|
|
for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++)
|
|
{
|
|
if (Weights(i, j) <= gp::Resolution())
|
|
throw Standard_ConstructionError("Geom_BSplineSurface: Weights values too small");
|
|
}
|
|
}
|
|
|
|
// check really rational
|
|
|
|
Rational(Weights, urational, vrational);
|
|
|
|
// check
|
|
|
|
CheckSurfaceData(Poles, UKnots, VKnots, UMults, VMults, UDegree, VDegree, UPeriodic, VPeriodic);
|
|
|
|
// copy arrays
|
|
|
|
poles = new TColgp_HArray2OfPnt(1, Poles.ColLength(), 1, Poles.RowLength());
|
|
poles->ChangeArray2() = Poles;
|
|
|
|
weights = new TColStd_HArray2OfReal(1, Poles.ColLength(), 1, Poles.RowLength());
|
|
weights->ChangeArray2() = Weights;
|
|
|
|
uknots = new TColStd_HArray1OfReal(1, UKnots.Length());
|
|
uknots->ChangeArray1() = UKnots;
|
|
|
|
umults = new TColStd_HArray1OfInteger(1, UMults.Length());
|
|
umults->ChangeArray1() = UMults;
|
|
|
|
vknots = new TColStd_HArray1OfReal(1, VKnots.Length());
|
|
vknots->ChangeArray1() = VKnots;
|
|
|
|
vmults = new TColStd_HArray1OfInteger(1, VMults.Length());
|
|
vmults->ChangeArray1() = VMults;
|
|
|
|
UpdateUKnots();
|
|
UpdateVKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::ExchangeUV()
|
|
{
|
|
Standard_Integer LC = poles->LowerCol();
|
|
Standard_Integer UC = poles->UpperCol();
|
|
Standard_Integer LR = poles->LowerRow();
|
|
Standard_Integer UR = poles->UpperRow();
|
|
|
|
Handle(TColgp_HArray2OfPnt) npoles = new TColgp_HArray2OfPnt(LC, UC, LR, UR);
|
|
Handle(TColStd_HArray2OfReal) nweights;
|
|
if (!weights.IsNull())
|
|
{
|
|
nweights = new TColStd_HArray2OfReal(LC, UC, LR, UR);
|
|
}
|
|
|
|
const TColgp_Array2OfPnt& spoles = poles->Array2();
|
|
const TColStd_Array2OfReal* sweights = !weights.IsNull() ? &weights->Array2() : NULL;
|
|
|
|
TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2();
|
|
TColStd_Array2OfReal* snweights = !nweights.IsNull() ? &nweights->ChangeArray2() : NULL;
|
|
for (Standard_Integer i = LC; i <= UC; i++)
|
|
{
|
|
for (Standard_Integer j = LR; j <= UR; j++)
|
|
{
|
|
snpoles(i, j) = spoles(j, i);
|
|
if (snweights != NULL)
|
|
{
|
|
snweights->ChangeValue(i, j) = sweights->Value(j, i);
|
|
}
|
|
}
|
|
}
|
|
poles = npoles;
|
|
weights = nweights;
|
|
|
|
std::swap(urational, vrational);
|
|
std::swap(uperiodic, vperiodic);
|
|
std::swap(udeg, vdeg);
|
|
std::swap(uknots, vknots);
|
|
std::swap(umults, vmults);
|
|
|
|
UpdateUKnots();
|
|
UpdateVKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncreaseDegree(const Standard_Integer UDegree,
|
|
const Standard_Integer VDegree)
|
|
{
|
|
if (UDegree != udeg)
|
|
{
|
|
if (UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad U degree value");
|
|
|
|
Standard_Integer FromK1 = FirstUKnotIndex();
|
|
Standard_Integer ToK2 = LastUKnotIndex();
|
|
|
|
Standard_Integer Step = UDegree - udeg;
|
|
|
|
Handle(TColgp_HArray2OfPnt) npoles =
|
|
new TColgp_HArray2OfPnt(1,
|
|
poles->ColLength() + Step * (ToK2 - FromK1),
|
|
1,
|
|
poles->RowLength());
|
|
|
|
Standard_Integer nbknots =
|
|
BSplCLib::IncreaseDegreeCountKnots(udeg, UDegree, uperiodic, umults->Array1());
|
|
|
|
Handle(TColStd_HArray1OfReal) nknots = new TColStd_HArray1OfReal(1, nbknots);
|
|
|
|
Handle(TColStd_HArray1OfInteger) nmults = new TColStd_HArray1OfInteger(1, nbknots);
|
|
|
|
Handle(TColStd_HArray2OfReal) nweights =
|
|
new TColStd_HArray2OfReal(1, npoles->ColLength(), 1, npoles->RowLength(), 1.);
|
|
|
|
if (urational || vrational)
|
|
{
|
|
|
|
BSplSLib::IncreaseDegree(Standard_True,
|
|
udeg,
|
|
UDegree,
|
|
uperiodic,
|
|
poles->Array2(),
|
|
&weights->Array2(),
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
npoles->ChangeArray2(),
|
|
&nweights->ChangeArray2(),
|
|
nknots->ChangeArray1(),
|
|
nmults->ChangeArray1());
|
|
}
|
|
else
|
|
{
|
|
|
|
BSplSLib::IncreaseDegree(Standard_True,
|
|
udeg,
|
|
UDegree,
|
|
uperiodic,
|
|
poles->Array2(),
|
|
BSplSLib::NoWeights(),
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
npoles->ChangeArray2(),
|
|
BSplSLib::NoWeights(),
|
|
nknots->ChangeArray1(),
|
|
nmults->ChangeArray1());
|
|
}
|
|
udeg = UDegree;
|
|
poles = npoles;
|
|
weights = nweights;
|
|
uknots = nknots;
|
|
umults = nmults;
|
|
UpdateUKnots();
|
|
}
|
|
|
|
if (VDegree != vdeg)
|
|
{
|
|
if (VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad V degree value");
|
|
|
|
Standard_Integer FromK1 = FirstVKnotIndex();
|
|
Standard_Integer ToK2 = LastVKnotIndex();
|
|
|
|
Standard_Integer Step = VDegree - vdeg;
|
|
|
|
Handle(TColgp_HArray2OfPnt) npoles =
|
|
new TColgp_HArray2OfPnt(1,
|
|
poles->ColLength(),
|
|
1,
|
|
poles->RowLength() + Step * (ToK2 - FromK1));
|
|
|
|
Standard_Integer nbknots =
|
|
BSplCLib::IncreaseDegreeCountKnots(vdeg, VDegree, vperiodic, vmults->Array1());
|
|
|
|
Handle(TColStd_HArray1OfReal) nknots = new TColStd_HArray1OfReal(1, nbknots);
|
|
|
|
Handle(TColStd_HArray1OfInteger) nmults = new TColStd_HArray1OfInteger(1, nbknots);
|
|
|
|
Handle(TColStd_HArray2OfReal) nweights =
|
|
new TColStd_HArray2OfReal(1, npoles->ColLength(), 1, npoles->RowLength(), 1.);
|
|
|
|
if (urational || vrational)
|
|
{
|
|
|
|
BSplSLib::IncreaseDegree(Standard_False,
|
|
vdeg,
|
|
VDegree,
|
|
vperiodic,
|
|
poles->Array2(),
|
|
&weights->Array2(),
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
npoles->ChangeArray2(),
|
|
&nweights->ChangeArray2(),
|
|
nknots->ChangeArray1(),
|
|
nmults->ChangeArray1());
|
|
}
|
|
else
|
|
{
|
|
|
|
BSplSLib::IncreaseDegree(Standard_False,
|
|
vdeg,
|
|
VDegree,
|
|
vperiodic,
|
|
poles->Array2(),
|
|
BSplSLib::NoWeights(),
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
npoles->ChangeArray2(),
|
|
BSplSLib::NoWeights(),
|
|
nknots->ChangeArray1(),
|
|
nmults->ChangeArray1());
|
|
}
|
|
vdeg = VDegree;
|
|
poles = npoles;
|
|
weights = nweights;
|
|
vknots = nknots;
|
|
vmults = nmults;
|
|
UpdateVKnots();
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncreaseUMultiplicity(const Standard_Integer UIndex,
|
|
const Standard_Integer M)
|
|
{
|
|
TColStd_Array1OfReal k(1, 1);
|
|
k(1) = uknots->Value(UIndex);
|
|
TColStd_Array1OfInteger m(1, 1);
|
|
m(1) = M - umults->Value(UIndex);
|
|
InsertUKnots(k, m, Epsilon(1.), Standard_True);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncreaseUMultiplicity(const Standard_Integer FromI1,
|
|
const Standard_Integer ToI2,
|
|
const Standard_Integer M)
|
|
{
|
|
Handle(TColStd_HArray1OfReal) tk = uknots;
|
|
TColStd_Array1OfReal k((uknots->Array1())(FromI1), FromI1, ToI2);
|
|
TColStd_Array1OfInteger m(FromI1, ToI2);
|
|
for (Standard_Integer i = FromI1; i <= ToI2; i++)
|
|
m(i) = M - umults->Value(i);
|
|
InsertUKnots(k, m, Epsilon(1.), Standard_True);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncreaseVMultiplicity(const Standard_Integer VIndex,
|
|
const Standard_Integer M)
|
|
{
|
|
TColStd_Array1OfReal k(1, 1);
|
|
k(1) = vknots->Value(VIndex);
|
|
TColStd_Array1OfInteger m(1, 1);
|
|
m(1) = M - vmults->Value(VIndex);
|
|
InsertVKnots(k, m, Epsilon(1.), Standard_True);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncreaseVMultiplicity(const Standard_Integer FromI1,
|
|
const Standard_Integer ToI2,
|
|
const Standard_Integer M)
|
|
{
|
|
Handle(TColStd_HArray1OfReal) tk = vknots;
|
|
TColStd_Array1OfReal k((vknots->Array1())(FromI1), FromI1, ToI2);
|
|
TColStd_Array1OfInteger m(FromI1, ToI2);
|
|
for (Standard_Integer i = FromI1; i <= ToI2; i++)
|
|
m(i) = M - vmults->Value(i);
|
|
InsertVKnots(k, m, Epsilon(1.), Standard_True);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::segment(const Standard_Real U1,
|
|
const Standard_Real U2,
|
|
const Standard_Real V1,
|
|
const Standard_Real V2,
|
|
const Standard_Real EpsU,
|
|
const Standard_Real EpsV,
|
|
const Standard_Boolean SegmentInU,
|
|
const Standard_Boolean SegmentInV)
|
|
{
|
|
Standard_Real deltaU = U2 - U1;
|
|
if (uperiodic)
|
|
{
|
|
Standard_Real aUPeriod = uknots->Last() - uknots->First();
|
|
if (deltaU - aUPeriod > Precision::PConfusion())
|
|
throw Standard_DomainError("Geom_BSplineSurface::Segment");
|
|
if (deltaU > aUPeriod)
|
|
deltaU = aUPeriod;
|
|
}
|
|
|
|
Standard_Real deltaV = V2 - V1;
|
|
if (vperiodic)
|
|
{
|
|
Standard_Real aVPeriod = vknots->Last() - vknots->First();
|
|
if (deltaV - aVPeriod > Precision::PConfusion())
|
|
throw Standard_DomainError("Geom_BSplineSurface::Segment");
|
|
if (deltaV > aVPeriod)
|
|
deltaV = aVPeriod;
|
|
}
|
|
|
|
Standard_Real NewU1, NewU2, NewV1, NewV2;
|
|
Standard_Real U, V;
|
|
Standard_Integer indexU, indexV;
|
|
|
|
indexU = 0;
|
|
BSplCLib::LocateParameter(udeg,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
U1,
|
|
uperiodic,
|
|
uknots->Lower(),
|
|
uknots->Upper(),
|
|
indexU,
|
|
NewU1);
|
|
indexU = 0;
|
|
BSplCLib::LocateParameter(udeg,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
U2,
|
|
uperiodic,
|
|
uknots->Lower(),
|
|
uknots->Upper(),
|
|
indexU,
|
|
NewU2);
|
|
if (SegmentInU)
|
|
{
|
|
// inserting the UKnots
|
|
TColStd_Array1OfReal UKnots(1, 2);
|
|
TColStd_Array1OfInteger UMults(1, 2);
|
|
UKnots(1) = Min(NewU1, NewU2);
|
|
UKnots(2) = Max(NewU1, NewU2);
|
|
UMults(1) = UMults(2) = udeg;
|
|
|
|
InsertUKnots(UKnots, UMults, EpsU);
|
|
}
|
|
|
|
indexV = 0;
|
|
BSplCLib::LocateParameter(vdeg,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
V1,
|
|
vperiodic,
|
|
vknots->Lower(),
|
|
vknots->Upper(),
|
|
indexV,
|
|
NewV1);
|
|
indexV = 0;
|
|
BSplCLib::LocateParameter(vdeg,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
V2,
|
|
vperiodic,
|
|
vknots->Lower(),
|
|
vknots->Upper(),
|
|
indexV,
|
|
NewV2);
|
|
if (SegmentInV)
|
|
{
|
|
// Inserting the VKnots
|
|
TColStd_Array1OfReal VKnots(1, 2);
|
|
TColStd_Array1OfInteger VMults(1, 2);
|
|
|
|
VKnots(1) = Min(NewV1, NewV2);
|
|
VKnots(2) = Max(NewV1, NewV2);
|
|
VMults(1) = VMults(2) = vdeg;
|
|
InsertVKnots(VKnots, VMults, EpsV);
|
|
}
|
|
|
|
if (uperiodic && SegmentInU)
|
|
{ // set the origine at NewU1
|
|
Standard_Integer index = 0;
|
|
BSplCLib::LocateParameter(udeg,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
U1,
|
|
uperiodic,
|
|
uknots->Lower(),
|
|
uknots->Upper(),
|
|
index,
|
|
U);
|
|
if (Abs(uknots->Value(index + 1) - U) <= EpsU)
|
|
index++;
|
|
SetUOrigin(index);
|
|
SetUNotPeriodic();
|
|
}
|
|
|
|
// compute index1 and index2 to set the new knots and mults
|
|
Standard_Integer index1U = 0, index2U = 0;
|
|
Standard_Integer FromU1 = uknots->Lower();
|
|
Standard_Integer ToU2 = uknots->Upper();
|
|
BSplCLib::LocateParameter(udeg,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
NewU1,
|
|
uperiodic,
|
|
FromU1,
|
|
ToU2,
|
|
index1U,
|
|
U);
|
|
if (Abs(uknots->Value(index1U + 1) - U) <= EpsU)
|
|
index1U++;
|
|
BSplCLib::LocateParameter(udeg,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
NewU1 + deltaU,
|
|
uperiodic,
|
|
FromU1,
|
|
ToU2,
|
|
index2U,
|
|
U);
|
|
if (Abs(uknots->Value(index2U + 1) - U) <= EpsU || index2U == index1U)
|
|
index2U++;
|
|
|
|
Standard_Integer nbuknots = index2U - index1U + 1;
|
|
|
|
Handle(TColStd_HArray1OfReal) nuknots = new TColStd_HArray1OfReal(1, nbuknots);
|
|
Handle(TColStd_HArray1OfInteger) numults = new TColStd_HArray1OfInteger(1, nbuknots);
|
|
|
|
Standard_Integer i, k = 1;
|
|
for (i = index1U; i <= index2U; i++)
|
|
{
|
|
nuknots->SetValue(k, uknots->Value(i));
|
|
numults->SetValue(k, umults->Value(i));
|
|
k++;
|
|
}
|
|
if (SegmentInU)
|
|
{
|
|
numults->SetValue(1, udeg + 1);
|
|
numults->SetValue(nbuknots, udeg + 1);
|
|
}
|
|
|
|
if (vperiodic && SegmentInV)
|
|
{ // set the origine at NewV1
|
|
Standard_Integer index = 0;
|
|
BSplCLib::LocateParameter(vdeg,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
V1,
|
|
vperiodic,
|
|
vknots->Lower(),
|
|
vknots->Upper(),
|
|
index,
|
|
V);
|
|
if (Abs(vknots->Value(index + 1) - V) <= EpsV)
|
|
index++;
|
|
SetVOrigin(index);
|
|
SetVNotPeriodic();
|
|
}
|
|
|
|
// compute index1 and index2 to set the new knots and mults
|
|
Standard_Integer index1V = 0, index2V = 0;
|
|
Standard_Integer FromV1 = vknots->Lower();
|
|
Standard_Integer ToV2 = vknots->Upper();
|
|
BSplCLib::LocateParameter(vdeg,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
NewV1,
|
|
vperiodic,
|
|
FromV1,
|
|
ToV2,
|
|
index1V,
|
|
V);
|
|
if (Abs(vknots->Value(index1V + 1) - V) <= EpsV)
|
|
index1V++;
|
|
BSplCLib::LocateParameter(vdeg,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
NewV1 + deltaV,
|
|
vperiodic,
|
|
FromV1,
|
|
ToV2,
|
|
index2V,
|
|
V);
|
|
if (Abs(vknots->Value(index2V + 1) - V) <= EpsV || index2V == index1V)
|
|
index2V++;
|
|
|
|
Standard_Integer nbvknots = index2V - index1V + 1;
|
|
|
|
Handle(TColStd_HArray1OfReal) nvknots = new TColStd_HArray1OfReal(1, nbvknots);
|
|
Handle(TColStd_HArray1OfInteger) nvmults = new TColStd_HArray1OfInteger(1, nbvknots);
|
|
|
|
k = 1;
|
|
for (i = index1V; i <= index2V; i++)
|
|
{
|
|
nvknots->SetValue(k, vknots->Value(i));
|
|
nvmults->SetValue(k, vmults->Value(i));
|
|
k++;
|
|
}
|
|
if (SegmentInV)
|
|
{
|
|
nvmults->SetValue(1, vdeg + 1);
|
|
nvmults->SetValue(nbvknots, vdeg + 1);
|
|
}
|
|
|
|
// compute index1 and index2 to set the new poles and weights
|
|
Standard_Integer pindex1U = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1());
|
|
Standard_Integer pindex2U = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1());
|
|
|
|
pindex1U++;
|
|
pindex2U = Min(pindex2U + 1, poles->ColLength());
|
|
|
|
Standard_Integer nbupoles = pindex2U - pindex1U + 1;
|
|
|
|
// compute index1 and index2 to set the new poles and weights
|
|
Standard_Integer pindex1V = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1());
|
|
Standard_Integer pindex2V = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1());
|
|
|
|
pindex1V++;
|
|
pindex2V = Min(pindex2V + 1, poles->RowLength());
|
|
|
|
Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
|
|
|
|
Handle(TColStd_HArray2OfReal) nweights;
|
|
|
|
Handle(TColgp_HArray2OfPnt) npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles);
|
|
k = 1;
|
|
Standard_Integer j, l;
|
|
if (urational || vrational)
|
|
{
|
|
nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles);
|
|
for (i = pindex1U; i <= pindex2U; i++)
|
|
{
|
|
l = 1;
|
|
for (j = pindex1V; j <= pindex2V; j++)
|
|
{
|
|
npoles->SetValue(k, l, poles->Value(i, j));
|
|
nweights->SetValue(k, l, weights->Value(i, j));
|
|
l++;
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = pindex1U; i <= pindex2U; i++)
|
|
{
|
|
l = 1;
|
|
for (j = pindex1V; j <= pindex2V; j++)
|
|
{
|
|
npoles->SetValue(k, l, poles->Value(i, j));
|
|
l++;
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
|
|
uknots = nuknots;
|
|
umults = numults;
|
|
vknots = nvknots;
|
|
vmults = nvmults;
|
|
poles = npoles;
|
|
if (urational || vrational)
|
|
weights = nweights;
|
|
else
|
|
weights = new TColStd_HArray2OfReal(1, poles->ColLength(), 1, poles->RowLength(), 1.0);
|
|
|
|
maxderivinvok = 0;
|
|
UpdateUKnots();
|
|
UpdateVKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::Segment(const Standard_Real U1,
|
|
const Standard_Real U2,
|
|
const Standard_Real V1,
|
|
const Standard_Real V2,
|
|
const Standard_Real theUTolerance,
|
|
const Standard_Real theVTolerance)
|
|
{
|
|
if ((U2 < U1) || (V2 < V1))
|
|
throw Standard_DomainError("Geom_BSplineSurface::Segment");
|
|
|
|
Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
|
|
Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
|
|
|
|
Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
|
|
Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
|
|
|
|
segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1,
|
|
const Standard_Real U2,
|
|
const Standard_Real V1,
|
|
const Standard_Real V2,
|
|
const Standard_Real theUTolerance,
|
|
const Standard_Real theVTolerance)
|
|
{
|
|
|
|
if ((U2 < U1) || (V2 < V1))
|
|
throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
|
|
|
|
Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
|
|
Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
|
|
|
|
Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
|
|
Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
|
|
|
|
Standard_Boolean segment_in_U = Standard_True;
|
|
Standard_Boolean segment_in_V = Standard_True;
|
|
segment_in_U = (Abs(U1 - uknots->Value(uknots->Lower())) > EpsU)
|
|
|| (Abs(U2 - uknots->Value(uknots->Upper())) > EpsU);
|
|
segment_in_V = (Abs(V1 - vknots->Value(vknots->Lower())) > EpsV)
|
|
|| (Abs(V2 - vknots->Value(vknots->Upper())) > EpsV);
|
|
|
|
segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetUKnot(const Standard_Integer UIndex, const Standard_Real K)
|
|
{
|
|
if (UIndex < 1 || UIndex > uknots->Length())
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch");
|
|
|
|
Standard_Integer NewIndex = UIndex;
|
|
Standard_Real DU = Abs(Epsilon(K));
|
|
if (UIndex == 1)
|
|
{
|
|
if (K >= uknots->Value(2) - DU)
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
|
|
}
|
|
else if (UIndex == uknots->Length())
|
|
{
|
|
if (K <= uknots->Value(uknots->Length() - 1) + DU)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (K <= uknots->Value(NewIndex - 1) + DU || K >= uknots->Value(NewIndex + 1) - DU)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
|
|
}
|
|
}
|
|
|
|
if (K != uknots->Value(NewIndex))
|
|
{
|
|
uknots->SetValue(NewIndex, K);
|
|
maxderivinvok = 0;
|
|
UpdateUKnots();
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetUKnots(const TColStd_Array1OfReal& UK)
|
|
{
|
|
|
|
Standard_Integer Lower = UK.Lower();
|
|
Standard_Integer Upper = UK.Upper();
|
|
if (Lower < 1 || Lower > uknots->Length() || Upper < 1 || Upper > uknots->Length())
|
|
{
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension");
|
|
}
|
|
if (Lower > 1)
|
|
{
|
|
if (Abs(UK(Lower) - uknots->Value(Lower - 1)) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
|
|
}
|
|
}
|
|
if (Upper < uknots->Length())
|
|
{
|
|
if (Abs(UK(Upper) - uknots->Value(Upper + 1)) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
|
|
}
|
|
}
|
|
Standard_Real K1 = UK(Lower);
|
|
for (Standard_Integer i = Lower; i <= Upper; i++)
|
|
{
|
|
uknots->SetValue(i, UK(i));
|
|
if (i != Lower)
|
|
{
|
|
if (Abs(UK(i) - K1) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
|
|
}
|
|
K1 = UK(i);
|
|
}
|
|
}
|
|
|
|
maxderivinvok = 0;
|
|
UpdateUKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetUKnot(const Standard_Integer UIndex,
|
|
const Standard_Real K,
|
|
const Standard_Integer M)
|
|
{
|
|
IncreaseUMultiplicity(UIndex, M);
|
|
SetUKnot(UIndex, K);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetVKnot(const Standard_Integer VIndex, const Standard_Real K)
|
|
{
|
|
if (VIndex < 1 || VIndex > vknots->Length())
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch");
|
|
Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
|
|
Standard_Real DV = Abs(Epsilon(K));
|
|
if (VIndex == 1)
|
|
{
|
|
if (K >= vknots->Value(2) - DV)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
|
|
}
|
|
}
|
|
else if (VIndex == vknots->Length())
|
|
{
|
|
if (K <= vknots->Value(vknots->Length() - 1) + DV)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (K <= vknots->Value(NewIndex - 1) + DV || K >= vknots->Value(NewIndex + 1) - DV)
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
|
|
}
|
|
}
|
|
|
|
if (K != vknots->Value(NewIndex))
|
|
{
|
|
vknots->SetValue(NewIndex, K);
|
|
maxderivinvok = 0;
|
|
UpdateVKnots();
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetVKnots(const TColStd_Array1OfReal& VK)
|
|
{
|
|
|
|
Standard_Integer Lower = VK.Lower();
|
|
Standard_Integer Upper = VK.Upper();
|
|
if (Lower < 1 || Lower > vknots->Length() || Upper < 1 || Upper > vknots->Length())
|
|
{
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension");
|
|
}
|
|
if (Lower > 1)
|
|
{
|
|
if (Abs(VK(Lower) - vknots->Value(Lower - 1)) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
|
|
}
|
|
}
|
|
if (Upper < vknots->Length())
|
|
{
|
|
if (Abs(VK(Upper) - vknots->Value(Upper + 1)) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
|
|
}
|
|
}
|
|
Standard_Real K1 = VK(Lower);
|
|
for (Standard_Integer i = Lower; i <= Upper; i++)
|
|
{
|
|
vknots->SetValue(i, VK(i));
|
|
if (i != Lower)
|
|
{
|
|
if (Abs(VK(i) - K1) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
|
|
}
|
|
K1 = VK(i);
|
|
}
|
|
}
|
|
|
|
maxderivinvok = 0;
|
|
UpdateVKnots();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetVKnot(const Standard_Integer VIndex,
|
|
const Standard_Real K,
|
|
const Standard_Integer M)
|
|
{
|
|
IncreaseVMultiplicity(VIndex, M);
|
|
SetVKnot(VIndex, K);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::InsertUKnot(const Standard_Real U,
|
|
const Standard_Integer M,
|
|
const Standard_Real ParametricTolerance,
|
|
const Standard_Boolean Add)
|
|
{
|
|
TColStd_Array1OfReal k(1, 1);
|
|
k(1) = U;
|
|
TColStd_Array1OfInteger m(1, 1);
|
|
m(1) = M;
|
|
InsertUKnots(k, m, ParametricTolerance, Add);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::InsertVKnot(const Standard_Real V,
|
|
const Standard_Integer M,
|
|
const Standard_Real ParametricTolerance,
|
|
const Standard_Boolean Add)
|
|
{
|
|
TColStd_Array1OfReal k(1, 1);
|
|
k(1) = V;
|
|
TColStd_Array1OfInteger m(1, 1);
|
|
m(1) = M;
|
|
InsertVKnots(k, m, ParametricTolerance, Add);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncrementUMultiplicity(const Standard_Integer FromI1,
|
|
const Standard_Integer ToI2,
|
|
const Standard_Integer Step)
|
|
{
|
|
Handle(TColStd_HArray1OfReal) tk = uknots;
|
|
TColStd_Array1OfReal k((uknots->Array1())(FromI1), FromI1, ToI2);
|
|
TColStd_Array1OfInteger m(FromI1, ToI2);
|
|
m.Init(Step);
|
|
InsertUKnots(k, m, Epsilon(1.));
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::IncrementVMultiplicity(const Standard_Integer FromI1,
|
|
const Standard_Integer ToI2,
|
|
const Standard_Integer Step)
|
|
{
|
|
Handle(TColStd_HArray1OfReal) tk = vknots;
|
|
TColStd_Array1OfReal k((vknots->Array1())(FromI1), FromI1, ToI2);
|
|
|
|
TColStd_Array1OfInteger m(FromI1, ToI2);
|
|
m.Init(Step);
|
|
|
|
InsertVKnots(k, m, Epsilon(1.));
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::UpdateUKnots()
|
|
{
|
|
|
|
Standard_Integer MaxKnotMult = 0;
|
|
BSplCLib::KnotAnalysis(udeg,
|
|
uperiodic,
|
|
uknots->Array1(),
|
|
umults->Array1(),
|
|
uknotSet,
|
|
MaxKnotMult);
|
|
|
|
if (uknotSet == GeomAbs_Uniform && !uperiodic)
|
|
{
|
|
ufknots = uknots;
|
|
}
|
|
else
|
|
{
|
|
ufknots =
|
|
new TColStd_HArray1OfReal(1, BSplCLib::KnotSequenceLength(umults->Array1(), udeg, uperiodic));
|
|
|
|
BSplCLib::KnotSequence(uknots->Array1(),
|
|
umults->Array1(),
|
|
udeg,
|
|
uperiodic,
|
|
ufknots->ChangeArray1());
|
|
}
|
|
|
|
if (MaxKnotMult == 0)
|
|
Usmooth = GeomAbs_CN;
|
|
else
|
|
{
|
|
switch (udeg - MaxKnotMult)
|
|
{
|
|
case 0:
|
|
Usmooth = GeomAbs_C0;
|
|
break;
|
|
case 1:
|
|
Usmooth = GeomAbs_C1;
|
|
break;
|
|
case 2:
|
|
Usmooth = GeomAbs_C2;
|
|
break;
|
|
case 3:
|
|
Usmooth = GeomAbs_C3;
|
|
break;
|
|
default:
|
|
Usmooth = GeomAbs_C3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::UpdateVKnots()
|
|
{
|
|
Standard_Integer MaxKnotMult = 0;
|
|
BSplCLib::KnotAnalysis(vdeg,
|
|
vperiodic,
|
|
vknots->Array1(),
|
|
vmults->Array1(),
|
|
vknotSet,
|
|
MaxKnotMult);
|
|
|
|
if (vknotSet == GeomAbs_Uniform && !vperiodic)
|
|
{
|
|
vfknots = vknots;
|
|
}
|
|
else
|
|
{
|
|
vfknots =
|
|
new TColStd_HArray1OfReal(1, BSplCLib::KnotSequenceLength(vmults->Array1(), vdeg, vperiodic));
|
|
|
|
BSplCLib::KnotSequence(vknots->Array1(),
|
|
vmults->Array1(),
|
|
vdeg,
|
|
vperiodic,
|
|
vfknots->ChangeArray1());
|
|
}
|
|
|
|
if (MaxKnotMult == 0)
|
|
Vsmooth = GeomAbs_CN;
|
|
else
|
|
{
|
|
switch (vdeg - MaxKnotMult)
|
|
{
|
|
case 0:
|
|
Vsmooth = GeomAbs_C0;
|
|
break;
|
|
case 1:
|
|
Vsmooth = GeomAbs_C1;
|
|
break;
|
|
case 2:
|
|
Vsmooth = GeomAbs_C2;
|
|
break;
|
|
case 3:
|
|
Vsmooth = GeomAbs_C3;
|
|
break;
|
|
default:
|
|
Vsmooth = GeomAbs_C3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Normalizes the parameters if the curve is periodic
|
|
// purpose : that is compute the cache so that it is valid
|
|
//=======================================================================
|
|
|
|
void Geom_BSplineSurface::PeriodicNormalization(Standard_Real& Uparameter,
|
|
Standard_Real& Vparameter) const
|
|
{
|
|
Standard_Real Period, aMaxVal, aMinVal;
|
|
|
|
if (uperiodic)
|
|
{
|
|
aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
|
|
aMinVal = ufknots->Value(udeg + 1);
|
|
Standard_Real eps = Abs(Epsilon(Uparameter));
|
|
Period = aMaxVal - aMinVal;
|
|
|
|
if (Period <= eps)
|
|
throw Standard_OutOfRange(
|
|
"Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
|
|
|
|
Standard_Boolean isLess, isGreater;
|
|
isLess = aMinVal - Uparameter > 0;
|
|
isGreater = Uparameter - aMaxVal > 0;
|
|
if (isLess || isGreater)
|
|
{
|
|
Standard_Real aDPar, aNbPer;
|
|
aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
|
|
modf(aDPar / Period, &aNbPer);
|
|
Uparameter += aNbPer * Period;
|
|
}
|
|
}
|
|
if (vperiodic)
|
|
{
|
|
aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
|
|
aMinVal = vfknots->Value(vdeg + 1);
|
|
Standard_Real eps = Abs(Epsilon(Vparameter));
|
|
Period = aMaxVal - aMinVal;
|
|
|
|
if (Period <= eps)
|
|
throw Standard_OutOfRange(
|
|
"Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
|
|
|
|
Standard_Boolean isLess, isGreater;
|
|
isLess = aMinVal - Vparameter > 0;
|
|
isGreater = Vparameter - aMaxVal > 0;
|
|
if (isLess || isGreater)
|
|
{
|
|
Standard_Real aDPar, aNbPer;
|
|
aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
|
|
modf(aDPar / Period, &aNbPer);
|
|
Vparameter += aNbPer * Period;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetWeight(const Standard_Integer UIndex,
|
|
const Standard_Integer VIndex,
|
|
const Standard_Real Weight)
|
|
{
|
|
if (Weight <= gp::Resolution())
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small");
|
|
TColStd_Array2OfReal& Weights = weights->ChangeArray2();
|
|
if (UIndex < 1 || UIndex > Weights.ColLength() || VIndex < 1 || VIndex > Weights.RowLength())
|
|
{
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch");
|
|
}
|
|
Weights(UIndex + Weights.LowerRow() - 1, VIndex + Weights.LowerCol() - 1) = Weight;
|
|
Rational(Weights, urational, vrational);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetWeightCol(const Standard_Integer VIndex,
|
|
const TColStd_Array1OfReal& CPoleWeights)
|
|
{
|
|
TColStd_Array2OfReal& Weights = weights->ChangeArray2();
|
|
if (VIndex < 1 || VIndex > Weights.RowLength())
|
|
{
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch");
|
|
}
|
|
if (CPoleWeights.Lower() < 1 || CPoleWeights.Lower() > Weights.ColLength()
|
|
|| CPoleWeights.Upper() < 1 || CPoleWeights.Upper() > Weights.ColLength())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension");
|
|
}
|
|
Standard_Integer I = CPoleWeights.Lower();
|
|
while (I <= CPoleWeights.Upper())
|
|
{
|
|
if (CPoleWeights(I) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small");
|
|
}
|
|
Weights(I + Weights.LowerRow() - 1, VIndex + Weights.LowerCol() - 1) = CPoleWeights(I);
|
|
I++;
|
|
}
|
|
// Verifie si c'est rationnel
|
|
Rational(Weights, urational, vrational);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::SetWeightRow(const Standard_Integer UIndex,
|
|
const TColStd_Array1OfReal& CPoleWeights)
|
|
{
|
|
TColStd_Array2OfReal& Weights = weights->ChangeArray2();
|
|
if (UIndex < 1 || UIndex > Weights.ColLength())
|
|
{
|
|
throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch");
|
|
}
|
|
if (CPoleWeights.Lower() < 1 || CPoleWeights.Lower() > Weights.RowLength()
|
|
|| CPoleWeights.Upper() < 1 || CPoleWeights.Upper() > Weights.RowLength())
|
|
{
|
|
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension");
|
|
}
|
|
Standard_Integer I = CPoleWeights.Lower();
|
|
|
|
while (I <= CPoleWeights.Upper())
|
|
{
|
|
if (CPoleWeights(I) <= gp::Resolution())
|
|
{
|
|
throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small");
|
|
}
|
|
Weights(UIndex + Weights.LowerRow() - 1, I + Weights.LowerCol() - 1) = CPoleWeights(I);
|
|
I++;
|
|
}
|
|
// Verifie si c'est rationnel
|
|
Rational(Weights, urational, vrational);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Geom_BSplineSurface::DumpJson(Standard_OStream& theOStream, Standard_Integer theDepth) const
|
|
{
|
|
OCCT_DUMP_TRANSIENT_CLASS_BEGIN(theOStream)
|
|
OCCT_DUMP_BASE_CLASS(theOStream, theDepth, Geom_BoundedSurface)
|
|
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, urational)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vrational)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, uperiodic)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vperiodic)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, uknotSet)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vknotSet)
|
|
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, Usmooth)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, Vsmooth)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, udeg)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vdeg)
|
|
|
|
if (!poles.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, poles->Size())
|
|
if (!weights.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, weights->Size())
|
|
if (!ufknots.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, ufknots->Size())
|
|
if (!vfknots.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vfknots->Size())
|
|
|
|
if (!uknots.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, uknots->Size())
|
|
if (!vknots.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vknots->Size())
|
|
if (!umults.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, umults->Size())
|
|
if (!vmults.IsNull())
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vmults->Size())
|
|
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, umaxderivinv)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, vmaxderivinv)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL(theOStream, maxderivinvok)
|
|
}
|