Files
EgtGeomKernel/SbzFromCurves.cpp
Daniele Bariletti e7d25b2d0e EgtGeomKernel :
- correzioni e migliorie a regolarize dei bordi per trimming.
2026-04-21 15:04:24 +02:00

845 lines
32 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 20024
//----------------------------------------------------------------------------
// File : SbzFromCurves.cpp Data : 07.05.24 Versione : 2.6e2
// Contenuto : Implementazione di funzioni per creazione di superfici Sbz
// a partire da curve, con diversi metodi.
//
//
// Modifiche : 07.05.24 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "Voronoi.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkSbzFromCurves.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <future>
using namespace std ;
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol)
{
// verifica parametri
if ( pCurve == nullptr)
return nullptr ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByFlatContour( PL))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
{
// verifica parametri
if ( &vpCurve == nullptr || vpCurve.empty())
return nullptr ;
// calcolo le polilinee che approssimano le curve della regione
POLYLINEVECTOR vPL ;
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return nullptr ;
}
Vector3d vtN ;
INTMATRIX vnPLIndMat ;
BOOLVECTOR vbInvert ;
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat,vbInvert))
return nullptr ;
POLYLINEVECTOR vPLOrd ;
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ;
if ( vbInvert[vnPLIndMat[i][j]])
vPLOrd.back().Invert() ;
}
}
// creo e setto la superficie di bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByRegion( vPLOrd))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( pCurve == nullptr || &vtExtr == nullptr)
return nullptr ;
PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ;
// creo e setto la superficie di Bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
////-------------------------------------------------------------------------------
//ISurfCompo*
//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) ///// RICHIEDE LE SURF COMPO/////////////////
//{
// // verifica parametri
// if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr)
// return nullptr ;
// // se una sola curva, uso la funzione precedente
// if ( vpCurve.size() == 1 )
// return GetSurfBezierByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
// // calcolo le polilinee che approssimano le curve della regione
// POLYLINEVECTOR vPL ;
// Vector3d vtN ;
// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
// return nullptr ;
// // verifico la direzione di estrusione
// double dOrthoExtr = vtN * vtExtr ;
// if ( ( abs( dOrthoExtr) < EPS_SMALL))
// return nullptr ;
// // se componente estrusione negativa, inverto tutti i percorsi
// if ( dOrthoExtr < 0) {
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
// vPL[i].Invert() ;
// }
// // creo la prima superficie di estremità
// PtrOwner<SurfBezier> pSbz1( CreateBasicSurfBezier()) ;
// if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL))
// return nullptr ;
// // creo la seconda superficie come copia della prima e poi inverto la prima
// PtrOwner<ISurfBezier> pSbz2( pSbz1->Clone()) ;
// pSbz1->Invert() ;
//
// // creo e unisco le diverse superfici di estrusione
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// // estrusione
// SurfBezier SbzLat ;
// if ( ! SbzLat.CreateByExtrusion( vPL[i], vtExtr)) // qui mi serve la curva e non la polyline della curva. vuol dire che dalla CalcRegionPolyLines devo farmi restituire anche le curve ordinate
// return nullptr ;
// }
// // restituisco la superficie
// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica
//}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
bool bCapEnds, double dLinTol) // con l'aggiunta delle SURFCOMPO posso gestire anche i cap e curve che attraversano l'asse
{
// verifica parametri
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
return nullptr ;
// limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, ANG_FULL, 0))
return nullptr ;
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pSbz->GetVolume( dVol) && dVol < 0)
pSbz->Invert() ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
return nullptr ;
// limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ;
// creo e setto la superficie bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
return nullptr ;
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pSbz->GetVolume( dVol) && dVol < 0)
pSbz->Invert() ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
{
// riferimento all'inizio della linea guida
Frame3d frStart ;
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
// capisco se la guida è una linea spezzata o una curva
bool bGuideIsPolyLine = false ;
switch ( pGuide->GetType()) {
case CRV_COMPO : {
bGuideIsPolyLine = true ;
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
const ICurve* pCrv = pCC->GetCurve( i) ;
if ( pCrv->GetType() != CRV_LINE) {
if ( pCrv->GetType() == CRV_BEZIER) {
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
bGuideIsPolyLine = pCrvBez->IsALine() ;
}
else
bGuideIsPolyLine = false ;
}
}
break ;
}
case CRV_LINE :
bGuideIsPolyLine = true ;
break ;
case CRV_BEZIER : {
// controllo se i punti di controllo sono allineati
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
bGuideIsPolyLine = pCrvBez->IsALine() ;
break ;
}
default :
break ;
}
bool bRat = false ;
int nSpanV = 0 ;
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
if ( bGuideIsPolyLine ) {
if ( pGuide->GetType() == CRV_LINE)
nSpanV = 1 ;
else if ( pGuide->GetType() == CRV_COMPO)
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
}
else {
//converto in bezier la guida ( grado 3, non razionale)
if ( pGuide->GetType() != CRV_BEZIER)
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
else {
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
if ( ! pGuideBez->IsRational())
pCrvV->AddCurve( pGuide->Clone()) ;
else
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
}
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
return nullptr ;
nSpanV = pCrvV->GetCurveCount() ;
}
// converto in bezier la sezione ( grado 3, non razionale)
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
if ( pSect->GetType() != CRV_BEZIER)
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
else {
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
}
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
return nullptr ;
int nSpanU = int( pCrvU->GetCurveCount()) ;
int nDegV = 3 ;
if ( bGuideIsPolyLine)
nDegV = 1 ;
int nDegU = 3 ;
// superficie swept
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
if ( bGuideIsPolyLine) {
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
// porto la sezione nel sistema di riferimento del piano in cui giace
pCrvU->ToLoc( frStart) ;
// la guida è una linea spezzata, quindi posso lavorare con gli offset
ICRVCOMPOPOVECTOR vCC ;
INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ;
int nMaxSpanV = nSpanV ;
for ( int i = 0 ; i < nSpanU ; ++i) {
const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
// faccio l'offset della guida nel punto di controllo della sezione
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
return nullptr ;
vCC.emplace_back() ;
vCC.back()->AddCurve(OffsCrv.GetLongerCurve()) ;
if ( IsNull( pCrvV))
return nullptr ;
vCC.back()->Translate( ptCtrl.y * frStart.VersY()) ;
//mRep[ i * nDegU + j].resize(vCC.back()->GetCurveCount()) ;
nMaxSpanV = max ( nMaxSpanV, vCC.back()->GetCurveCount()) ;
}
}
// devo capire quante span in V devo creare e a quale span appartengono i tratti degli offset
for ( int k = 0 ; k < int( vCC.size()) ; ++k) {
const ICurveComposite* pCC = vCC[k] ;
mRep[k].resize( nMaxSpanV) ;
for ( int z = 0 ; z < int( mRep[k].size()) ; ++z) {
int nProp = - 1 ; pCC->GetCurveTempProp( z, nProp) ;
if ( nProp == 0) {
// ho trovato almeno una curva di offset che ha un tratto non derivante direttamente dalla curva originale
// tutte le altre curve che hanno curve di offeset che non hanno questo tratto bonus dovranno ripetere il punto di controllo
for ( int w = 0 ; w < int( vCC.size()) ; ++w) {
const ICurveComposite* pCCOther = vCC[w] ;
int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ;
if ( nPropCheck != 0)
mRep[w][z] = 1 ;
}
}
}
}
// conto in quante colonne di mRep la somma degli elementi è != 0
// questo numero va aggiunto all'attuale nSpanV
int nSpanPlus = 0 ;
for ( int z = 0 ; z < nMaxSpanV ; ++z) {
int nPosTot = 0 ;
for ( int k = 0 ; k < int( mRep.size()) ; ++k )
nPosTot += mRep[k][z] ;
if ( nPosTot != 0)
nSpanPlus += 1 ;
}
nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ;
nSpanV = nMaxSpanV ;
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
//// aggiungo i punti di controllo alla superficie
//for ( int i = 0 ; i < nSpanU ; ++i) {
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
// const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ;
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
// if ( pCL == nullptr)
// return nullptr ;
// if ( z == 0) {
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
// }
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
// }
// }
//}
//// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO
//for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
// const ICurveComposite* pOffsetCrv = vCC[i] ;
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
// if ( pCL == nullptr)
// return nullptr ;
// if ( z == 0) {
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
// }
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
// }
//}
}
else {
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
// VERSIONE con le copie della sezione ( superficie skinned)
// creo delle copie della curva e faccio la skinned
// per ogni sottocurva della guida ( che sarà composta da curve di bezier di grado 3)
// posiziono una copia della curva di sezione per ogni punto di controllo
frStart.Set( ptStart, vtStart) ;
pCrvU->ToLoc( frStart) ;
ICURVEPOVECTOR vCrvSet ;
CICURVEPVECTOR vpCrv ;
RotationMinimizingFrame rmfGuide ; rmfGuide.Set( pCrvV, frStart) ;
//double dStep = 0.25 ;
FRAME3DVECTOR vFrame ;
int nSpanV = pCrvV->GetCurveCount() ;
int nSplit = 8 * nSpanV ;
rmfGuide.GetFramesBySplit( nSplit, vFrame) ;
for ( int i = 0 ; i < nSpanV ; ++i) {
for ( int j = i==0 ? 0 : 1 ; j < nSplit + 1 ; ++j) {
ICurve* pNewSect = pCrvU->Clone() ;
pNewSect->ToGlob( vFrame[j]) ; // da sistemare se ho più curve ( la pGuide è una compo) e in base allo step di divisione!!!!!!!!! ///////
vpCrv.push_back( pNewSect) ;
vCrvSet.emplace_back( pNewSect) ;
}
}
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
//////VERSIONE con l'offset dei punti di controllo // richiede l'interpolazione dei punti
//
//// faccio l'offset della guida e poi riconverto i risultati in curve di bezier tramite interpolazione
//
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
//// porto la sezione nel sistema di riferimento del piano in cui giace
//pCrvU->ToLoc( frStart) ;
//for ( int i = 0 ; i < nSpanU ; ++i) {
// const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
// Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
// // faccio l'offset della guida nel punto di controllo della sezione
// OffsetCurve OffsCrv ;
// if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
// return nullptr ;
// PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
// pCrvV->AddCurve( OffsCrv.GetLongerCurve()) ;
// if ( IsNull( pCrvV))
// return nullptr ;
// pCrvV->Translate( ptCtrl.y * frStart.VersY()) ;
// PNTVECTOR vPnt ;
// int nOffCrvs = pCrvV->GetCurveCount() ;
// for ( int z = 0 ; z < nOffCrvs ; ++z) {
// Point3d ptCtrl ;
// if ( z == 0) {
// pCrvV->GetCurve(z)->GetStartPoint( ptCtrl) ;
// vPnt.push_back( ptCtrl) ;
// }
// pCrvV->GetCurve(z)->GetEndPoint( ptCtrl) ;
// vPnt.push_back( ptCtrl) ;
// }
// pCrvV.Set( CreateCurveComposite()) ;
// pCrvV->AddCurve( InterpolatePointSetWithBezier( vPnt, dLinTol)) ;
//
//
// nSpanV = pCrvV->GetCurveCount() ;
// pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; /// NON POSSO REINIZIALIZZARE LA SURF QUI!
// /// QUANDO INIZIO A INSERIRE I PUNTI DI CONTROLLO DEVO AVER DEFINITO nSpanV
//
//
// // aggiungo i punti di controllo alla superficie
// for ( int z = 0 ; z < nSpanV ; ++z) {
// const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ;
// if ( pCrvBez == nullptr)
// return nullptr ;
// for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) {
// Point3d ptCtrl = pCrvBez->GetControlPoint( k) ;
// pSurfBez->SetControlPoint( i * nDegU + j, z * nDegV + k, ptCtrl) ;
// }
// }
// }
//}
}
////// se richiesti caps e sezione chiusa e guida aperta /// in attesa della SurfCompo, al momento viene fatto nell'executor
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// // verifico che le due estremità siano chiuse e piatte
//}
// restituisco la superficie
return Release( pSurfBez) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
{
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
bool bRMF = vtAx.IsSmall() ;
// riferimento all'inizio della linea guida
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
Frame3d frStart ;
if ( bRMF) {
if ( ! frStart.Set( ptStart, vtStart))
return nullptr ;
}
else {
Vector3d vtAxX = vtAx ^ vtStart ;
if ( vtAxX.IsSmall()) {
vtAxX = FromUprightOrtho( vtAx) ;
vtAxX.Rotate( vtAx, 0, 1) ;
}
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
return nullptr ;
}
// capisco se la guida è una linea spezzata o una curva
bool bGuideIsPolyLine = false ;
switch( pGuide->GetType()) {
case CRV_COMPO : {
bGuideIsPolyLine = true ;
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
const ICurve* pCrv = pCC->GetCurve( i) ;
if ( pCrv->GetType() != CRV_LINE) {
if ( pCrv->GetType() == CRV_BEZIER) {
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
bGuideIsPolyLine = pCrvBez->IsALine() ;
}
else
bGuideIsPolyLine = false ;
}
}
break ;
}
case CRV_LINE :
bGuideIsPolyLine = true ;
break ;
case CRV_BEZIER : {
// controllo se i punti di controllo sono allineati
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
bGuideIsPolyLine = pCrvBez->IsALine() ;
break ;
}
default :
break ;
}
bool bRat = false ;
int nSpanV = 0 ;
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
if ( bGuideIsPolyLine) {
if ( pGuide->GetType() == CRV_LINE)
nSpanV = 1 ;
else if ( pGuide->GetType() == CRV_COMPO)
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
}
else {
// converto in bezier la guida ( grado 3, non razionale)
if ( pGuide->GetType() != CRV_BEZIER)
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
else {
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
if ( ! pGuideBez->IsRational())
pCrvV->AddCurve( pGuide->Clone()) ;
else
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
}
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
return nullptr ;
nSpanV = pCrvV->GetCurveCount() ;
}
// converto in bezier la sezione ( grado 3, non razionale)
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
if ( pSect->GetType() != CRV_BEZIER)
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
else {
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
if ( ! pSectBez->IsRational())
pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
else
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
}
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
return nullptr ;
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
FRAME3DVECTOR vFrames ;
if ( bRMF) {
RotationMinimizingFrame RMF ;
if ( bGuideIsPolyLine) {
if ( ! RMF.Set( pGuide, frStart) ||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
return nullptr ;
}
else {
if ( ! RMF.Set( pGuide, frStart) ||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ;
}
}
else {
RotationXplaneFrame RXF ;
if ( bGuideIsPolyLine) {
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
return nullptr ;
}
else {
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ;
}
}
// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
int nSpanU = int( pCrvU->GetCurveCount()) ;
int nDegU = 9 ; // debug
int nDegV = 3 ;
if ( bGuideIsPolyLine){
nDegV = 1 ;
// superficie swept
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
pCrvU->ToLoc( frStart) ;
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ;
pNewSect->ToGlob( vFrames[f]) ;
for ( int i = 0 ; i < nSpanU ; ++i) {
const ICurveBezier* pSubCrvBez = GetCurveBezier( pNewSect->GetCurve( i)) ;
for ( int j = 0 ; j < nDegU + 1 ; ++j) {
Point3d ptCtrl = pSubCrvBez->GetControlPoint( j) ;
pSurfBez->SetControlPoint( i * nDegU + j, f, ptCtrl) ;
}
}
}
return Release( pSurfBez) ;
}
else {
// porto la sezione nel sistema di riferimento del piano in cui giace
pCrvU->ToLoc( frStart) ;
ICURVEPOVECTOR vCrvSet ;
CICURVEPVECTOR vpCrv ;
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
ICurve* pNewSect = pCrvU->Clone() ;
// porto la curva nel frame corrente
pNewSect->ToGlob( vFrames[f]) ;
vpCrv.push_back( pNewSect) ;
vCrvSet.emplace_back( pNewSect) ;
}
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
}
//// se richiesti caps e sezione chiusa e guida aperta
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// // aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
// return nullptr ;
// pSci->ToGlob( vFrames.front()) ;
// // aggiungo
// StmFts.AddSurfTriMesh( *pSci) ;
// // aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
// return nullptr ;
// pSce->ToGlob( vFrames.back()) ;
// // inverto
// pSce->Invert() ;
// // aggiungo
// StmFts.AddSurfTriMesh( *pSce) ;
//}
//// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
//double dVol ;
//if ( pSTM->GetVolume( dVol) && dVol < 0)
// pSTM->Invert() ;
// restituisco la superficie
return nullptr ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
{
// verifica parametri
if ( &ptP == nullptr || pCurve == nullptr)
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
{
// verifico che le curve siano valide
for ( int i = 0 ; i < int( vCrv.size()) ; ++i) {
if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
return nullptr ;
}
// se ho solo due curve allora faccio la rigata
if ( vCrv.size() == 2)
return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ;
//trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
ICURVEPOVECTOR vCrvBez ;
for ( int c = 0 ; c < int( vCrv.size()) ; ++c){
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
if ( vCrv[c]->GetType() != CRV_BEZIER )
pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ;
else
pCC->AddCurve( vCrv[c]->Clone()) ;
if ( IsNull( pCC) || ! pCC->IsValid())
return nullptr ;
vCrvBez.emplace_back( Release( pCC)) ;
}
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateBySetOfCurves( vCrvBez, true))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}