mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-16 10:08:36 +03:00
Automatic upgrade of OCCT code by command "occt_upgrade . -nocdl": - WOK-generated header files from inc and sources from drv are moved to src - CDL files removed - All packages are converted to nocdlpack
458 lines
14 KiB
C++
458 lines
14 KiB
C++
// Created on: 1996-06-07
|
|
// Created by: Philippe MANGIN
|
|
// Copyright (c) 1996-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.
|
|
|
|
|
|
#include <Geom_BezierSurface.hxx>
|
|
#include <Geom_BSplineSurface.hxx>
|
|
#include <Geom_Curve.hxx>
|
|
#include <GeomConvert_CompBezierSurfacesToBSplineSurface.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Vec.hxx>
|
|
#include <gp_XYZ.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_ConstructionError.hxx>
|
|
#include <Standard_DimensionError.hxx>
|
|
#include <Standard_NotImplemented.hxx>
|
|
#include <TColGeom_Array2OfBezierSurface.hxx>
|
|
#include <TColgp_HArray2OfPnt.hxx>
|
|
#include <TColStd_HArray1OfReal.hxx>
|
|
|
|
// ============================================================================
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface::
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface(const TColGeom_Array2OfBezierSurface& Beziers)
|
|
// ============================================================================
|
|
{
|
|
Standard_Integer ii;
|
|
myDone = Standard_True;
|
|
// Choix des noeuds
|
|
myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
|
|
for (ii=0; ii<myUKnots->Length(); ii++) { myUKnots->SetValue(ii+1, ii); }
|
|
|
|
myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
|
|
for (ii=0; ii<myVKnots->Length(); ii++) { myVKnots->SetValue(ii+1, ii); }
|
|
|
|
// Calcul des Poles
|
|
Perform(Beziers);
|
|
}
|
|
|
|
|
|
// ============================================================================
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface::
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface(
|
|
const TColGeom_Array2OfBezierSurface& Beziers,
|
|
const Standard_Real Tolerance,
|
|
const Standard_Boolean RemoveKnots)
|
|
// ============================================================================
|
|
{
|
|
Standard_Integer ii, jj, multU=0, multV, minus;
|
|
Standard_Boolean Ok;
|
|
gp_Vec vec;
|
|
Standard_Real V1, V2, V3, Ratio, L1, L2, Tol, val;
|
|
gp_Pnt P1, P2, P3;
|
|
Handle(Geom_Curve) FirstCurve, SecondCurve;
|
|
|
|
myDone = Standard_True;
|
|
|
|
// Choix des noeuds
|
|
|
|
myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
|
|
myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
|
|
|
|
// --> en U
|
|
myUKnots->SetValue(1, 0);
|
|
jj = myVKnots->Length()/2;
|
|
FirstCurve = Beziers(1, jj)->VIso(0.3);
|
|
FirstCurve->D0(0, P1);
|
|
FirstCurve->D0(0.5, P2);
|
|
FirstCurve->D1(1, P3, vec);
|
|
|
|
L1 = P1.Distance(P2) + P2.Distance(P3);
|
|
myUKnots->SetValue(2, L1);
|
|
|
|
V1 = vec.Magnitude();
|
|
// si la Parametrisation est trop bizzare on garde la pseudo-longueur
|
|
if ((V1 > 1000 * L1) || (V1 < L1 * 1.e-3)) V1 = L1;
|
|
|
|
for (ii=2; ii<myUKnots->Length(); ii++) {
|
|
|
|
SecondCurve = Beziers(ii, jj)->VIso(0.3);
|
|
SecondCurve->D1(0, P1, vec);
|
|
V2 = vec.Magnitude();
|
|
SecondCurve->D0(0.5, P2);
|
|
SecondCurve->D1(1, P3, vec);
|
|
V3 = vec.Magnitude();
|
|
L2 = P1.Distance(P2) + P2.Distance(P3);
|
|
|
|
// On calcul le ratio, en evitant les cas tordus...
|
|
if ((V2 > 1000 * L2) || (V2 < L2 * 1.e-3)) V2 = L2;
|
|
if ((V3 > 1000 * L2) || (V3 < L2 * 1.e-3)) V3 = L2;
|
|
|
|
Ratio = 1;
|
|
if ( (V1 > Precision::Confusion()) && (V2 > Precision::Confusion()) ) {
|
|
Ratio = V2 / V1;
|
|
}
|
|
if ( (Ratio < Precision::Confusion())
|
|
|| (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
|
|
|
|
// On en deduit un nouveau noeud
|
|
val = myUKnots->Value(ii);
|
|
myUKnots->SetValue(ii+1, val + Ratio*(val- myUKnots->Value(ii-1)) );
|
|
|
|
// Et c'est reparti, pour un tour
|
|
L1 = L2;
|
|
V1 = V3;
|
|
FirstCurve = SecondCurve;
|
|
}
|
|
|
|
// --> en V
|
|
myVKnots->SetValue(1, 0);
|
|
ii = myUKnots->Length()/2;
|
|
FirstCurve = Beziers(ii, 1)->UIso(0.3);
|
|
FirstCurve->D0(0, P1);
|
|
FirstCurve->D0(0.5, P2);
|
|
FirstCurve->D1(1, P3, vec);
|
|
|
|
L1 = P1.Distance(P2) + P2.Distance(P3);
|
|
myVKnots->SetValue(2, L1);
|
|
|
|
V1 = vec.Magnitude();
|
|
// si la Parametrisation est trop bizzare on garde la pseudo-longueur
|
|
if ((V1 > 1000 * L1) || (V1 < L1 * 1.e-3)) V1 = L1;
|
|
|
|
for (jj=2; jj<myVKnots->Length(); jj++) {
|
|
|
|
SecondCurve = Beziers(ii, jj)->UIso(0.3);
|
|
SecondCurve->D1(0, P1, vec);
|
|
V2 = vec.Magnitude();
|
|
SecondCurve->D0(0.5, P2);
|
|
SecondCurve->D1(1, P3, vec);
|
|
V3 = vec.Magnitude();
|
|
L2 = P1.Distance(P2) + P2.Distance(P3);
|
|
|
|
// On calcul le ratio, en evitant les cas tordus...
|
|
if ((V2 > 1000 * L2) || (V2 < L2 * 1.e-3)) V2 = L2;
|
|
if ((V3 > 1000 * L2) || (V3 < L2 * 1.e-3)) V3 = L2;
|
|
|
|
Ratio = 1;
|
|
if ( (V1 > Precision::Confusion()) && (V2 > Precision::Confusion()) ) {
|
|
Ratio = V2 / V1;
|
|
}
|
|
if ( (Ratio < Precision::Confusion())
|
|
|| (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
|
|
|
|
// On en deduit un nouveau noeud
|
|
val = myVKnots->Value(jj);
|
|
myVKnots->SetValue(jj+1, val + Ratio*(val-myVKnots->Value(jj-1)) );
|
|
|
|
// Et c'est reparti, pour un tour
|
|
L1 = L2;
|
|
V1 = V3;
|
|
FirstCurve = SecondCurve;
|
|
}
|
|
|
|
// Calcul des Poles
|
|
Perform(Beziers);
|
|
|
|
// Reduction de la multiplicite
|
|
Handle(Geom_BSplineSurface) Surface = new (Geom_BSplineSurface)
|
|
(myPoles->Array2(),
|
|
myUKnots->Array1(),
|
|
myVKnots->Array1(),
|
|
myUMults->Array1(),
|
|
myVMults->Array1(),
|
|
myUDegree,
|
|
myVDegree);
|
|
|
|
if (RemoveKnots) minus = 0;
|
|
else minus = 1;
|
|
|
|
for (ii=myUKnots->Length()-1; ii>1; ii--) {
|
|
Ok=Standard_True;
|
|
Tol = Tolerance/2;
|
|
multU = myUMults->Value(ii)-1;
|
|
for ( ; Ok && multU > minus; multU--, Tol/=2) {
|
|
Ok = Surface->RemoveUKnot(ii, multU, Tol);
|
|
}
|
|
}
|
|
|
|
for (ii=myVKnots->Length()-1; ii>1; ii--) {
|
|
Ok=Standard_True;
|
|
Tol = Tolerance/2;
|
|
multV = myVMults->Value(ii)-1;
|
|
for ( ; Ok && multU > minus; multV--, Tol/=2) {
|
|
Ok = Surface->RemoveVKnot(ii, multV, Tol);
|
|
}
|
|
}
|
|
|
|
// Les nouveaux champs sont arrivees ....
|
|
myPoles = new (TColgp_HArray2OfPnt) (1, Surface->NbUPoles(), 1, Surface->NbVPoles());
|
|
Surface->Poles( myPoles->ChangeArray2());
|
|
|
|
myUMults = new (TColStd_HArray1OfInteger) (1, Surface->NbUKnots());
|
|
myVMults = new (TColStd_HArray1OfInteger) (1, Surface->NbVKnots());
|
|
myUKnots = new (TColStd_HArray1OfReal) (1, Surface->NbUKnots());
|
|
myVKnots = new (TColStd_HArray1OfReal) (1, Surface->NbVKnots());
|
|
|
|
|
|
Surface->UMultiplicities( myUMults->ChangeArray1());
|
|
Surface->VMultiplicities( myVMults->ChangeArray1());
|
|
Surface->UKnots( myUKnots->ChangeArray1());
|
|
Surface->VKnots( myVKnots->ChangeArray1());
|
|
}
|
|
|
|
// ============================================================================
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface::
|
|
GeomConvert_CompBezierSurfacesToBSplineSurface(
|
|
const TColGeom_Array2OfBezierSurface& Beziers,
|
|
const TColStd_Array1OfReal& UKnots,
|
|
const TColStd_Array1OfReal& VKnots,
|
|
const GeomAbs_Shape UContinuity,
|
|
const GeomAbs_Shape VContinuity,
|
|
const Standard_Real Tolerance)
|
|
// ============================================================================
|
|
{
|
|
Standard_Integer decu=0, decv=0;
|
|
Standard_Boolean Ok;
|
|
|
|
myDone = Standard_True;
|
|
|
|
// Recuperation des noeuds
|
|
myUKnots = new (TColStd_HArray1OfReal) (1, Beziers.ColLength()+1);
|
|
myUKnots->ChangeArray1() = UKnots;
|
|
|
|
myVKnots = new (TColStd_HArray1OfReal) (1, Beziers.RowLength()+1);
|
|
myVKnots->ChangeArray1() = VKnots;
|
|
|
|
// Calcul des Poles
|
|
Perform(Beziers);
|
|
|
|
// Obtention des bonne continuitee
|
|
|
|
switch ( UContinuity ) {
|
|
case GeomAbs_C0 :
|
|
decu = 0;
|
|
break;
|
|
case GeomAbs_C1 :
|
|
decu = 1;
|
|
break;
|
|
case GeomAbs_C2 :
|
|
decu = 2;
|
|
break;
|
|
case GeomAbs_C3 :
|
|
decu = 3;
|
|
break;
|
|
default:
|
|
Standard_ConstructionError::Raise(
|
|
"GeomConvert_CompBezierSurfacesToBSpl:: UContinuity error");
|
|
}
|
|
|
|
switch ( VContinuity ) {
|
|
case GeomAbs_C0 :
|
|
decv = 0;
|
|
break;
|
|
case GeomAbs_C1 :
|
|
decv = 1;
|
|
break;
|
|
case GeomAbs_C2 :
|
|
decv = 2;
|
|
break;
|
|
case GeomAbs_C3 :
|
|
decv = 3;
|
|
break;
|
|
default:
|
|
Standard_ConstructionError::Raise(
|
|
"GeomConvert_CompBezierSurfacesToBSpl:: VContinuity error");
|
|
}
|
|
|
|
|
|
if ( (decu>0) || (decv>0) ) {
|
|
|
|
Standard_Integer ii;
|
|
Standard_Integer multU = myUDegree - decu;
|
|
Standard_ConstructionError_Raise_if(
|
|
((multU <= 0) && (myUKnots->Length()>2)) ,
|
|
"GeomConvert_CompBezierSurfacesToBSpl:: UContinuity or Udeg error");
|
|
|
|
Standard_Integer multV = myVDegree - decv;
|
|
Standard_ConstructionError_Raise_if(
|
|
((multV <= 0) && (myVKnots->Length()>2)) ,
|
|
"GeomConvert_CompBezierSurfacesToBSpl:: VContinuity or Vdeg error");
|
|
|
|
Handle(Geom_BSplineSurface) Surface = new (Geom_BSplineSurface)
|
|
(myPoles->Array2(),
|
|
myUKnots->Array1(),
|
|
myVKnots->Array1(),
|
|
myUMults->Array1(),
|
|
myVMults->Array1(),
|
|
myUDegree,
|
|
myVDegree);
|
|
|
|
|
|
if (decu>0) {
|
|
for (ii=2; ii<myUKnots->Length(); ii++) {
|
|
Ok = Surface->RemoveUKnot(ii, multU, Tolerance);
|
|
if (!Ok) {myDone = Ok;}
|
|
}
|
|
}
|
|
|
|
if (decv>0) {
|
|
for (ii=2; ii<myVKnots->Length(); ii++) {
|
|
Ok = Surface->RemoveVKnot(ii, multV, Tolerance);
|
|
if (!Ok) {myDone = Ok;}
|
|
}
|
|
}
|
|
|
|
// Les nouveaux champs sont arrivees ....
|
|
myPoles = new (TColgp_HArray2OfPnt) (1, Surface->NbUPoles(), 1, Surface->NbVPoles());
|
|
Surface->Poles( myPoles->ChangeArray2());
|
|
Surface->UMultiplicities( myUMults->ChangeArray1());
|
|
Surface->VMultiplicities( myVMults->ChangeArray1());
|
|
}
|
|
}
|
|
|
|
|
|
// ================================================================================
|
|
void GeomConvert_CompBezierSurfacesToBSplineSurface::Perform(
|
|
const TColGeom_Array2OfBezierSurface& Beziers)
|
|
// ================================================================================
|
|
{
|
|
Standard_Integer IU, IV;
|
|
|
|
// (1) Determination des degrees et si le resultat est rationnel.
|
|
isrational = Standard_False;
|
|
myUDegree = 1;
|
|
myVDegree = 1;
|
|
|
|
for (IU=Beziers.LowerRow(); IU <=Beziers.UpperRow(); IU++) {
|
|
for (IV=Beziers.LowerCol(); IV <=Beziers.UpperCol(); IV++) {
|
|
if ( Beziers(IU, IV)-> IsURational()
|
|
|| Beziers(IU, IV)-> IsVRational()) { isrational = Standard_True;}
|
|
|
|
myUDegree = ( Beziers(IU, IV)->UDegree() > myUDegree ) ?
|
|
Beziers(IU, IV)->UDegree() : myUDegree;
|
|
|
|
myVDegree = ( Beziers(IU, IV)->VDegree() > myVDegree ) ?
|
|
Beziers(IU, IV)->VDegree() : myVDegree;
|
|
}
|
|
}
|
|
|
|
Standard_NotImplemented_Raise_if(isrational,
|
|
"CompBezierSurfacesToBSpl : rational !");
|
|
|
|
|
|
// (2) Boucle sur les carreaux -----------------------------
|
|
|
|
Handle(Geom_BezierSurface) Patch;
|
|
Standard_Integer UIndex, VIndex, uindex, vindex, udeb, vdeb;
|
|
Standard_Integer upol, vpol, ii;
|
|
|
|
|
|
myPoles = new (TColgp_HArray2OfPnt)
|
|
( 1, (myUDegree+1)*Beziers.ColLength() - myUKnots->Length() + 2 ,
|
|
1, (myVDegree+1)*Beziers.RowLength() - myVKnots->Length() + 2 );
|
|
|
|
for (IU=Beziers.LowerRow(); IU <=Beziers.UpperRow(); IU++) {
|
|
UIndex = (IU-1)*myUDegree + 1;
|
|
for (IV=Beziers.LowerCol(); IV <=Beziers.UpperCol(); IV++) {
|
|
|
|
Patch = Beziers(IU, IV);
|
|
VIndex = (IV-1)*myVDegree + 1;
|
|
|
|
// (2.1) Augmentation du degree
|
|
Patch->Increase(myUDegree, myVDegree);
|
|
|
|
// (2.2) Poles a recopier
|
|
if (IU==1) {udeb = 1;}
|
|
else {udeb = 2;}
|
|
if (IV==1) {vdeb = 1;}
|
|
else {vdeb = 2;}
|
|
|
|
uindex = UIndex + udeb -1;
|
|
|
|
for (upol = udeb; upol <= myUDegree+1; upol++, uindex++ ) {
|
|
vindex = VIndex + vdeb - 1;
|
|
for (vpol = vdeb; vpol <= myVDegree+1; vpol++, vindex++) {
|
|
myPoles->ChangeValue(uindex, vindex) = Patch->Pole(upol, vpol);
|
|
}
|
|
}
|
|
|
|
// (2.3) Poles a sommer
|
|
if (udeb==2) {
|
|
vindex = VIndex + vdeb - 1;
|
|
for (vpol = vdeb; vpol <= myVDegree+1; vpol++, vindex++) {
|
|
myPoles->ChangeValue(UIndex, vindex).ChangeCoord() +=
|
|
Patch->Pole(1, vpol).Coord();
|
|
}
|
|
}
|
|
|
|
if (vdeb==2) {
|
|
uindex = UIndex + udeb - 1;
|
|
for (upol = udeb; upol <= myUDegree+1; upol++, uindex++) {
|
|
myPoles->ChangeValue(uindex, VIndex).ChangeCoord() +=
|
|
Patch->Pole(upol, 1).Coord();
|
|
}
|
|
}
|
|
|
|
if (udeb==2 && vdeb==2) {
|
|
myPoles->ChangeValue(UIndex, VIndex).ChangeCoord() +=
|
|
Patch->Pole(1, 1).Coord();
|
|
}
|
|
}
|
|
}
|
|
|
|
// (3) Elimination des redondances
|
|
// car dans la boucle precedente on compte :
|
|
// - 2 fois les poles associes aux noeuds simples
|
|
// - 4 fois les poles associes aux doubles noeuds (en U et V)
|
|
|
|
// (3.1) Elimination en U
|
|
for ( UIndex = myUDegree+1, ii=2;
|
|
ii< myUKnots->Length();
|
|
ii++, UIndex+=myUDegree) {
|
|
for (vpol = 1; vpol<=myPoles->UpperCol(); vpol++) {
|
|
myPoles->ChangeValue(UIndex, vpol).ChangeCoord() *= 0.5;
|
|
}
|
|
}
|
|
|
|
// (3.2) Elimination en V
|
|
for ( VIndex = myVDegree+1, ii=2;
|
|
ii< myVKnots->Length();
|
|
ii++, VIndex += myVDegree) {
|
|
for (upol = 1; upol<=myPoles->UpperRow(); upol++) {
|
|
myPoles->ChangeValue(upol, VIndex).ChangeCoord() *= 0.5;
|
|
}
|
|
}
|
|
|
|
// (4) Init des multiplicites
|
|
myUMults = new (TColStd_HArray1OfInteger) (1, myUKnots->Length());
|
|
myUMults->Init( myUDegree);
|
|
myUMults->SetValue(1, myUDegree+1);
|
|
myUMults->SetValue( myUMults->Upper(), myUDegree+1);
|
|
|
|
myVMults = new (TColStd_HArray1OfInteger) (1, myVKnots->Length());
|
|
myVMults->Init( myVDegree);
|
|
myVMults->SetValue(1, myVDegree+1);
|
|
myVMults->SetValue(myVMults->Upper(), myVDegree+1);
|
|
}
|
|
|
|
// ========================================================================
|
|
Standard_Boolean GeomConvert_CompBezierSurfacesToBSplineSurface::IsDone() const
|
|
// ========================================================================
|
|
{
|
|
return myDone;
|
|
}
|
|
|