EgtGeomKernel :

- aggiunta la funzione IsLine per le bezier
- aggiunta funzione SurfBzSweptInPlane
- aggiunta la funzione InterpolatePointSetWithBezier.
This commit is contained in:
Daniele Bariletti
2024-09-17 17:19:20 +02:00
parent 93c87ee720
commit bfc09d135c
4 changed files with 544 additions and 280 deletions
+153 -9
View File
@@ -25,9 +25,13 @@
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Extern/Eigen/Dense"
using namespace std ;
static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ;
static bool CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis) ;
//----------------------------------------------------------------------------
bool
IsClosed( const ICurve& crvC)
@@ -420,12 +424,14 @@ CurveToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
switch ( pCrv->GetType()) {
case CRV_LINE :{
const ICurveLine* pCrvLine = static_cast<const ICurveLine*>( pCrv) ;
pBezierForm.Set( LineToBezierCurve( pCrvLine, nDeg, bMakeRatOrNot)) ;
int nDegWanted = nDeg == -1 ? 3 : nDeg ;
pBezierForm.Set( LineToBezierCurve( pCrvLine, nDegWanted, bMakeRatOrNot)) ;
break ;
}
case CRV_ARC : {
const ICurveArc* pCrvArc = static_cast<const ICurveArc*>( pCrv) ;
pBezierForm.Set( ArcToBezierCurve( pCrvArc, nDeg, bMakeRatOrNot)) ;
int nDegWanted = nDeg == -1 ? 3 : nDeg ;
pBezierForm.Set( ArcToBezierCurve( pCrvArc, nDegWanted, bMakeRatOrNot)) ;
break ;
}
case CRV_COMPO : {
@@ -557,12 +563,17 @@ CompositeToBezierCurve( const ICurveComposite* pCC, int nDeg, bool bMakeRatOrNot
ICurve*
EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, double dTol)
{
if( nDeg < 3)
// se nDeg == -1 allora viene mantenuto il grado della curva originale
if( nDeg == 2 || nDeg == 1)
return nullptr ;
// dovrei restituire una bezier di grado 2, razionale per poter essere uniforme con le altre curve trasmorate in bezier
PtrOwner<ICurveBezier> pCrvNew( pCrvBezier->Clone()) ;
int nDegCurr = pCrvNew->GetDegree() ;
bool bRat = pCrvNew->IsRational() ;
int nDegWanted = nDeg == -1 ? nDegCurr : nDeg ;
if( ! bMakeRatOrNot) {
if( ! pCrvNew->MakeNonRational( 10 * EPS_SMALL)) {
if( ! pCrvNew->MakeNonRational( dTol)) {
// se ho fallito la conversione diretta in curva non razionale allora la spezzo in bezier cubiche
PtrOwner<ICurveComposite> pBezCubics( CreateCurveComposite()) ;
pBezCubics->AddCurve( ApproxBezierWithCubics(pCrvBezier, dTol)) ;
@@ -570,17 +581,15 @@ EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, d
return nullptr ;
// adatto ogni sottocurva cubica
PtrOwner<ICurveComposite> pCCEdited( CreateCurveComposite()) ;
for ( int i = 0 ; i < pBezCubics->GetCurveCount() ; ++i) {
if( ! pCCEdited->AddCurve( EditBezierCurve( GetCurveBezier( pBezCubics->GetCurve( i)), nDeg, bMakeRatOrNot, dTol)) )
if( ! pCCEdited->AddCurve( EditBezierCurve( GetCurveBezier( pBezCubics->GetCurve( i)), nDegWanted, bMakeRatOrNot, dTol)) )
return nullptr ;
}
return Release( pCCEdited) ;
}
}
int nDegCurr = pCrvNew->GetDegree() ;
bool bRat = pCrvNew->IsRational() ;
// se la curva è già nella forma giusta la restituisco
int nDegWanted = nDeg ;
if ( nDegCurr == nDegWanted && ( ( ! bRat && ! bMakeRatOrNot) || (bRat && bMakeRatOrNot)))
return Release( pCrvNew) ;
// sennò mi porto al grado giusto
@@ -1022,6 +1031,141 @@ ApproxCurveWithBezier( const ICurve*, double dTol)
return Release( pCC) ;
}
//----------------------------------------------------------------------------
ICurve*
InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dTol)
{
PtrOwner<ICurve> pCrvInt ;
// pag 364 del Piegl
// scelgo il parametro associato ad ogni punto in modo che rispecchi la distanza tra i punti
int nPoints = vPnt.size() ;
if( nPoints < 4)
return nullptr ;
int nDeg = 3 ;
DBLVECTOR vLen ;
double dLenTot = 0 ;
for ( int i = 0 ; i < int( nPoints -1) ; ++i) {
double dLen = Dist(vPnt[i], vPnt[i+1]) ;
vLen.push_back( dLen) ;
dLenTot += dLen ;
}
DBLVECTOR vPntParam ;
vPntParam.resize( nPoints) ;
vPntParam[0] = 0 ;
vPntParam.back() = 1 ;
for ( int i = 1 ; i < int( nPoints - 1) ; ++i)
vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ;
DBLVECTOR vKnots ;
vKnots.resize( nPoints + nDeg - 1) ;
for ( int i = 0 ; i < nDeg ; ++i) {
vKnots[i] = 0 ;
vKnots.end()[-i-1] = 1 ;
}
for ( int i = nDeg ; i < nPoints - 1 ; ++i) {
double dKnot = 0 ;
for ( int j = i ; j < i + nDeg ; ++j)
dKnot += vPntParam[j - nDeg] ;
dKnot /= nDeg ;
vKnots[i] = dKnot ;
}
Eigen::MatrixXd mA( nPoints, nPoints) ;
mA.fill( 0) ;
for ( int i = 0 ; i < nPoints ; ++i) {
int nSpan = 0 ; FindSpan(vPntParam[i], nDeg, vKnots, nSpan) ;
if ( i == 0)
mA.row(0).col(0) << 1 ;
else if ( i == nPoints - 1)
mA.row(i).col(nPoints - 1) << 1 ;
else {
DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ;
CalcBasisFunc( vPntParam[i], nDeg, vKnots, vBasis) ;
for( int j = nSpan - nDeg ; j < nSpan ; ++j)
mA.row(i).col(j) << vBasis[j - nSpan + nDeg] ;
}
}
int nDim = 3 ;
Eigen::MatrixXd mb ; mb.resize( nPoints, nDim) ;
Eigen::MatrixXd mX = mA.fullPivLu().solve(mb) ;
PNTVECTOR vPntCtrl ;
for ( int i = 0 ; i < nPoints ; ++i)
vPntCtrl.emplace_back( mX(i,0), mX(i,1), mX(i,2)) ;
CNurbsData cNurbs ;
cNurbs.nDeg = nDeg ;
cNurbs.vCP = vPntCtrl ;
cNurbs.vU = vKnots ;
cNurbs.bRat = false ;
pCrvInt.Set( NurbsToBezierCurve( cNurbs)) ;
return Release( pCrvInt) ;
}
//----------------------------------------------------------------------------
static bool
FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
{
if( dU < 0)
return false ;
else if( dU < EPS_ZERO) {
nSpan = nDeg ;
return true ;
}
// trovo a quale span appartiene il parametro dU
int nKnots = int( vKnots.size()) ;
if( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
nSpan = nKnots - 1 ;
return true ;
}
int nLow = nDeg ;
int nHigh = nKnots ;
int nMid = ( nLow + nHigh) / 2 ;
while ( dU < vKnots[nMid] || dU > vKnots[nMid + 1] ) {
if ( dU < vKnots[nMid])
nHigh = nMid ;
else
nLow = nMid ;
nMid = ( nLow + nHigh) / 2 ;
if( nMid == nDeg)
break ;
}
nSpan = nMid ;
return true ;
}
//----------------------------------------------------------------------------
static bool
CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
{
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
if( vBasis.size() != nDeg + 1)
return false ;
int nSpan = 0 ;
FindSpan( dU, nDeg, vKnots, nSpan) ;
vBasis[0] = 1 ;
DBLVECTOR vLeft ; vLeft.resize( nDeg + 1) ;
DBLVECTOR vRight ; vRight.resize( nDeg + 1) ;
for ( int j = 1 ; j <= nDeg ; ++j) {
vLeft[j] = dU - vKnots[nSpan + 1 -j] ;
vRight[j] = vKnots[nSpan + j] - dU ;
double dSaved = 0 ;
for ( int r = 0 ; r < j ; ++r) {
double dTemp = vBasis[r] / ( vRight[r+1] + vLeft[j-r]) ;
vBasis[r] = dSaved + vRight[r+1] * dTemp ;
dSaved = vLeft[j-r] * dTemp ;
}
vBasis[j] = dSaved ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
CalcBezierApproxError( const ICurveBezier* pCrvOri, const ICurveBezier* pCrvNew, double& dErr, int nPoints)
+16
View File
@@ -2367,3 +2367,19 @@ CurveBezier::MakeNonRational( double dTol)
return bOk ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::IsALine( void) const
{
Point3d ptStart ; GetStartPoint( ptStart) ;
Point3d ptEnd ; GetEndPoint( ptEnd) ;
for ( int i = 1 ; i < m_nDeg ; ++i) {
Point3d ptCtrl = GetControlPoint( i) ;
DistPointLine dpl( ptCtrl, ptStart, ptEnd) ;
double dDist = 0 ; dpl.GetDist( dDist) ;
if( dDist > EPS_SMALL)
return false ;
}
return true ;
}
+1
View File
@@ -152,6 +152,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool MakeRational( void) override ;
bool MakeRationalStandardForm( void) override ;
bool MakeNonRational( double dTol) override ;
bool IsALine( void) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+374 -271
View File
@@ -20,6 +20,7 @@
#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"
@@ -49,8 +50,7 @@ GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol)
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByFlatContour( PL))
return nullptr ;
//// salvo tolleranza lineare usata
//pSTM->SetLinearTolerance( dLinTol) ;
// restituisco la superficie
return Release( pSbz) ;
}
@@ -205,12 +205,6 @@ GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3
//PolyLine PL ;
//if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
//// calcolo lo step di rotazione
//double dMaxRad = 0 ;
//if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL)
// return nullptr ;
//double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ;
//// se richiesta chiusura degli estremi
//if ( bCapEnds && ! PL.IsClosed()) { // serve la SURFCOMPO
@@ -255,8 +249,7 @@ GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3
double dVol ;
if ( pSbz->GetVolume( dVol) && dVol < 0)
pSbz->Invert() ;
//// salvo tolleranza lineare usata
//pSbz->SetLinearTolerance( dLinTol) ;
// restituisco la superficie
return Release( pSbz) ;
}
@@ -276,17 +269,6 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
//// calcolo lo step di rotazione
//double dMaxRad = 0 ;
//if ( ! PL.GetMaxDistanceFromLine( ptAx, vtAx, 1, dMaxRad, false) || dMaxRad < EPS_SMALL)
// return nullptr ;
//double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ;
//// se superficie rototraslata, necessari limiti sulla lunghezza dei segmenti
//if ( abs( dAngRotDeg) > EPS_ANG_SMALL && abs( dMove) > EPS_SMALL){
// double dLenMax = 2.5 * abs( dMove * dStepRotDeg / dAngRotDeg) ;
// if ( ! PL.AdjustForMaxSegmentLen( dLenMax))
// return nullptr ;
//}
// creo e setto la superficie bezier
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
@@ -322,8 +304,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector
double dVol ;
if ( pSbz->GetVolume( dVol) && dVol < 0)
pSbz->Invert() ;
//// salvo tolleranza lineare usata
//pSTM->SetLinearTolerance( dLinTol) ;
// restituisco la superficie
return Release( pSbz) ;
}
@@ -653,254 +634,376 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector
// else
// return GetSurfBezierBeveledRectSwept( dDimH, dDimV, dBevelH, dBevelV, pGuide, nCapType, dLinTol) ;
//}
//
////-------------------------------------------------------------------------------
//static ISurfBezier*
//GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
//{
// // determino se la sezione è chiusa
// bool bSectClosed = pSect->IsClosed() ;
// // determino se la guida è chiusa
// bool bGuideClosed = pGuide->IsClosed() ;
//
// // riferimento all'inizio della linea guida
// Frame3d frStart ;
// Point3d ptStart ;
// pGuide->GetStartPoint( ptStart) ;
// Vector3d vtStart ;
// pGuide->GetStartDir( vtStart) ;
// frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
//
// // calcolo la polilinea che approssima la sezione
// PolyLine PL ;
// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
//
// // porto la sezione in questo riferimento e ve la appiattisco
// if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
// return nullptr ;
//
// // preparo collettore delle superfici componenti
// StmFromTriangleSoup StmFts ;
// if ( ! StmFts.Start())
// return nullptr ;
//
// // superficie swept
// PtrOwner<ICurve> pPrevCrv ;
// Point3d ptP ;
// bool bPoint = PL.GetFirstPoint( ptP) ;
// while ( bPoint) {
// // nuova curva ( definita dall'Offset )
// OffsetCurve OffsCrv ;
// if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
// return nullptr ;
// PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
// if ( IsNull( pCurrCrv))
// return nullptr ;
// pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
// // se esiste la curva precedente, costruisco la rigata ( di tipo minima distanza)
// if ( ! IsNull( pPrevCrv)) {
// PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
// if ( IsNull( pSr))
// return nullptr ;
// // inserisco nel collettore
// StmFts.AddSurfTriMesh( *pSr) ;
// }
// // salvo la curva come prossima precedente
// pPrevCrv.Set( pCurrCrv) ;
// // prossimo punto
// bPoint = PL.GetNextPoint( ptP) ;
// }
//
// // recupero la supeficie risultante
// if ( ! StmFts.End())
// return nullptr ;
// PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
// if ( IsNull( pSTM))
// return nullptr ;
// // salvo tolleranza lineare usata
// pSTM->SetLinearTolerance( dLinTol) ;
//
// // se richiesti caps e sezione chiusa e guida aperta
// if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// // verifico che le due estremità siano chiuse e piatte
// POLYLINEVECTOR vPL ;
// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
// return nullptr ;
// Plane3d plEnds ; double dArea ;
// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
// return nullptr ;
// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
// return nullptr ;
// // aggiungo il cap sull'inizio
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
// return nullptr ;
// pSci->ToGlob( frStart) ;
// // unisco
// pSTM->DoSewing( *pSci) ;
// // riferimento alla fine della linea guida
// Frame3d frEnd ;
// Point3d ptEnd ;
// pGuide->GetEndPoint( ptEnd) ;
// Vector3d vtEnd ;
// pGuide->GetEndDir( vtEnd) ;
// frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ;
// // aggiungo il cap sulla fine
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
// return nullptr ;
// pSce->Invert() ;
// pSce->ToGlob( frEnd) ;
// // unisco
// pSTM->DoSewing( *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 Release( pSTM) ;
//}
//
////-------------------------------------------------------------------------------
//static 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 se la sezione è chiusa
// bool bSectClosed = pSect->IsClosed() ;
// // determino se la guida è chiusa
// bool bGuideClosed = pGuide->IsClosed() ;
// // 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 ;
// }
//
// // calcolo la polilinea che approssima la sezione
// PolyLine PL ;
// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
//
// // recupero la sezione dalla PolyLine approssimata come Curva
// PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
// if ( IsNull( pSecLocApprox) ||
// ! pSecLocApprox->FromPolyLine( PL) ||
// ! pSecLocApprox->IsValid())
// return nullptr ;
//
// // porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
// PL.ToLoc( frStart) ;
// pSecLocApprox->ToLoc( frStart) ;
//
// // calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
// FRAME3DVECTOR vFrames ;
// if ( bRMF) {
// RotationMinimizingFrame RMF ;
// if ( ! RMF.Set( pGuide, frStart) ||
// ! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
// return nullptr ;
// }
// else {
// RotationXplaneFrame RXF ;
// if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
// ! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
// return nullptr ;
// }
//
// // preparo collettore delle superfici componenti
// StmFromTriangleSoup StmFts ;
// if ( ! StmFts.Start())
// return nullptr ;
//
// // per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
// for ( int i = 0 ; i < int( vFrames.size()) - 1 ; ++ i) {
//
// // definisco la sezione allo step corrente
// PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
// if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
// return nullptr ;
//
// // considero la sezione ( in locale ) come vista dal globale
// if ( ! pSecCurr->ToGlob( vFrames[i]))
// return nullptr ;
//
// // definisco la sezione allo step successivo
// PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
// if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
// return nullptr ;
//
// // considero la sezione ( in locale ) come vista dal globale
// if ( ! pSecSucc->ToGlob( vFrames[i+1]))
// return nullptr ;
//
// // creo la rigata tra queste due sezioni
// PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
// if ( IsNull( pSr) || ! pSr->IsValid())
// return nullptr ;
// // la inverto
// pSr->Invert() ;
// // inserisco la superficie nel collettore
// StmFts.AddSurfTriMesh( *pSr) ;
// }
//
// // 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) ;
// }
//
// // recupero la supeficie risultante
// if ( ! StmFts.End())
// return nullptr ;
// PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
// if ( IsNull( pSTM))
// return nullptr ;
// // salvo tolleranza lineare usata
// pSTM->SetLinearTolerance( dLinTol) ;
//
// // 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 Release( pSTM) ;
//}
//
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
{
// determino se la sezione è chiusa
bool bSectClosed = pSect->IsClosed() ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// 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) ;
if( ! pSectBez->IsRational())
pCrvU->AddCurve( pSect->Clone()) ;
else
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 = 9 ;
// superficie swept
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
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
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()) ;
if( pCrvV->GetCurveCount() != nSpanV)
return nullptr ;
// aggiungo i punti di controllo alla superficie
for ( int z = 0 ; z < nSpanV ; ++z) {
const ICurveLine* pCL = GetCurveLine( pCrvV->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 {
// 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 ; ++j) {
ICurve* pNewSect = pCrvU->Clone() ;
pNewSect->ToGlob( vFrame[j]) ; // da sistemare se ho più curve 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
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 se la sezione è chiusa
//bool bSectClosed = pSect->IsClosed() ;
//// determino se la guida è chiusa
//bool bGuideClosed = pGuide->IsClosed() ;
//// 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 ;
//}
//// calcolo la polilinea che approssima la sezione
//PolyLine PL ;
//if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
// return nullptr ;
//// recupero la sezione dalla PolyLine approssimata come Curva
//PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
//if ( IsNull( pSecLocApprox) ||
// ! pSecLocApprox->FromPolyLine( PL) ||
// ! pSecLocApprox->IsValid())
// return nullptr ;
//// porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
//PL.ToLoc( frStart) ;
//pSecLocApprox->ToLoc( frStart) ;
//// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
//FRAME3DVECTOR vFrames ;
//if ( bRMF) {
// RotationMinimizingFrame RMF ;
// if ( ! RMF.Set( pGuide, frStart) ||
// ! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
// return nullptr ;
//}
//else {
// RotationXplaneFrame RXF ;
// if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
// ! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
// return nullptr ;
//}
//// preparo collettore delle superfici componenti
//StmFromTriangleSoup StmFts ;
//if ( ! StmFts.Start())
// return nullptr ;
//// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
//for ( int i = 0 ; i < int( vFrames.size()) - 1 ; ++ i) {
// // definisco la sezione allo step corrente
// PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
// if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
// return nullptr ;
// // considero la sezione ( in locale ) come vista dal globale
// if ( ! pSecCurr->ToGlob( vFrames[i]))
// return nullptr ;
// // definisco la sezione allo step successivo
// PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
// if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
// return nullptr ;
// // considero la sezione ( in locale ) come vista dal globale
// if ( ! pSecSucc->ToGlob( vFrames[i+1]))
// return nullptr ;
// // creo la rigata tra queste due sezioni
// PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
// if ( IsNull( pSr) || ! pSr->IsValid())
// return nullptr ;
// // la inverto
// pSr->Invert() ;
// // inserisco la superficie nel collettore
// StmFts.AddSurfTriMesh( *pSr) ;
//}
//// 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) ;
//}
//// recupero la supeficie risultante
//if ( ! StmFts.End())
// return nullptr ;
//PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
//if ( IsNull( pSTM))
// return nullptr ;
//// salvo tolleranza lineare usata
//pSTM->SetLinearTolerance( dLinTol) ;
//// 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*
//GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx,