Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright (c) 1997-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 <GeomConvert_ApproxSurface.hxx>
#include <Adaptor3d_Surface.hxx>
#include <AdvApp2Var_ApproxAFunc2Var.hxx>
#include <AdvApprox_PrefAndRec.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Precision.hxx>
#include <Standard_Real.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_HArray2.hxx>
class GeomConvert_ApproxSurface_Eval : public AdvApp2Var_EvaluatorFunc2Var
{
public:
GeomConvert_ApproxSurface_Eval(const occ::handle<Adaptor3d_Surface>& theAdaptor)
: myAdaptor(theAdaptor)
{
}
void Evaluate(int* theDimension,
double* theUStartEnd,
double* theVStartEnd,
int* theFavorIso,
double* theConstParam,
int* theNbParams,
double* theParameters,
int* theUOrder,
int* theVOrder,
double* theResult,
int* theErrorCode) const override;
private:
mutable occ::handle<Adaptor3d_Surface> myAdaptor;
};
void GeomConvert_ApproxSurface_Eval::Evaluate(int* Dimension,
// Dimension
double* UStartEnd,
// StartEnd[2] in U
double* VStartEnd,
// StartEnd[2] in V
int* FavorIso,
// Choice of constante, 1 for U, 2 for V
double* ConstParam,
// Value of constant parameter
int* NbParams,
// Number of parameters N
double* Parameters,
// Values of parameters,
int* UOrder,
// Derivative Request in U
int* VOrder,
// Derivative Request in V
double* Result,
// Result[Dimension,N]
int* ErrorCode) const
// Error Code
{
*ErrorCode = 0;
// int idim;
int jpar;
double Upar, Vpar;
// Dimension incorrecte
if (*Dimension != 3)
{
*ErrorCode = 1;
}
// Incorrect parameters
/* if (*FavorIso==1) {
Upar = *ConstParam;
if (( Upar < UStartEnd[0] ) || ( Upar > UStartEnd[1] )) {
*ErrorCode = 2;
}
for (jpar=1;jpar<=*NbParams;jpar++) {
Vpar = Parameters[jpar-1];
if (( Vpar < VStartEnd[0] ) || ( Vpar > VStartEnd[1] )) {
*ErrorCode = 2;
}
}
}
else {
Vpar = *ConstParam;
if (( Vpar < VStartEnd[0] ) || ( Vpar > VStartEnd[1] )) {
*ErrorCode = 2;
}
for (jpar=1;jpar<=*NbParams;jpar++) {
Upar = Parameters[jpar-1];
if (( Upar < UStartEnd[0] ) || ( Upar > UStartEnd[1] )) {
*ErrorCode = 2;
}
}
}*/
// Initialisation
myAdaptor = myAdaptor->UTrim(UStartEnd[0], UStartEnd[1], Precision::PConfusion());
myAdaptor = myAdaptor->VTrim(VStartEnd[0], VStartEnd[1], Precision::PConfusion());
/*
for (idim=1;idim<=*Dimension;idim++) {
for (jpar=1;jpar<=*NbParams;jpar++) {
Result[idim-1+(jpar-1)*(*Dimension)] = 0.;
}
}*/
int Order = *UOrder + *VOrder;
gp_Pnt pnt;
gp_Vec vect, v1, v2, v3, v4, v5, v6, v7, v8, v9;
if (*FavorIso == 1)
{
Upar = *ConstParam;
switch (Order)
{
case 0:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Vpar = Parameters[jpar - 1];
pnt = myAdaptor->Value(Upar, Vpar);
Result[(jpar - 1) * (*Dimension)] = pnt.X();
Result[1 + (jpar - 1) * (*Dimension)] = pnt.Y();
Result[2 + (jpar - 1) * (*Dimension)] = pnt.Z();
}
break;
case 1:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Vpar = Parameters[jpar - 1];
myAdaptor->D1(Upar, Vpar, pnt, v1, v2);
if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v1.X();
Result[1 + (jpar - 1) * (*Dimension)] = v1.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v1.Z();
}
else
{
Result[(jpar - 1) * (*Dimension)] = v2.X();
Result[1 + (jpar - 1) * (*Dimension)] = v2.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v2.Z();
}
}
break;
case 2:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Vpar = Parameters[jpar - 1];
myAdaptor->D2(Upar, Vpar, pnt, v1, v2, v3, v4, v5);
if (*UOrder == 2)
{
Result[(jpar - 1) * (*Dimension)] = v3.X();
Result[1 + (jpar - 1) * (*Dimension)] = v3.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v3.Z();
}
else if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v5.X();
Result[1 + (jpar - 1) * (*Dimension)] = v5.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v5.Z();
}
else if (*UOrder == 0)
{
Result[(jpar - 1) * (*Dimension)] = v4.X();
Result[1 + (jpar - 1) * (*Dimension)] = v4.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v4.Z();
}
}
break;
case 3:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Vpar = Parameters[jpar - 1];
myAdaptor->D3(Upar, Vpar, pnt, v1, v2, v3, v4, v5, v6, v7, v8, v9);
if (*UOrder == 2)
{
Result[(jpar - 1) * (*Dimension)] = v8.X();
Result[1 + (jpar - 1) * (*Dimension)] = v8.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v8.Z();
}
else if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v9.X();
Result[1 + (jpar - 1) * (*Dimension)] = v9.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v9.Z();
}
}
break;
case 4:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Vpar = Parameters[jpar - 1];
vect = myAdaptor->DN(Upar, Vpar, *UOrder, *VOrder);
Result[(jpar - 1) * (*Dimension)] = vect.X();
Result[1 + (jpar - 1) * (*Dimension)] = vect.Y();
Result[2 + (jpar - 1) * (*Dimension)] = vect.Z();
}
break;
}
}
else
{
Vpar = *ConstParam;
switch (Order)
{
case 0:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Upar = Parameters[jpar - 1];
pnt = myAdaptor->Value(Upar, Vpar);
Result[(jpar - 1) * (*Dimension)] = pnt.X();
Result[1 + (jpar - 1) * (*Dimension)] = pnt.Y();
Result[2 + (jpar - 1) * (*Dimension)] = pnt.Z();
}
break;
case 1:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Upar = Parameters[jpar - 1];
myAdaptor->D1(Upar, Vpar, pnt, v1, v2);
if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v1.X();
Result[1 + (jpar - 1) * (*Dimension)] = v1.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v1.Z();
}
else
{
Result[(jpar - 1) * (*Dimension)] = v2.X();
Result[1 + (jpar - 1) * (*Dimension)] = v2.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v2.Z();
}
}
break;
case 2:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Upar = Parameters[jpar - 1];
myAdaptor->D2(Upar, Vpar, pnt, v1, v2, v3, v4, v5);
if (*UOrder == 2)
{
Result[(jpar - 1) * (*Dimension)] = v3.X();
Result[1 + (jpar - 1) * (*Dimension)] = v3.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v3.Z();
}
else if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v5.X();
Result[1 + (jpar - 1) * (*Dimension)] = v5.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v5.Z();
}
else if (*UOrder == 0)
{
Result[(jpar - 1) * (*Dimension)] = v4.X();
Result[1 + (jpar - 1) * (*Dimension)] = v4.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v4.Z();
}
}
break;
case 3:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Upar = Parameters[jpar - 1];
myAdaptor->D3(Upar, Vpar, pnt, v1, v2, v3, v4, v5, v6, v7, v8, v9);
if (*UOrder == 2)
{
Result[(jpar - 1) * (*Dimension)] = v8.X();
Result[1 + (jpar - 1) * (*Dimension)] = v8.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v8.Z();
}
else if (*UOrder == 1)
{
Result[(jpar - 1) * (*Dimension)] = v9.X();
Result[1 + (jpar - 1) * (*Dimension)] = v9.Y();
Result[2 + (jpar - 1) * (*Dimension)] = v9.Z();
}
}
break;
case 4:
for (jpar = 1; jpar <= *NbParams; jpar++)
{
Upar = Parameters[jpar - 1];
vect = myAdaptor->DN(Upar, Vpar, *UOrder, *VOrder);
Result[(jpar - 1) * (*Dimension)] = vect.X();
Result[1 + (jpar - 1) * (*Dimension)] = vect.Y();
Result[2 + (jpar - 1) * (*Dimension)] = vect.Z();
}
break;
}
}
}
//=================================================================================================
GeomConvert_ApproxSurface::GeomConvert_ApproxSurface(const occ::handle<Geom_Surface>& Surf,
const double Tol3d,
const GeomAbs_Shape UContinuity,
const GeomAbs_Shape VContinuity,
const int MaxDegU,
const int MaxDegV,
const int MaxSegments,
const int PrecisCode)
{
occ::handle<Adaptor3d_Surface> aSurfAdaptor = new GeomAdaptor_Surface(Surf);
Approximate(aSurfAdaptor,
Tol3d,
UContinuity,
VContinuity,
MaxDegU,
MaxDegV,
MaxSegments,
PrecisCode);
}
GeomConvert_ApproxSurface::GeomConvert_ApproxSurface(const occ::handle<Adaptor3d_Surface>& Surf,
const double Tol3d,
const GeomAbs_Shape UContinuity,
const GeomAbs_Shape VContinuity,
const int MaxDegU,
const int MaxDegV,
const int MaxSegments,
const int PrecisCode)
{
Approximate(Surf, Tol3d, UContinuity, VContinuity, MaxDegU, MaxDegV, MaxSegments, PrecisCode);
}
void GeomConvert_ApproxSurface::Approximate(const occ::handle<Adaptor3d_Surface>& theSurf,
const double theTol3d,
const GeomAbs_Shape theUContinuity,
const GeomAbs_Shape theVContinuity,
const int theMaxDegU,
const int theMaxDegV,
const int theMaxSegments,
const int thePrecisCode)
{
double U0 = theSurf->FirstUParameter();
double U1 = theSurf->LastUParameter();
double V0 = theSurf->FirstVParameter();
double V1 = theSurf->LastVParameter();
// "Init of subspace counts and tolerances"
int nb1 = 0, nb2 = 0, nb3 = 1;
occ::handle<NCollection_HArray1<double>> nul1 = new NCollection_HArray1<double>(1, 1);
nul1->SetValue(1, 0.);
occ::handle<NCollection_HArray2<double>> nul2 = new NCollection_HArray2<double>(1, 1, 1, 4);
nul2->SetValue(1, 1, 0.);
nul2->SetValue(1, 2, 0.);
nul2->SetValue(1, 3, 0.);
nul2->SetValue(1, 4, 0.);
occ::handle<NCollection_HArray1<double>> eps3D = new NCollection_HArray1<double>(1, 1);
eps3D->SetValue(1, theTol3d);
occ::handle<NCollection_HArray2<double>> epsfr = new NCollection_HArray2<double>(1, 1, 1, 4);
epsfr->SetValue(1, 1, theTol3d);
epsfr->SetValue(1, 2, theTol3d);
epsfr->SetValue(1, 3, theTol3d);
epsfr->SetValue(1, 4, theTol3d);
// " Init du type d'iso"
GeomAbs_IsoType IsoType = GeomAbs_IsoV;
int NbDec;
NbDec = theSurf->NbUIntervals(GeomAbs_C2);
NCollection_Array1<double> UDec_C2(1, NbDec + 1);
theSurf->UIntervals(UDec_C2, GeomAbs_C2);
NbDec = theSurf->NbVIntervals(GeomAbs_C2);
NCollection_Array1<double> VDec_C2(1, NbDec + 1);
theSurf->VIntervals(VDec_C2, GeomAbs_C2);
NbDec = theSurf->NbUIntervals(GeomAbs_C3);
NCollection_Array1<double> UDec_C3(1, NbDec + 1);
theSurf->UIntervals(UDec_C3, GeomAbs_C3);
NbDec = theSurf->NbVIntervals(GeomAbs_C3);
NCollection_Array1<double> VDec_C3(1, NbDec + 1);
theSurf->VIntervals(VDec_C3, GeomAbs_C3);
// Approximation with preferential splitting
// at C2 discontinuity locations
AdvApprox_PrefAndRec pUDec(UDec_C2, UDec_C3);
AdvApprox_PrefAndRec pVDec(VDec_C2, VDec_C3);
// POP for WNT
GeomConvert_ApproxSurface_Eval ev(theSurf);
AdvApp2Var_ApproxAFunc2Var approx(nb1,
nb2,
nb3,
nul1,
nul1,
eps3D,
nul2,
nul2,
epsfr,
U0,
U1,
V0,
V1,
IsoType,
theUContinuity,
theVContinuity,
thePrecisCode,
theMaxDegU,
theMaxDegV,
theMaxSegments,
ev,
pUDec,
pVDec);
myMaxError = approx.MaxError(3, 1);
myBSplSurf = approx.Surface(1);
myIsDone = approx.IsDone();
myHasResult = approx.HasResult();
}
//=================================================================================================
occ::handle<Geom_BSplineSurface> GeomConvert_ApproxSurface::Surface() const
{
return myBSplSurf;
}
//=================================================================================================
bool GeomConvert_ApproxSurface::IsDone() const
{
return myIsDone;
}
//=================================================================================================
bool GeomConvert_ApproxSurface::HasResult() const
{
return myHasResult;
}
//=================================================================================================
double GeomConvert_ApproxSurface::MaxError() const
{
return myMaxError;
}
//=================================================================================================
void GeomConvert_ApproxSurface::Dump(Standard_OStream& o) const
{
o << '\n';
if (!myHasResult)
{
o << "No result" << '\n';
}
else
{
o << "Result max error :" << myMaxError << '\n';
}
o << '\n';
}