EgtGeomKernel :
- Swept con o senza caps mediante RMF - inizio stesura codice per frame statico - migliorie varie.
This commit is contained in:
+155
-107
@@ -15,29 +15,11 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const double dStep)
|
||||
RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start)
|
||||
{
|
||||
// assegno i parametri
|
||||
m_pCrv = pCrv->Clone() ;
|
||||
m_Frame0 = fr_Start ;
|
||||
m_dStep = dStep ;
|
||||
}
|
||||
|
||||
RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const int nStep)
|
||||
{
|
||||
// assegno i parametri
|
||||
if ( nStep < 1) // devo averne almeno 1, altrimenti è automaticamente il fr_Start
|
||||
return ;
|
||||
|
||||
// recupero la lunghezza della curva
|
||||
double dLen = 0 ;
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid() || ! pCrv->GetLength( dLen))
|
||||
return ;
|
||||
|
||||
m_pCrv = pCrv->Clone() ;
|
||||
m_Frame0 = fr_Start ;
|
||||
m_dStep = dLen / nStep ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -46,6 +28,21 @@ RotationMinimizeFrame::~RotationMinimizeFrame( void)
|
||||
Clear() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::Clear( void)
|
||||
{
|
||||
// pulizia della curva
|
||||
if ( m_pCrv != nullptr)
|
||||
delete m_pCrv ;
|
||||
m_pCrv = nullptr ;
|
||||
|
||||
// reset del frame di partenza
|
||||
m_Frame0.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::IsValid()
|
||||
@@ -58,14 +55,6 @@ RotationMinimizeFrame::IsValid()
|
||||
if ( ! m_Frame0.IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sul parametro di discretizzazione
|
||||
if ( m_dStep < EPS_SMALL)
|
||||
return false ;
|
||||
// controllo che il passo non sia superiore alla lunghezza della curva
|
||||
double dLen = 0. ;
|
||||
if ( ! m_pCrv->GetLength( dLen) || m_dStep > dLen)
|
||||
return false ;
|
||||
|
||||
// controllo che l'origine del frame sia sulla curva e che l'asse Z sia tangente alla curva
|
||||
Point3d ptS ;
|
||||
Vector3d vtZ ;
|
||||
@@ -81,38 +70,85 @@ RotationMinimizeFrame::IsValid()
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::Clear( void)
|
||||
RotationMinimizeFrame::GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext)
|
||||
{
|
||||
// pulizia della curva
|
||||
if ( m_pCrv != nullptr)
|
||||
delete m_pCrv ;
|
||||
m_pCrv = nullptr ;
|
||||
|
||||
// reset del frame di partenza
|
||||
m_Frame0.Reset() ;
|
||||
/*
|
||||
Double Reflection
|
||||
Computation of Rotation Minimizing Frame in Computer Graphics
|
||||
Wenping Wang Bert Juttler Dayue Zheng Yang Liu
|
||||
*/
|
||||
|
||||
// reset dell'intervallo di discretizzazione
|
||||
m_dStep = 0. ;
|
||||
// ricavo i parametri dal frame
|
||||
if ( ! frAct.IsValid())
|
||||
return false ;
|
||||
|
||||
// origine del frame e versori ( ptAct, [ vt_r, vt_s, vt_t])
|
||||
Point3d ptCurr = frAct.Orig() ;
|
||||
Vector3d vt_r = frAct.VersX() ;
|
||||
Vector3d vt_s = frAct.VersY() ;
|
||||
Vector3d vt_t = frAct.VersZ() ;
|
||||
|
||||
double dUNext ; // parametro sulla curva nello step successivo
|
||||
Point3d ptNext ; // punto sulla curva allo step successivo
|
||||
|
||||
// parametro (i+1)-esimo sulla curva
|
||||
if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext))
|
||||
return false ;
|
||||
// punto (i+1)-esimo sulla curva e suo vettore tangente
|
||||
Vector3d vt_t_next ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dUNext, ICurve::FROM_MINUS, ptNext, &vt_t_next) ||
|
||||
! vt_t_next.IsValid() || ! vt_t_next.Normalize()) // versore tangente
|
||||
return false ;
|
||||
// controllo per casi degeneri
|
||||
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
|
||||
abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste il piano R2
|
||||
return false ;
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR1_norm = ptNext - ptCurr ;
|
||||
if ( ! vR1_norm.IsValid())
|
||||
return false ;
|
||||
// parametro di riflessione per R1
|
||||
double dPar1 = vR1_norm * vR1_norm ;
|
||||
// riflessione rispetto al piano R1 ( sistema sinistrorso L )
|
||||
Vector3d vt_r_L = vt_r - ( 2 / dPar1) * ( vR1_norm * vt_r) * vR1_norm ;
|
||||
Vector3d vt_t_L = vt_t - ( 2 / dPar1) * ( vR1_norm * vt_t) * vR1_norm ;
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR2_norm = vt_t_next - vt_t_L ;
|
||||
if ( ! vR2_norm.IsValid())
|
||||
return false ;
|
||||
// parametro di riflessione per R2
|
||||
double dPar2 = vR2_norm * vR2_norm ;
|
||||
// versore r del nuovo frame
|
||||
Vector3d vt_r_next = vt_r_L - ( 2 / dPar2) * ( vR2_norm * vt_r_L) * vR2_norm ;
|
||||
// versore t del nuovo frame
|
||||
Vector3d vt_s_next = vt_t_next ^ vt_r_next ;
|
||||
// imposto il nuovo frame
|
||||
frNext.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ;
|
||||
if ( ! frNext.IsValid()) { // il frame potrebbe non essere nelle tolleranze...
|
||||
// ... sistemo ricavando il versore "s" mediante "t" ed "r" ...
|
||||
frNext.Set( ptNext, vt_t_next, vt_r_next) ;
|
||||
if ( ! frNext.IsValid())
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrames)
|
||||
RotationMinimizeFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform)
|
||||
{
|
||||
// controllo sullo step
|
||||
dStep = max( 10 * EPS_SMALL, dStep) ;
|
||||
|
||||
// controllo validità
|
||||
if ( ! IsValid()) {
|
||||
Clear() ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
/*
|
||||
Double Reflection
|
||||
Computation of Rotation Minimizing Frame in Computer Graphics
|
||||
Wenping Wang Bert Juttler Dayue Zheng Yang Liu
|
||||
*/
|
||||
|
||||
// calcolo lunghezza della curva
|
||||
double dLen = 0. ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
@@ -122,80 +158,92 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrames)
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
|
||||
// ricavo il numero degli step
|
||||
int nStep = ceil( dLen / m_dStep) ;
|
||||
int nStep = int( ceil( dLen / dStep)) ;
|
||||
if ( nStep == 0) // se non ho step allora serve sono il frame iniziale
|
||||
return true ;
|
||||
|
||||
// variabili di utilizzo
|
||||
double dLenCurr = 0 ; // lunghezza della curva allo step i-esimo
|
||||
double dLenNext ; // lunghezza della curva allo step (i+1)-esimo
|
||||
double dUCurr = 0. ; // parametro sulla curva allo step i-esimo
|
||||
double dUNext ; // parametro sulla curva allo step (i+1)-esimo
|
||||
Point3d ptCurr ; // punto sulla curva allo step i-esimo
|
||||
if ( ! m_pCrv->GetStartPoint( ptCurr))
|
||||
return false ;
|
||||
Point3d ptNext ; // punto sulla curva allo step (i+1)-esimo
|
||||
// lunghezza della curva identificata dal punto successivo
|
||||
double dLenNext ;
|
||||
|
||||
// definizione dei versori "r","s","t"
|
||||
Vector3d vt_r = m_Frame0.VersX() ;
|
||||
Vector3d vt_s = m_Frame0.VersY() ;
|
||||
Vector3d vt_t = m_Frame0.VersZ() ;
|
||||
|
||||
// ricavo la lunghezza dello step di campionamento reale
|
||||
double dStep_real = dLen / nStep ;
|
||||
// step corrente
|
||||
double dMyStep = dStep ;
|
||||
if ( bUniform)
|
||||
dMyStep = dLen / nStep ;
|
||||
|
||||
// ciclo sugli step in cui la curva è suddivisa
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
// ricavo la lunghezza della curva relativo allo step (i+1)-esimo
|
||||
dLenNext = min( dLen - EPS_SMALL, ( i + 1) * dStep_real) ;
|
||||
// parametro (i+1)-esimo sulla curva
|
||||
if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext))
|
||||
dLenNext = min( dLen - EPS_SMALL, ( i + 1) * dMyStep) ;
|
||||
// ricavo il frame alla lunghezza calcolata
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtLength( vRMFrames[i], dLenNext, frNext))
|
||||
return false ;
|
||||
// punto (i+1)-esimo sulla curva e suo vettore tangente
|
||||
Vector3d vt_t_next ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dUNext, ICurve::FROM_MINUS, ptNext, &vt_t_next) ||
|
||||
! vt_t_next.IsValid() || ! vt_t_next.Normalize()) // versore tangente
|
||||
return false ;
|
||||
// controllo per casi degeneri
|
||||
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
|
||||
abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste il piano R2
|
||||
return false ;
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR1_norm = ptNext - ptCurr ;
|
||||
if ( ! vR1_norm.IsValid())
|
||||
return false ;
|
||||
// parametro di riflessione per R1
|
||||
double dPar1 = vR1_norm * vR1_norm ;
|
||||
// riflessione rispetto al piano R1 ( sistema sinistrorso L )
|
||||
Vector3d vt_r_L = vt_r - ( 2 / dPar1) * ( vR1_norm * vt_r) * vR1_norm ;
|
||||
Vector3d vt_t_L = vt_t - ( 2 / dPar1) * ( vR1_norm * vt_t) * vR1_norm ;
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR2_norm = vt_t_next - vt_t_L ;
|
||||
if ( ! vR2_norm.IsValid())
|
||||
return false ;
|
||||
// parametro di riflessione per R2
|
||||
double dPar2 = vR2_norm * vR2_norm ;
|
||||
// versore r del nuovo frame (i+1)-esimo
|
||||
Vector3d vt_r_next = vt_r_L - ( 2 / dPar2) * ( vR2_norm * vt_r_L) * vR2_norm ;
|
||||
// versore t del nuovo frame (i+1)-esimo
|
||||
Vector3d vt_s_next = vt_t_next ^ vt_r_next ;
|
||||
// creazione del nuovo frame (i+1)-esimo
|
||||
Frame3d RMFrame_next ;
|
||||
RMFrame_next.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ;
|
||||
if ( ! RMFrame_next.IsValid()) { // il frame potrebbe non essere nelle tolleranze...
|
||||
// ... sistemo ricavando il versore "s" mediante "t" ed "r" ...
|
||||
RMFrame_next.Set( ptNext, vt_t_next, vt_r_next) ;
|
||||
if ( ! RMFrame_next.IsValid())
|
||||
return false ;
|
||||
}
|
||||
// aggiornamento vettore dei frame
|
||||
vRMFrames.push_back( RMFrame_next) ;
|
||||
// aggiornamento dei parametri
|
||||
dLenCurr = dLenNext ;
|
||||
dUCurr = dUNext ;
|
||||
ptCurr = ptNext ;
|
||||
vt_r = vt_r_next ;
|
||||
vt_t = vt_t_next ;
|
||||
vRMFrames.push_back( frNext) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals)
|
||||
{
|
||||
// controllo sul numero di intervalli
|
||||
nIntervals = max( 1, nIntervals) ;
|
||||
|
||||
// ricavo lo step associato
|
||||
double dLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
// ricavo lo step associato
|
||||
double dStep = dLen / nIntervals ;
|
||||
|
||||
return GetFramesByStep( vRMFrames, dStep) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol)
|
||||
{
|
||||
// controllo sulla tolleranza
|
||||
dTol = max( EPS_SMALL, dTol) ;
|
||||
|
||||
// controllo validità
|
||||
if ( ! IsValid()) {
|
||||
Clear() ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// ricavo la PolyLine associata alla curva mediante tale tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! m_pCrv->ApproxWithLines( dTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return false ;
|
||||
|
||||
// devo calcolare il RMF su ogni punto ricavato dall'approssimazione
|
||||
Point3d ptCurr ;
|
||||
bool bPoint = PL.GetFirstPoint( ptCurr) ;
|
||||
bool bFirst = true ;
|
||||
while ( bPoint) {
|
||||
if ( bFirst) {
|
||||
// in prima posizione viene inserito il frame iniziale
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
bFirst = false ;
|
||||
}
|
||||
else {
|
||||
// ricavo la lunghezza della curva al punto corrente
|
||||
double dLen = 0. ;
|
||||
if ( ! m_pCrv->GetLengthAtPoint( ptCurr, dLen))
|
||||
return false ;
|
||||
// ricavo il Frame associato a tale lunghezza
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtLength( vRMFrames.back(), dLen, frNext))
|
||||
return false ;
|
||||
vRMFrames.emplace_back( frNext) ;
|
||||
}
|
||||
// passo al punto successivo
|
||||
bPoint = PL.GetNextPoint( ptCurr) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
@@ -24,20 +24,21 @@ typedef std::vector<Frame3d> FRAME3DVECTOR ;
|
||||
class RotationMinimizeFrame
|
||||
{
|
||||
public :
|
||||
RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const double dStep) ;
|
||||
RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const int nStep) ;
|
||||
RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start) ;
|
||||
~RotationMinimizeFrame( void) ;
|
||||
|
||||
public :
|
||||
bool GetFrames( FRAME3DVECTOR& vRMFrams) ;
|
||||
bool GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform = false) ;
|
||||
bool GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals) ;
|
||||
bool GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol) ;
|
||||
|
||||
private :
|
||||
bool Clear( void) ;
|
||||
bool IsValid( void) ;
|
||||
bool GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext) ;
|
||||
|
||||
private :
|
||||
ICurve* m_pCrv ; // curva per il calcolo del rotation minimize frame
|
||||
Frame3d m_Frame0 ; // frame iniziale della curva
|
||||
double m_dStep ; // passo di discretizzazione
|
||||
} ;
|
||||
|
||||
|
||||
+226
-97
@@ -665,109 +665,246 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
bool bSectClosed = PL.IsClosed() ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// ricavo punto e versore iniziale
|
||||
Point3d ptStart ; pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ; pGuide->GetStartDir( vtStart) ;
|
||||
// creo il riferimento iniziale
|
||||
Frame3d frStart ;
|
||||
// inizializzo la superficie
|
||||
// definisco la superficie da restituire ( definendo la sua tolleranza )
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
// salvo tolleranza lineare usata
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
// calcolo punto e versore tangente iniziale
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
// inizializzazione del frame iniziale
|
||||
Frame3d frStart ;
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
Vector3d vtNorm ;
|
||||
bool bIsFlat = pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL) ;
|
||||
// inizializzo frame iniziale e finale nel caso di Rotation Minimize Frame per guide non piane
|
||||
Frame3d frRMF_Start, frRMF_End ;
|
||||
if ( bIsFlat) {
|
||||
// definisco il frame iniziale
|
||||
vtNorm = plGuide.GetVersN() ;
|
||||
frStart.Set( ptStart, - vtStart, vtStart ^ vtNorm) ;
|
||||
// porto la sezione in questo riferimento e appiattisco
|
||||
if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
|
||||
return nullptr ;
|
||||
// superficie swept
|
||||
PtrOwner<ICurve> pPrevCrv ;
|
||||
Point3d ptP ;
|
||||
bool bPoint = PL.GetFirstPoint( ptP) ;
|
||||
while ( bPoint) {
|
||||
// nuova curva
|
||||
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 ;
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
// salvo la curva come prossima precedente
|
||||
pPrevCrv.Set( pCurrCrv) ;
|
||||
// prossimo punto
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// definisco il frame iniziale
|
||||
frStart.Set( ptStart, vtStart) ;
|
||||
// porto la sezione in questo riferimento
|
||||
if ( ! PL.ToLoc( frStart))
|
||||
return nullptr ;
|
||||
double dStep = 10 ;
|
||||
// calcolo il vettore di Frame campionati lungo la curva
|
||||
RotationMinimizeFrame RMF( pGuide, frStart, dStep) ;
|
||||
FRAME3DVECTOR vRMF ;
|
||||
if ( ! RMF.GetFrames( vRMF) || vRMF.empty())
|
||||
return nullptr ;
|
||||
// recupero la sezione come curve dalla PolyLine
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) {
|
||||
|
||||
/*
|
||||
La guida non è piana, l'estrusione può essere definita mediante :
|
||||
( 1) un versore statico
|
||||
( 2) mediante l'algoritmo del Rotation Minimize Frame
|
||||
*/
|
||||
|
||||
// recupero la sezione come curva composite mediante tolleranza definita
|
||||
PtrOwner<ICurveComposite> pSecLocApprox( CreateCurveComposite()) ;
|
||||
if ( IsNull( pSecLocApprox) ||
|
||||
if ( IsNull( pSecLocApprox) ||
|
||||
! pSecLocApprox->FromPolyLine( PL) ||
|
||||
! pSecLocApprox->IsValid())
|
||||
return nullptr ;
|
||||
/*
|
||||
for ( int i = 0 ; i < int( vRMF.size()) ; ++ i) {
|
||||
Vector3d vtH = vRMF[i].VersZ() ;
|
||||
vtH.z = 0 ;
|
||||
vtH.Normalize() ;
|
||||
vRMF[i].Set( vRMF[i].Orig(), vtH, Z_AX ^ vtH) ;
|
||||
}
|
||||
pSecLocApprox->LocToLoc( frStart, vRMF[0]) ;
|
||||
*/
|
||||
|
||||
// creo la sezione per lo step (i+1)-esimo che aggiornerò di volta in volta
|
||||
for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) {
|
||||
// creo la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
// recupero il frame iniziale sulla guida
|
||||
frStart.Set( ptStart, vtStart) ;
|
||||
if ( ! frStart.IsValid())
|
||||
return nullptr ;
|
||||
// porto la PolyLine della sezione in questo riferimento
|
||||
if ( ! PL.ToLoc( frStart))
|
||||
return nullptr ;
|
||||
// tengo in memorial il frame nel punto iniziale e finale della guida in caso di caps
|
||||
Frame3d frCaps_start ;
|
||||
Frame3d frCaps_end ;
|
||||
|
||||
if ( true) { // (1) versore statico
|
||||
Vector3d VETTORE( 0, 0, 1) ;
|
||||
// creo il piano di proiezine in Z = 0 con normale definita dal vettore
|
||||
Plane3d plProj ;
|
||||
plProj.Set( ORIG, VETTORE) ;
|
||||
if ( ! plProj.IsValid())
|
||||
return nullptr ;
|
||||
// porto la sezione nel frame corrente
|
||||
if ( ! pSecCurr->ToGlob( vRMF[i]))
|
||||
// approssimo la guida mediante la tolleranza richiesta
|
||||
PolyLine PL_G ;
|
||||
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL_G))
|
||||
return nullptr ;
|
||||
// creo la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecNext( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecNext) || ! pSecNext->IsValid())
|
||||
// punto attuale e punto successivo
|
||||
Point3d ptCurr, ptSucc ;
|
||||
if ( ! PL_G.GetFirstPoint( ptCurr))
|
||||
return nullptr ;
|
||||
// porto la sezione nel frame successivo
|
||||
if ( ! pSecNext->ToGlob( vRMF[i+1]))
|
||||
bool bNextPoint = PL_G.GetNextPoint( ptSucc) ;
|
||||
if ( ! bNextPoint)
|
||||
return nullptr ;
|
||||
// creo la rigata tra queste due curve
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecNext, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
// parametro attuale e successivo riferito ai punti sulla guida
|
||||
double dParCurr = 0 ;
|
||||
double dParSucc ;
|
||||
// versore attuale e successivo riferito ai punti sulla guida
|
||||
Vector3d vtTanCurr, vtTanSucc ;
|
||||
if ( ! pGuide->GetStartDir( vtTanCurr))
|
||||
return nullptr ;
|
||||
// frame iniziale e successivo riferito alla curva
|
||||
Frame3d frCurr, frSucc ;
|
||||
|
||||
bool bFirstIter = true ;
|
||||
while ( bNextPoint) { // finchè recupero un punto sucessivo...
|
||||
// recupero il parametro successivo riferito alla guida
|
||||
if ( ! pGuide->GetParamAtPoint( ptSucc, dParSucc))
|
||||
return nullptr ;
|
||||
// recupero il versore tangente riferito al punto successivo sulla griglia
|
||||
if ( ! pGuide->GetPointD1D2( dParSucc, ICurve::FROM_MINUS, ptSucc, &vtTanSucc) ||
|
||||
! vtTanSucc.Normalize())
|
||||
return nullptr ;
|
||||
// proietto i versori tangenti sul piano
|
||||
Point3d ptS_proj( vtTanCurr.x, vtTanCurr.y, vtTanCurr.z) ;
|
||||
ptS_proj = ProjectPointOnPlane( ptS_proj, plProj) ;
|
||||
vtTanCurr.Set( ptS_proj.x, ptS_proj.y, ptS_proj.z) ;
|
||||
if ( ! vtTanCurr.Normalize())
|
||||
return nullptr ; // se tangente alla guida in ptCurr perpendicolare al piano...
|
||||
Point3d ptE_proj( vtTanSucc.x, vtTanSucc.y, vtTanSucc.z) ;
|
||||
ptE_proj = ProjectPointOnPlane( ptE_proj, plProj) ;
|
||||
vtTanSucc.Set( ptE_proj.x, ptE_proj.y, ptE_proj.z) ;
|
||||
if ( ! vtTanSucc.Normalize())
|
||||
return nullptr ; // se tangente alla guida in ptSucc perpendicolare al piano...
|
||||
// creazione del frame corrente
|
||||
frCurr.Set( ptCurr, vtTanCurr, VETTORE ^ vtTanCurr) ;
|
||||
if ( ! frCurr.IsValid())
|
||||
return nullptr ;
|
||||
if ( bFirstIter) { // memorizzo il primo frame di caso di caps
|
||||
frCaps_start = frCurr ;
|
||||
bFirstIter = false ;
|
||||
}
|
||||
// creazione del frame successivo
|
||||
frSucc.Set( ptSucc, vtTanSucc, VETTORE ^ vtTanSucc) ;
|
||||
if ( ! frSucc.IsValid())
|
||||
return nullptr ;
|
||||
frCaps_end = frSucc ; // aggiorno il frame finale
|
||||
// definisco la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
return nullptr ;
|
||||
// porto la sezione corrente nel frame attuale
|
||||
if ( ! pSecCurr->ToGlob( frCurr))
|
||||
return nullptr ;
|
||||
// definisco la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
|
||||
return nullptr ;
|
||||
// porto questa sezione nel frame allo step successivo
|
||||
if ( ! pSecSucc->ToGlob( frSucc))
|
||||
return nullptr ;
|
||||
// creo la rigata tra queste due sezioni
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
// aggiornamento dei parametri
|
||||
ptCurr = ptSucc ; // il punto corrente diventa il successivo
|
||||
bNextPoint = PL.GetNextPoint( ptSucc) ; // il successivo lo recupero dalla PolyLine
|
||||
vtTanCurr = vtTanSucc ; // il versore tangete corrente diventa il successivo
|
||||
}
|
||||
// la superficie definita dal RMF è invertita, il verosre Z è diretto come la tangente della curva
|
||||
pSTM->Invert() ;
|
||||
|
||||
}
|
||||
else { // (2) Rotation Minimize Frame
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
RotationMinimizeFrame RMF( pGuide, frStart) ;
|
||||
FRAME3DVECTOR vRMF ;
|
||||
if ( ! RMF.GetFramesByTollerance( vRMF, dLinTol) || vRMF.empty())
|
||||
return nullptr ;
|
||||
// per ogni RMF calcolato, la sezione va roto-traslata lungo la guida
|
||||
for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) {
|
||||
// definisco la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
return nullptr ;
|
||||
// porto la sezione corrente nel frame attuale
|
||||
if ( ! pSecCurr->ToGlob( vRMF[i]))
|
||||
return nullptr ;
|
||||
// definisco la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
|
||||
return nullptr ;
|
||||
// porto questa sezione nel frame allo step successivo
|
||||
if ( ! pSecSucc->ToGlob( vRMF[i+1]))
|
||||
return nullptr ;
|
||||
// creo la rigata tra queste due sezioni
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
// la superficie definita dal RMF è invertita, il verosre Z è diretto come la tangente della curva
|
||||
pSTM->Invert() ;
|
||||
// assegno frame iniziale e finale per caps
|
||||
frCaps_start = vRMF[0] ;
|
||||
frCaps_end = vRMF.back() ;
|
||||
}
|
||||
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// inverto
|
||||
pSTM->Invert() ;
|
||||
// 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) ||
|
||||
! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// 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( frCaps_start) ;
|
||||
pSci->Invert() ; // il versore Z è tangente alla curva nella sua direzione di percorrenza
|
||||
// unisco
|
||||
pSTM->DoSewing( *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( frCaps_end) ;
|
||||
// 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) ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
La guida è piana, l'estrusione viene definita mediante Offset della guida sulla sezione
|
||||
*/
|
||||
|
||||
|
||||
// il frame iniziale è definito dal versore tangente e dalla normale al piano
|
||||
// che contiene la guida
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
// porto la sezione in questo riferimento e ve la appiattisco
|
||||
if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
|
||||
return nullptr ;
|
||||
// superficie swept
|
||||
PtrOwner<ICurve> pPrevCrv ;
|
||||
Point3d ptP ;
|
||||
bool bPoint = PL.GetFirstPoint( ptP) ;
|
||||
while ( bPoint) {
|
||||
// nuova curva
|
||||
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 ;
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
// se devo chiudere la superficie, salvo i frame iniziali e finali
|
||||
frRMF_Start = vRMF[0] ;
|
||||
frRMF_End = vRMF.back() ;
|
||||
// salvo la curva come prossima precedente
|
||||
pPrevCrv.Set( pCurrCrv) ;
|
||||
// prossimo punto
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
@@ -776,37 +913,29 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
Plane3d plEnds ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL) ||
|
||||
! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
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 ;
|
||||
if ( ! bIsFlat)
|
||||
frStart = frRMF_Start ;
|
||||
pSci->ToGlob( frStart) ;
|
||||
if ( ! bIsFlat)
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// riferimento alla fine della linea guida
|
||||
Frame3d frEnd ;
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtEnd ;
|
||||
pGuide->GetEndDir( vtEnd) ;
|
||||
Frame3d frEnd ;
|
||||
if ( ! bIsFlat)
|
||||
frEnd = frRMF_End ;
|
||||
else
|
||||
frEnd.Set( ptEnd, - vtEnd, vtEnd ^ vtNorm) ;
|
||||
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) ;
|
||||
if ( ! bIsFlat)
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
|
||||
Reference in New Issue
Block a user