From ec109908fa5f274b694d979c2be02d98f20b9a7f Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 5 Mar 2024 16:20:28 +0100 Subject: [PATCH 1/9] EgtGeomKernel : - inizio stesura codice per Rotation Minimize Frame. --- EgtGeomKernel.vcxproj | 2 + EgtGeomKernel.vcxproj.filters | 6 ++ RotationMinimizeFrame.cpp | 182 ++++++++++++++++++++++++++++++++++ RotationMinimizeFrame.h | 47 +++++++++ 4 files changed, 237 insertions(+) create mode 100644 RotationMinimizeFrame.cpp create mode 100644 RotationMinimizeFrame.h diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 6277db6..935171b 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -318,6 +318,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -460,6 +461,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 75fe444..1e16302 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -522,6 +522,9 @@ File di origine\GeoInters + + File di origine\Geo + @@ -1190,6 +1193,9 @@ File di intestazione\Include + + File di intestazione + diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp new file mode 100644 index 0000000..c11027d --- /dev/null +++ b/RotationMinimizeFrame.cpp @@ -0,0 +1,182 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2024 +//---------------------------------------------------------------------------- +// File : RotationMinimizeFrame.cpp Data : 05.03.24 Versione : 2.6c1 +// Contenuto : Classe per RotationMinimizeFrame +// +// +// +// Modifiche : 05.03.24 RE Creazione modulo. + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "RotationMinimizeFrame.h" +#include "GeoConst.h" + +using namespace std ; + +RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const double dStep) +{ + // 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 ; + +} + +//---------------------------------------------------------------------------- +RotationMinimizeFrame::~RotationMinimizeFrame( void) +{ + Clear() ; +} + +//---------------------------------------------------------------------------- +bool +RotationMinimizeFrame::IsValid() +{ + // controllo validità della curva + if ( m_pCrv == nullptr || ! m_pCrv->IsValid()) + return false ; + + // controllo del frame iniziale + 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 ; + + return true ; + +} + +//---------------------------------------------------------------------------- +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() ; + + // reset dell'intervallo di discretizzazione + m_dStep = 0. ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) +{ + // 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)) + return false ; + + // ricavo il numero degli step + int nStep = 1 + ceil( dLen / nStep) ; // frame iniziale, ... frame intermedi ..., frame finale + + // in prima posizione viene inserito il frame iniziale + m_vRMFrams.push_back( m_Frame0) ; + + // 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->GetPointD1D2( dUCurr, ICurve::FROM_MINUS, ptCurr)) + return false ; + Point3d ptNext ; // punto sulla curva allo step (i+1)-esimo + + // definizione dei versori r,s,t + Vector3d vt_r = m_Frame0.VersX() ; + Vector3d vt_s = m_Frame0.VersY() ; + Vector3d vt_t = m_Frame0.VersZ() ; + + // ciclo sugli step in cui la curva è suddivisa + for ( int i = 0 ; i <= nStep ; ++ i) { + // ricavo la lunghezza della curva nello step successivo + dLenNext = min( dLen, ( i + 1) * dLen / nStep) ; + // parametro successivo sulla curva + if ( ! m_pCrv->GetParamAtLength( dLenNext, dUnext)) + return false ; + // punto successivo sulla curva + if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptNext)) + return false ; + // ricavo il vettore di riflessione rispetto al piano R1 + Vector3d v1 = ptNext - ptCurr ; + if ( ! v1.IsValid()) + return false ; + // parametro di riflessione + double c1 = v1 * v1 ; + // riflessione rispetto al piano R1 + Vector3d vt_r_L = vt_r - ( 2 / c1) * ( v1 * vt_r) * v1 ; + Vector3d vt_t_L = vt_t - ( 2 / c1) * ( v1 * vt_t) * v1 ; + // vettore tangente al punto successivo + Vector3d vt_t_next ; + Point3d ptH ; + if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptH, &vt_t_next) || + ! vt_t_next.IsValid()) + return false ; + // risplessione rispetto al piano R2 + Vector3d v2 = vt_t_next - vt_t ; + if ( ! v2.IsValid()) + return false ; + // parametro di riflessione + double c2 = v2 * v2 ; + // versore r del nuovo frame + Vector3d vt_r_next = vt_r_L - ( 2 / c2) * ( v2 * vt_r_L) * v2 ; + // versore t del nuovo frame + Vector3d vt_s_next = vt_t_next ^ vt_r_next ; + // creazione del nuovo frame + Frame3d RMFrame_next ; + RMFrame_next.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ; + if ( ! RMFrame_next.IsValid()) + return false ; + // aggiornamento vettore dei frame + m_vRMFrams.push_back( RMFrame_next) ; + // aggiornamento dei parametri + dLenCurr = dLenNext ; + dUCurr = dUnext ; + ptCurr = ptNext ; + } + + return true ; +} \ No newline at end of file diff --git a/RotationMinimizeFrame.h b/RotationMinimizeFrame.h new file mode 100644 index 0000000..fe662a6 --- /dev/null +++ b/RotationMinimizeFrame.h @@ -0,0 +1,47 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2024 +//---------------------------------------------------------------------------- +// File : RotationMinimizeFrame.h Data : 05.03.24 Versione : 2.6c1 +// Contenuto : Dichiarazione della classe RotationMinimizeFrame +// +// +// +// Modifiche : 05.03.24 RE Creazione modulo. + +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkFrame3d.h" +#include "/EgtDev/Include/EGkCurve.h" +#include + +//-------------------------- Forward Definitions ------------------------------- +class ICurve ; + +//---------------------------------------------------------------------------- +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( void) ; + + public : + bool GetFrames( FRAME3DVECTOR& vRMFrams) ; + + private : + bool Clear( void) ; + bool IsValid( void) ; + + 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 + FRAME3DVECTOR m_vRMFrams ; // vettore contenente i RMFrame + +} ; + +//---------------------------------------------------------------------------- +typedef std::vector FRAME3DVECTOR ; From 003dd0bdef4f75045b9e1b3ecb4d5f67592672e1 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Wed, 6 Mar 2024 16:29:36 +0100 Subject: [PATCH 2/9] EgtGeomKernel : - codice di prova per RMF. --- RotationMinimizeFrame.cpp | 63 +++++++++++++++++++++++------------- RotationMinimizeFrame.h | 8 ++--- StmFromCurves.cpp | 68 +++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 59 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index c11027d..8a31952 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -85,6 +85,9 @@ RotationMinimizeFrame::Clear( void) // reset dell'intervallo di discretizzazione m_dStep = 0. ; + // pulizia del vettore dei frames + m_vRMFrames.clear() ; + return true ; } @@ -110,18 +113,18 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) return false ; // ricavo il numero degli step - int nStep = 1 + ceil( dLen / nStep) ; // frame iniziale, ... frame intermedi ..., frame finale + int nStep = ceil( dLen / m_dStep) ; // in prima posizione viene inserito il frame iniziale - m_vRMFrams.push_back( m_Frame0) ; + m_vRMFrames.push_back( m_Frame0) ; // 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 + double dUNext ; // parametro sulla curva allo step (i+1)-esimo Point3d ptCurr ; // punto sulla curva allo step i-esimo - if ( ! m_pCrv->GetPointD1D2( dUCurr, ICurve::FROM_MINUS, ptCurr)) + if ( ! m_pCrv->GetStartPoint( ptCurr)) return false ; Point3d ptNext ; // punto sulla curva allo step (i+1)-esimo @@ -131,35 +134,35 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) Vector3d vt_t = m_Frame0.VersZ() ; // ciclo sugli step in cui la curva è suddivisa - for ( int i = 0 ; i <= nStep ; ++ i) { + for ( int i = 0 ; i < nStep ; ++ i) { // ricavo la lunghezza della curva nello step successivo - dLenNext = min( dLen, ( i + 1) * dLen / nStep) ; + dLenNext = min( dLen - EPS_SMALL, ( i + 1) * dLen / nStep) ; // parametro successivo sulla curva - if ( ! m_pCrv->GetParamAtLength( dLenNext, dUnext)) + if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext)) return false ; - // punto successivo sulla curva - if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptNext)) + // punto successivo 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()*/) + return false ; + // controllo per caso degenere + if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste R1 + abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste R2 return false ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d v1 = ptNext - ptCurr ; if ( ! v1.IsValid()) return false ; - // parametro di riflessione + // parametro di riflessione per R1 double c1 = v1 * v1 ; // riflessione rispetto al piano R1 Vector3d vt_r_L = vt_r - ( 2 / c1) * ( v1 * vt_r) * v1 ; Vector3d vt_t_L = vt_t - ( 2 / c1) * ( v1 * vt_t) * v1 ; - // vettore tangente al punto successivo - Vector3d vt_t_next ; - Point3d ptH ; - if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptH, &vt_t_next) || - ! vt_t_next.IsValid()) - return false ; - // risplessione rispetto al piano R2 - Vector3d v2 = vt_t_next - vt_t ; + // ricavo il vettore di riflessione rispetto al piano R1 + Vector3d v2 = vt_t_next - vt_t_L ; if ( ! v2.IsValid()) return false ; - // parametro di riflessione + // parametro di riflessione per R2 double c2 = v2 * v2 ; // versore r del nuovo frame Vector3d vt_r_next = vt_r_L - ( 2 / c2) * ( v2 * vt_r_L) * v2 ; @@ -168,15 +171,29 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) // creazione del nuovo frame Frame3d RMFrame_next ; RMFrame_next.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ; - if ( ! RMFrame_next.IsValid()) - return false ; + if ( ! RMFrame_next.IsValid()) { + // sistemo... + RMFrame_next.Set( ptNext, vt_t_next, vt_r_next) ; + if ( ! RMFrame_next.IsValid()) + return false ; + } // aggiornamento vettore dei frame - m_vRMFrams.push_back( RMFrame_next) ; + m_vRMFrames.push_back( RMFrame_next) ; // aggiornamento dei parametri dLenCurr = dLenNext ; - dUCurr = dUnext ; + dUCurr = dUNext ; ptCurr = ptNext ; } + // restituisco il vettore di Frame + vRMFrams.resize( int( m_vRMFrames.size())) ; + + // oriento i frames ottenuti in modo da avere il versore X tangente alla curva + for ( int i = 0 ; i < int( m_vRMFrames.size()) ; ++ i) { + vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; + if ( ! vRMFrams[i].IsValid()) + return false ; + } + return true ; } \ No newline at end of file diff --git a/RotationMinimizeFrame.h b/RotationMinimizeFrame.h index fe662a6..4b73137 100644 --- a/RotationMinimizeFrame.h +++ b/RotationMinimizeFrame.h @@ -17,8 +17,8 @@ #include "/EgtDev/Include/EGkCurve.h" #include -//-------------------------- Forward Definitions ------------------------------- -class ICurve ; +//---------------------------------------------------------------------------- +typedef std::vector FRAME3DVECTOR ; //---------------------------------------------------------------------------- class RotationMinimizeFrame @@ -39,9 +39,7 @@ class RotationMinimizeFrame ICurve* m_pCrv ; // curva per il calcolo del rotation minimize frame Frame3d m_Frame0 ; // frame iniziale della curva double m_dStep ; // passo di discretizzazione - FRAME3DVECTOR m_vRMFrams ; // vettore contenente i RMFrame + FRAME3DVECTOR m_vRMFrames ; // vettore contenente i RMFrame } ; -//---------------------------------------------------------------------------- -typedef std::vector FRAME3DVECTOR ; diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 0af869f..120656a 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -19,6 +19,7 @@ #include "CurveComposite.h" #include "SurfTriMesh.h" #include "Voronoi.h" +#include "RotationMinimizeFrame.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" @@ -664,52 +665,57 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d bool bSectClosed = PL.IsClosed() ; // verifico che la linea guida sia piana Plane3d plGuide ; - if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) - return nullptr ; + bool bIsFlat = pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL) ; // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; - // riferimento all'inizio della linea guida - Frame3d frStart ; + // ricavo punto e versore iniziale Point3d ptStart ; pGuide->GetStartPoint( ptStart) ; Vector3d vtStart ; pGuide->GetStartDir( vtStart) ; + // ricavo versore normale all 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 ; // calcolo la superficie PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM)) return nullptr ; - // salvo tolleranza lineare usata - pSTM->SetLinearTolerance( dLinTol) ; - // superficie swept - PtrOwner 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) + // riferimento all'inizio della linea guida + Frame3d frStart ; + if ( bIsFlat) { + frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; + // porto la sezione in questo riferimento e ve la appiattisco + if ( ! PL.ToLoc( frStart) || ! PL.Flatten()) return nullptr ; - PtrOwner 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 pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; - if ( IsNull( pSr)) + // salvo tolleranza lineare usata + pSTM->SetLinearTolerance( dLinTol) ; + // superficie swept + PtrOwner 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 ; - pSTM->DoSewing( *pSr) ; + PtrOwner 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 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) ; } - // salvo la curva come prossima precedente - pPrevCrv.Set( pCurrCrv) ; - // prossimo punto - bPoint = PL.GetNextPoint( ptP) ; } + else + return nullptr ; // se richiesti caps e sezione chiusa e guida aperta if ( bCapEnds && bSectClosed && ! bGuideClosed) { // verifico che le due estremità siano chiuse e piatte From d48348fa1ccad1c043d64f593256026304675f6d Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 7 Mar 2024 10:51:59 +0100 Subject: [PATCH 3/9] EgtGeomKernel : - pulizia codice. --- RotationMinimizeFrame.cpp | 63 ++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index 8a31952..76d0689 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -112,12 +112,14 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) if ( ! m_pCrv->GetLength( dLen)) return false ; - // ricavo il numero degli step - int nStep = ceil( dLen / m_dStep) ; - // in prima posizione viene inserito il frame iniziale m_vRMFrames.push_back( m_Frame0) ; + // ricavo il numero degli step + int nStep = ceil( dLen / m_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 @@ -128,51 +130,54 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) return false ; Point3d ptNext ; // punto sulla curva allo step (i+1)-esimo - // definizione dei versori r,s,t + // 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 ; + // ciclo sugli step in cui la curva è suddivisa for ( int i = 0 ; i < nStep ; ++ i) { - // ricavo la lunghezza della curva nello step successivo - dLenNext = min( dLen - EPS_SMALL, ( i + 1) * dLen / nStep) ; - // parametro successivo sulla curva + // 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)) return false ; - // punto successivo sulla curva e suo vettore tangente + // 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()*/) + ! vt_t_next.IsValid()) return false ; - // controllo per caso degenere - if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste R1 - abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste R2 + // 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 v1 = ptNext - ptCurr ; - if ( ! v1.IsValid()) + Vector3d vR1_norm = ptNext - ptCurr ; + if ( ! vR1_norm.IsValid()) return false ; // parametro di riflessione per R1 - double c1 = v1 * v1 ; - // riflessione rispetto al piano R1 - Vector3d vt_r_L = vt_r - ( 2 / c1) * ( v1 * vt_r) * v1 ; - Vector3d vt_t_L = vt_t - ( 2 / c1) * ( v1 * vt_t) * v1 ; + 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 v2 = vt_t_next - vt_t_L ; - if ( ! v2.IsValid()) + Vector3d vR2_norm = vt_t_next - vt_t_L ; + if ( ! vR2_norm.IsValid()) return false ; // parametro di riflessione per R2 - double c2 = v2 * v2 ; - // versore r del nuovo frame - Vector3d vt_r_next = vt_r_L - ( 2 / c2) * ( v2 * vt_r_L) * v2 ; - // versore t del nuovo frame + 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 + // 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()) { - // sistemo... + 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 ; @@ -185,10 +190,8 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) ptCurr = ptNext ; } - // restituisco il vettore di Frame - vRMFrams.resize( int( m_vRMFrames.size())) ; - // oriento i frames ottenuti in modo da avere il versore X tangente alla curva + vRMFrams.resize( int( m_vRMFrames.size())) ; for ( int i = 0 ; i < int( m_vRMFrames.size()) ; ++ i) { vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; if ( ! vRMFrams[i].IsValid()) From 4f485d0e874cc2795a8dea41d5d105a7b9e7ec14 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 7 Mar 2024 16:53:19 +0100 Subject: [PATCH 4/9] EgtGeomKernel : - primo codice di prova per creazione Swept. --- RotationMinimizeFrame.cpp | 3 +- StmFromCurves.cpp | 113 +++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index 76d0689..bce4b2a 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -193,7 +193,8 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) // oriento i frames ottenuti in modo da avere il versore X tangente alla curva vRMFrams.resize( int( m_vRMFrames.size())) ; for ( int i = 0 ; i < int( m_vRMFrames.size()) ; ++ i) { - vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; + //vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; + vRMFrams[i] = m_vRMFrames[i] ; if ( ! vRMFrams[i].IsValid()) return false ; } diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 120656a..0df253d 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1 @@ -111,9 +111,9 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM) || ! pSTM->CreateByExtrusion( PL, vtExtr)) return nullptr ; - // se da fare, metto i tappi sulle estremità + // se da fare, metto i tappi sulle estremità if ( bDoCapEnds) { - // creo la prima superficie di estremità + // creo la prima superficie di estremità SurfTriMesh STM1 ; if ( ! STM1.CreateByFlatContour( PL)) return nullptr ; @@ -157,7 +157,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& for ( int i = 0 ; i < int( vPL.size()) ; ++ i) vPL[i].Invert() ; } - // creo la prima superficie di estremità + // creo la prima superficie di estremità PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) return nullptr ; @@ -289,7 +289,7 @@ GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vecto return nullptr ; // se richiesti caps if ( bCapEnds) { - // determino se la sezione è chiusa e piatta + // determino se la sezione è chiusa e piatta Plane3d plPlane ; double dArea ; bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; // determino non sia una semplice rivoluzione @@ -333,7 +333,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) return nullptr ; Vector3d vtNorm = plGuide.GetVersN() ; - // determino se la guida è chiusa + // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; // curve di offset OffsetCurve OffsCrvR ; @@ -374,7 +374,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, pSTM->SetSmoothAngle( 20) ; // se guida aperta e tappi piatti if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { - // verifico che le due estremità siano chiuse e piatte + // verifico che le due estremità siano chiuse e piatte POLYLINEVECTOR vPL ; if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) return nullptr ; @@ -453,7 +453,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub Point3d ptCen ; pGuide->GetStartPoint( ptCen) ; ptCen -= dDimV / 2 * vtNorm ; - // determino se la guida è chiusa + // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; // curve di offset const int NUM_OFFS = 4 ; @@ -476,7 +476,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub } } else { - // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo + // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i) bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ; } @@ -553,7 +553,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub StmFromTriangleSoup stmCapSoup ; if ( ! stmCapSoup.Start( nBuckets)) return nullptr ; - // verifico che le due estremità siano chiuse e piatte + // verifico che le due estremità siano chiuse e piatte POLYLINEVECTOR vPL ; if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) return nullptr ; @@ -661,33 +661,82 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d PolyLine PL ; if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) return nullptr ; - // determino se la sezione è chiusa + // determino se la sezione è chiusa bool bSectClosed = PL.IsClosed() ; - // verifico che la linea guida sia piana - Plane3d plGuide ; - bool bIsFlat = pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL) ; - // determino se la guida è chiusa + // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; - // ricavo punto e versore iniziale + // riferimento all'inizio della linea guida + Frame3d frStart ; Point3d ptStart ; pGuide->GetStartPoint( ptStart) ; Vector3d vtStart ; pGuide->GetStartDir( vtStart) ; - // ricavo versore normale all guida - Vector3d vtNorm = plGuide.GetVersN() ; - // calcolo la superficie + // inizializzo la superficie PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM)) return nullptr ; - // riferimento all'inizio della linea guida - Frame3d frStart ; - if ( bIsFlat) { + // salvo tolleranza lineare usata + pSTM->SetLinearTolerance( dLinTol) ; + // verifico che la linea guida sia piana + Plane3d plGuide ; + Vector3d vtNorm ; + if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) { + // se non risulta piana, utilizzo il Rotation Minimize Frame + // recupero il piano della sezione + Plane3d plSection ; + if ( ! pSect->IsFlat( plSection)) + return nullptr ; + Vector3d vtTan ; + if ( ! pGuide->GetPointD1D2( 0., ICurve::FROM_MINUS, ptStart, &vtTan)) + return false ; + frStart.Set( ptStart, vtTan) ; // la tangente è la Z del frame + double dStep = 0.5 ; // <<<---- come parametro.... + // calcolo il vettore di Frame campionati lungo la curva + RotationMinimizeFrame RMF( pGuide, frStart, dStep) ; + FRAME3DVECTOR vRMF ; + if ( ! RMF.GetFrames( vRMF) || vRMF.empty()) + return nullptr ; + // creo il frame della sezione + Point3d ptC ; pSect->GetCentroid( ptC) ; + Frame3d frSection ; frSection.Set( ptC, plSection.GetVersN()) ; + if ( ! frSection.IsValid()) + return nullptr ; + // porto una copia della sezione in questo frame + PtrOwner pSecLoc( pSect->Clone()) ; + if ( IsNull( pSecLoc) || ! pSecLoc->IsValid() || + ! pSecLoc->ToLoc( frSection)) + return nullptr ; + // creo la sezione per lo step (i+1)-esimo che aggiornerò di volta in volta + PtrOwner pSecNext ; + for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) { + // creo la sezione allo step corrente + PtrOwner pSecCurr( pSecLoc->Clone()) ; + if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) + return nullptr ; + // porto la sezione nel frame corrente + if ( ! pSecCurr->ToGlob( vRMF[i])) + return nullptr ; + // creo la sezione allo step successivo + PtrOwner pSecNext( pSecLoc->Clone()) ; + if ( IsNull( pSecNext) || ! pSecNext->IsValid()) + return nullptr ; + // porto la sezione nel frame successivo + if ( ! pSecNext->ToGlob( vRMF[i+1])) + return nullptr ; + // creo la rigata tra queste due curve + PtrOwner pSr( GetSurfTriMeshRuled( pSecCurr, pSecNext, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; + if ( IsNull( pSr)) + return nullptr ; + pSTM->DoSewing( *pSr) ; + } + pSTM->ToGlob( frSection) ; + } + else { + 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 ; - // salvo tolleranza lineare usata - pSTM->SetLinearTolerance( dLinTol) ; // superficie swept PtrOwner pPrevCrv ; Point3d ptP ; @@ -714,11 +763,9 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d bPoint = PL.GetNextPoint( ptP) ; } } - else - return nullptr ; // se richiesti caps e sezione chiusa e guida aperta if ( bCapEnds && bSectClosed && ! bGuideClosed) { - // verifico che le due estremità siano chiuse e piatte + // verifico che le due estremit� siano chiuse e piatte POLYLINEVECTOR vPL ; if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) return nullptr ; @@ -763,7 +810,7 @@ GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEn // verifica parametri if ( pSect == nullptr || pGuide == nullptr) return nullptr ; - // determino se la sezione è chiusa + // determino se la sezione è chiusa bool bSectClosed = pSect->IsClosed() ; // punto iniziale della sezione e vettore a inizio guida Point3d ptStart ; @@ -777,7 +824,7 @@ GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEn PolyLine PLG ; if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG)) return nullptr ; - // determino se la guida è chiusa + // determino se la guida è chiusa bool bGuideClosed = PLG.IsClosed() ; // calcolo la superficie PtrOwner pSTM( CreateBasicSurfTriMesh()) ; @@ -943,7 +990,7 @@ CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, vCrvCompo[i]->ToLoc( frRef) ; } - // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle + // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle // successive i loop interni INTMATRIX vnPLIndMat ; @@ -976,10 +1023,10 @@ CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, } bFirstCrv = false ; } - // ... altrimenti verifico se il loop è interno o no + // ... altrimenti verifico se il loop è interno o no else { - // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo - // esterno a tutti i loop già inseriti nella riga attuale. + // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo + // esterno a tutti i loop già inseriti nella riga attuale. // verifica rispetto loop esterno IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; CRVCVECTOR ccClass ; From 4268da4a1f7a6dc8e9af5b00d622c416a9dc906e Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 11 Mar 2024 13:22:37 +0100 Subject: [PATCH 5/9] EgtGeomKernel : - primo codice di test con Caps per funzione Swept con guida non piana. --- RotationMinimizeFrame.cpp | 31 ++++---- RotationMinimizeFrame.h | 2 - StmFromCurves.cpp | 144 +++++++++++++++++++++----------------- 3 files changed, 94 insertions(+), 83 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index bce4b2a..39ccc43 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -66,6 +66,15 @@ RotationMinimizeFrame::IsValid() 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 ; + if ( ! m_pCrv->GetPointD1D2( 0., ICurve::FROM_MINUS, ptS, &vtZ) || + ! vtZ.Normalize() || + ! AreSamePointApprox( ptS, m_Frame0.Orig()) || + ! AreSameVectorEpsilon( vtZ, m_Frame0.VersZ(), 5 * EPS_SMALL)) + return false ; + return true ; } @@ -85,15 +94,12 @@ RotationMinimizeFrame::Clear( void) // reset dell'intervallo di discretizzazione m_dStep = 0. ; - // pulizia del vettore dei frames - m_vRMFrames.clear() ; - return true ; } //---------------------------------------------------------------------------- bool -RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) +RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrames) { // controllo validità if ( ! IsValid()) { @@ -113,7 +119,7 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) return false ; // in prima posizione viene inserito il frame iniziale - m_vRMFrames.push_back( m_Frame0) ; + vRMFrames.push_back( m_Frame0) ; // ricavo il numero degli step int nStep = ceil( dLen / m_dStep) ; @@ -148,7 +154,7 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) // 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.IsValid() || ! vt_t_next.Normalize()) // versore tangente return false ; // controllo per casi degeneri if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1 @@ -183,20 +189,13 @@ RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) return false ; } // aggiornamento vettore dei frame - m_vRMFrames.push_back( RMFrame_next) ; + vRMFrames.push_back( RMFrame_next) ; // aggiornamento dei parametri dLenCurr = dLenNext ; dUCurr = dUNext ; ptCurr = ptNext ; - } - - // oriento i frames ottenuti in modo da avere il versore X tangente alla curva - vRMFrams.resize( int( m_vRMFrames.size())) ; - for ( int i = 0 ; i < int( m_vRMFrames.size()) ; ++ i) { - //vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; - vRMFrams[i] = m_vRMFrames[i] ; - if ( ! vRMFrams[i].IsValid()) - return false ; + vt_r = vt_r_next ; + vt_t = vt_t_next ; } return true ; diff --git a/RotationMinimizeFrame.h b/RotationMinimizeFrame.h index 4b73137..fda7651 100644 --- a/RotationMinimizeFrame.h +++ b/RotationMinimizeFrame.h @@ -39,7 +39,5 @@ class RotationMinimizeFrame ICurve* m_pCrv ; // curva per il calcolo del rotation minimize frame Frame3d m_Frame0 ; // frame iniziale della curva double m_dStep ; // passo di discretizzazione - FRAME3DVECTOR m_vRMFrames ; // vettore contenente i RMFrame - } ; diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 0df253d..ec20f0c 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -665,12 +665,11 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d bool bSectClosed = PL.IsClosed() ; // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; - // riferimento all'inizio della linea guida + // ricavo punto e versore iniziale + Point3d ptStart ; pGuide->GetStartPoint( ptStart) ; + Vector3d vtStart ; pGuide->GetStartDir( vtStart) ; + // creo il riferimento iniziale Frame3d frStart ; - Point3d ptStart ; - pGuide->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pGuide->GetStartDir( vtStart) ; // inizializzo la superficie PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM)) @@ -680,61 +679,14 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d // verifico che la linea guida sia piana Plane3d plGuide ; Vector3d vtNorm ; - if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) { - // se non risulta piana, utilizzo il Rotation Minimize Frame - // recupero il piano della sezione - Plane3d plSection ; - if ( ! pSect->IsFlat( plSection)) - return nullptr ; - Vector3d vtTan ; - if ( ! pGuide->GetPointD1D2( 0., ICurve::FROM_MINUS, ptStart, &vtTan)) - return false ; - frStart.Set( ptStart, vtTan) ; // la tangente è la Z del frame - double dStep = 0.5 ; // <<<---- come parametro.... - // calcolo il vettore di Frame campionati lungo la curva - RotationMinimizeFrame RMF( pGuide, frStart, dStep) ; - FRAME3DVECTOR vRMF ; - if ( ! RMF.GetFrames( vRMF) || vRMF.empty()) - return nullptr ; - // creo il frame della sezione - Point3d ptC ; pSect->GetCentroid( ptC) ; - Frame3d frSection ; frSection.Set( ptC, plSection.GetVersN()) ; - if ( ! frSection.IsValid()) - return nullptr ; - // porto una copia della sezione in questo frame - PtrOwner pSecLoc( pSect->Clone()) ; - if ( IsNull( pSecLoc) || ! pSecLoc->IsValid() || - ! pSecLoc->ToLoc( frSection)) - return nullptr ; - // creo la sezione per lo step (i+1)-esimo che aggiornerò di volta in volta - PtrOwner pSecNext ; - for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) { - // creo la sezione allo step corrente - PtrOwner pSecCurr( pSecLoc->Clone()) ; - if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) - return nullptr ; - // porto la sezione nel frame corrente - if ( ! pSecCurr->ToGlob( vRMF[i])) - return nullptr ; - // creo la sezione allo step successivo - PtrOwner pSecNext( pSecLoc->Clone()) ; - if ( IsNull( pSecNext) || ! pSecNext->IsValid()) - return nullptr ; - // porto la sezione nel frame successivo - if ( ! pSecNext->ToGlob( vRMF[i+1])) - return nullptr ; - // creo la rigata tra queste due curve - PtrOwner pSr( GetSurfTriMeshRuled( pSecCurr, pSecNext, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; - if ( IsNull( pSr)) - return nullptr ; - pSTM->DoSewing( *pSr) ; - } - pSTM->ToGlob( frSection) ; - } - else { + 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 ve la appiattisco + frStart.Set( ptStart, - vtStart, vtStart ^ vtNorm) ; + // porto la sezione in questo riferimento e appiattisco if ( ! PL.ToLoc( frStart) || ! PL.Flatten()) return nullptr ; // superficie swept @@ -763,36 +715,98 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d 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 + PtrOwner pSecLocApprox( CreateCurveComposite()) ; + 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 pSecCurr( pSecLocApprox->Clone()) ; + if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) + return nullptr ; + // porto la sezione nel frame corrente + if ( ! pSecCurr->ToGlob( vRMF[i])) + return nullptr ; + // creo la sezione allo step successivo + PtrOwner pSecNext( pSecLocApprox->Clone()) ; + if ( IsNull( pSecNext) || ! pSecNext->IsValid()) + return nullptr ; + // porto la sezione nel frame successivo + if ( ! pSecNext->ToGlob( vRMF[i+1])) + return nullptr ; + // creo la rigata tra queste due curve + PtrOwner pSr( GetSurfTriMeshRuled( pSecCurr, pSecNext, 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() ; + } // se richiesti caps e sezione chiusa e guida aperta if ( bCapEnds && bSectClosed && ! bGuideClosed) { - // verifico che le due estremit� siano chiuse e piatte + // 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)) + if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL) || + ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) return nullptr ; // aggiungo il cap sull'inizio PtrOwner 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) ; - frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ; + Frame3d frEnd ; + if ( ! bIsFlat) + frEnd = frRMF_End ; + else + frEnd.Set( ptEnd, - vtEnd, vtEnd ^ vtNorm) ; // aggiungo il cap sulla fine PtrOwner 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 From d2768099068d246897e511e561c9fe219c8bc5bf Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 14 Mar 2024 13:04:09 +0100 Subject: [PATCH 6/9] EgtGeomKernel : - Swept con o senza caps mediante RMF - inizio stesura codice per frame statico - migliorie varie. --- RotationMinimizeFrame.cpp | 262 ++++++++++++++++++------------- RotationMinimizeFrame.h | 9 +- StmFromCurves.cpp | 323 ++++++++++++++++++++++++++------------ 3 files changed, 386 insertions(+), 208 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index 39ccc43..13603db 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -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 ; diff --git a/RotationMinimizeFrame.h b/RotationMinimizeFrame.h index fda7651..c3b80ba 100644 --- a/RotationMinimizeFrame.h +++ b/RotationMinimizeFrame.h @@ -24,20 +24,21 @@ typedef std::vector 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 } ; diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index ec20f0c..7e60df8 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 From 9880fa01739fa9e305026329c7c9c9a1c3102bbb Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 15 Mar 2024 13:17:41 +0100 Subject: [PATCH 7/9] EgtGeomKernel : - migliorie varie. --- RotationMinimizeFrame.cpp | 9 +++++- StmFromCurves.cpp | 58 ++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index 13603db..9691c96 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -173,7 +173,7 @@ RotationMinimizeFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, // 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) * dMyStep) ; + dLenNext = min( dLen - 10 * EPS_SMALL, ( i + 1) * dMyStep) ; // ricavo il frame alla lunghezza calcolata Frame3d frNext ; if ( ! GetFrameAtLength( vRMFrames[i], dLenNext, frNext)) @@ -221,6 +221,11 @@ RotationMinimizeFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double d if ( ! m_pCrv->ApproxWithLines( dTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) return false ; + // ricavo la lunghezza della curva + double dCrvLen = 0 ; + if ( ! m_pCrv->GetLength( dCrvLen)) + return false ; + // devo calcolare il RMF su ogni punto ricavato dall'approssimazione Point3d ptCurr ; bool bPoint = PL.GetFirstPoint( ptCurr) ; @@ -236,6 +241,8 @@ RotationMinimizeFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double d double dLen = 0. ; if ( ! m_pCrv->GetLengthAtPoint( ptCurr, dLen)) return false ; + // per sicurezza controllo che sia minore della lunghezza complessiva + dLen = min( dCrvLen - 10 * EPS_SMALL , dLen) ; // ricavo il Frame associato a tale lunghezza Frame3d frNext ; if ( ! GetFrameAtLength( vRMFrames.back(), dLen, frNext)) diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 7e60df8..a2a4d7a 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -652,7 +652,7 @@ GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBev //------------------------------------------------------------------------------- ISurfTriMesh* -GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) +GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic) { // verifica parametri if ( pSect == nullptr || pGuide == nullptr) @@ -687,7 +687,6 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d ( 2) mediante l'algoritmo del Rotation Minimize Frame */ - // recupero la sezione come curva composite mediante tolleranza definita PtrOwner pSecLocApprox( CreateCurveComposite()) ; if ( IsNull( pSecLocApprox) || ! pSecLocApprox->FromPolyLine( PL) || @@ -698,20 +697,29 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d 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 + + // tengo in memoria 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 + if ( vtStatic != nullptr) { // (1) versore statico + // creo il piano di proiezione con normale definita dal vettore Plane3d plProj ; - plProj.Set( ORIG, VETTORE) ; + plProj.Set( ORIG, *vtStatic) ; if ( ! plProj.IsValid()) return nullptr ; + // porto la sezione nel frame definito dalla guida proeittando la Z nel piano definito da vtStatic + Point3d ptS_proj( vtStart.x, vtStart.y, vtStart.z) ; + ptS_proj = ProjectPointOnPlane( ptS_proj, plProj) ; + Vector3d vtStartH( ptS_proj.x, ptS_proj.y, ptS_proj.z) ; + if ( ! vtStartH.Normalize()) + return nullptr ; + Frame3d frInitial ; + frInitial.Set( ptStart, vtStartH) ; + if ( ! frInitial.IsValid()) + return nullptr ; + pSecLocApprox->ToLoc( frInitial) ; + PL.ToLoc( frInitial) ; // approssimo la guida mediante la tolleranza richiesta PolyLine PL_G ; if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL_G)) @@ -754,7 +762,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d if ( ! vtTanSucc.Normalize()) return nullptr ; // se tangente alla guida in ptSucc perpendicolare al piano... // creazione del frame corrente - frCurr.Set( ptCurr, vtTanCurr, VETTORE ^ vtTanCurr) ; + frCurr.Set( ptCurr, vtTanCurr, *vtStatic ^ vtTanCurr) ; if ( ! frCurr.IsValid()) return nullptr ; if ( bFirstIter) { // memorizzo il primo frame di caso di caps @@ -762,7 +770,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d bFirstIter = false ; } // creazione del frame successivo - frSucc.Set( ptSucc, vtTanSucc, VETTORE ^ vtTanSucc) ; + frSucc.Set( ptSucc, vtTanSucc, *vtStatic ^ vtTanSucc) ; if ( ! frSucc.IsValid()) return nullptr ; frCaps_end = frSucc ; // aggiorno il frame finale @@ -788,7 +796,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d pSTM->DoSewing( *pSr) ; // aggiornamento dei parametri ptCurr = ptSucc ; // il punto corrente diventa il successivo - bNextPoint = PL.GetNextPoint( ptSucc) ; // il successivo lo recupero dalla PolyLine + bNextPoint = PL_G.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 @@ -796,6 +804,9 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d } else { // (2) Rotation Minimize Frame + // porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida + pSecLocApprox->ToLoc( frStart) ; + PL.ToLoc( frStart) ; // calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita RotationMinimizeFrame RMF( pGuide, frStart) ; FRAME3DVECTOR vRMF ; @@ -824,7 +835,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d // 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 + // la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva pSTM->Invert() ; // assegno frame iniziale e finale per caps frCaps_start = vRMF[0] ; @@ -833,22 +844,11 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d // 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 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 ) @@ -856,6 +856,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) return nullptr ; pSce->ToGlob( frCaps_end) ; + pSce->Invert() ; // il versore z è definito dalle tangenti alla curva // unisco pSTM->DoSewing( *pSce) ; } @@ -946,6 +947,13 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d return Release( pSTM) ; } +//------------------------------------------------------------------------------- +ISurfTriMesh* +GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic) +{ + return nullptr ; +} + //------------------------------------------------------------------------------- ISurfTriMesh* GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) From e2445c0a157ee2352dfd5daad144b2075fefb242 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 18 Mar 2024 13:20:35 +0100 Subject: [PATCH 8/9] EgtGeomKernel : - modifica Swept con vettore statico. - aggiunta Swep con FlatRegion come sezione - migliorie varie. --- StmFromCurves.cpp | 111 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 23 deletions(-) diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index a2a4d7a..9b71de6 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -24,6 +24,7 @@ #include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkSfrCreate.h" #include #include #include @@ -687,7 +688,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d ( 2) mediante l'algoritmo del Rotation Minimize Frame */ - PtrOwner pSecLocApprox( CreateCurveComposite()) ; + PtrOwner pSecLocApprox( CreateBasicCurveComposite()) ; if ( IsNull( pSecLocApprox) || ! pSecLocApprox->FromPolyLine( PL) || ! pSecLocApprox->IsValid()) @@ -708,18 +709,20 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d plProj.Set( ORIG, *vtStatic) ; if ( ! plProj.IsValid()) return nullptr ; - // porto la sezione nel frame definito dalla guida proeittando la Z nel piano definito da vtStatic - Point3d ptS_proj( vtStart.x, vtStart.y, vtStart.z) ; - ptS_proj = ProjectPointOnPlane( ptS_proj, plProj) ; - Vector3d vtStartH( ptS_proj.x, ptS_proj.y, ptS_proj.z) ; - if ( ! vtStartH.Normalize()) + // porto la sezione nel frame definito dalla guida, tenendo il versore X nel piano definito da vtStatic + Vector3d vtX = vtStart ; + vtX.Rotate( *vtStatic, 90) ; + Point3d ptX_proj( vtX.x, vtX.y, vtX.z) ; + ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; + vtX.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; + if ( ! vtX.Normalize()) return nullptr ; Frame3d frInitial ; - frInitial.Set( ptStart, vtStartH) ; + frInitial.Set( ptStart, vtStart, vtX) ; if ( ! frInitial.IsValid()) return nullptr ; pSecLocApprox->ToLoc( frInitial) ; - PL.ToLoc( frInitial) ; + PL.ToLoc( frInitial) ; //... porto anche la PolyLine del bordo della sezione // approssimo la guida mediante la tolleranza richiesta PolyLine PL_G ; if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL_G)) @@ -750,19 +753,15 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d 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, *vtStatic ^ vtTanCurr) ; + Vector3d vtX_curr = vtTanCurr ; + vtX_curr.Rotate( *vtStatic, 90) ; + Point3d ptX_proj( vtX_curr.x, vtX_curr.y, vtX_curr.z) ; + ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; + vtX_curr.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; + if ( ! vtX_curr.Normalize()) + return nullptr ; + frCurr.Set( ptCurr, vtTanCurr, vtX_curr) ; if ( ! frCurr.IsValid()) return nullptr ; if ( bFirstIter) { // memorizzo il primo frame di caso di caps @@ -770,7 +769,14 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d bFirstIter = false ; } // creazione del frame successivo - frSucc.Set( ptSucc, vtTanSucc, *vtStatic ^ vtTanSucc) ; + Vector3d vtX_succ = vtTanSucc ; + vtX_succ.Rotate( *vtStatic, 90) ; + ptX_proj.Set( vtX_succ.x, vtX_succ.y, vtX_succ.z) ; + ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; + vtX_succ.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; + if ( ! vtX_succ.Normalize()) + return nullptr ; + frSucc.Set( ptSucc, vtTanSucc, vtX_succ) ; if ( ! frSucc.IsValid()) return nullptr ; frCaps_end = frSucc ; // aggiorno il frame finale @@ -949,9 +955,68 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d //------------------------------------------------------------------------------- ISurfTriMesh* -GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic) +GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds, + double dLinTol, Vector3d* vtStatic) { - return nullptr ; + // verifica dei parametri + if ( pSfrSect == nullptr || pGuide == nullptr) + return nullptr ; + + // creo la Trimesh da restituire + PtrOwner pStmSwept( CreateBasicSurfTriMesh()) ; + if ( IsNull( pStmSwept) || ! pStmSwept->AdjustTopology()) + return nullptr ; + + StmFromTriangleSoup StmSoup ; + StmSoup.Start() ; + // per ogni loop della superficie, creo una Swept + for ( int c = 0 ; c < pSfrSect->GetChunkCount() ; ++ c) { + for ( int l = 0 ; l < pSfrSect->GetLoopCount( c) ; ++ l) { + // recupero il loop + PtrOwner pCrvLoop( pSfrSect->GetLoop( c, l)) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return nullptr ; + // creo la Trimesh Swept + PtrOwner pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, false, dLinTol, vtStatic)) ; + if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid()) + return nullptr ; + // aggiungo la Swept ricavata al risultato finale ( come triangoli ) + StmSoup.AddSurfTriMesh( *pStmLoopSwept) ; + } + } + StmSoup.End() ; + if ( ! pStmSwept.Set( StmSoup.GetSurf()) || IsNull( pStmSwept) || + ! pStmSwept->IsValid() || ! pStmSwept->AdjustTopology()) + return nullptr ; + + + // se rischista chiusura... + // NB. Controllo solo che al guida non sia chiusa, la sezione derivando da una Flatregion è chiusa per + // definizione + if ( bCapEnds && ! pGuide->IsClosed()) { + // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta ) + PtrOwner pSci( pSfrSect->GetAuxSurf()->Clone()) ; + if ( IsNull( pSci) || ! pSci->IsValid()) + return nullptr ; + pStmSwept->DoSewing( *pSci) ; + // recupero i loops alla fine + POLYLINEVECTOR vPL ; + if ( ! pStmSwept->GetLoops( vPL)) + return nullptr ; + // creo la superficie alla fine e la attacco + PtrOwner pSce( CreateSurfTriMesh()) ; + if ( ! pSce->CreateByRegion( vPL)) + return nullptr ; + // attacco la superficie finale alla swept + pSce->Invert() ; + pStmSwept->DoSewing( *pSce) ; + } + // se superficie risultante chiusa, verifico che la normale sia verso l'esterno + double dVol ; + if ( pStmSwept->GetVolume( dVol) && dVol < 0) + pStmSwept->Invert() ; + + return Release( pStmSwept) ; } //------------------------------------------------------------------------------- From 104726c5ee92771e0a53de06e5a39273440404e1 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 19 Mar 2024 09:01:46 +0100 Subject: [PATCH 9/9] EgtGeomKernel : - migliorie varie. --- RotationMinimizeFrame.cpp | 10 ++- StmFromCurves.cpp | 137 ++++++++++++++++++++++++++------------ 2 files changed, 105 insertions(+), 42 deletions(-) diff --git a/RotationMinimizeFrame.cpp b/RotationMinimizeFrame.cpp index 9691c96..ad4f49c 100644 --- a/RotationMinimizeFrame.cpp +++ b/RotationMinimizeFrame.cpp @@ -86,8 +86,8 @@ RotationMinimizeFrame::GetFrameAtLength( const Frame3d& frAct, const double dLen // 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() ; + // ( vt_s è implicito ) double dUNext ; // parametro sulla curva nello step successivo Point3d ptNext ; // punto sulla curva allo step successivo @@ -95,34 +95,42 @@ RotationMinimizeFrame::GetFrameAtLength( const Frame3d& frAct, const double dLen // 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... diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 9b71de6..a86c90b 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -658,26 +658,31 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d // verifica parametri if ( pSect == nullptr || pGuide == nullptr) 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 ; + // determino se la sezione è chiusa bool bSectClosed = PL.IsClosed() ; // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; + // definisco la superficie da restituire ( definendo la sua tolleranza ) PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM)) return nullptr ; pSTM->SetLinearTolerance( dLinTol) ; + // calcolo punto e versore tangente iniziale - Point3d ptStart ; - pGuide->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pGuide->GetStartDir( vtStart) ; - // inizializzazione del frame iniziale + Point3d ptStart ; pGuide->GetStartPoint( ptStart) ; + Vector3d vtStart ; pGuide->GetStartDir( vtStart) ; + // inizializzazione del frame iniziale ( viene definito a seconda dei casi ) Frame3d frStart ; + + /* GUIDA PIANA */ + // verifico che la linea guida sia piana Plane3d plGuide ; if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) { @@ -688,13 +693,14 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d ( 2) mediante l'algoritmo del Rotation Minimize Frame */ + // recupero la sezione dalla PolyLine approssimata come Curva PtrOwner pSecLocApprox( CreateBasicCurveComposite()) ; if ( IsNull( pSecLocApprox) || ! pSecLocApprox->FromPolyLine( PL) || ! pSecLocApprox->IsValid()) return nullptr ; - // recupero il frame iniziale sulla guida + // recupero il frame iniziale sulla guida ( Origine sul punto iniziale e asse Z tangente ) frStart.Set( ptStart, vtStart) ; if ( ! frStart.IsValid()) return nullptr ; @@ -704,152 +710,179 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d Frame3d frCaps_end ; if ( vtStatic != nullptr) { // (1) versore statico + // creo il piano di proiezione con normale definita dal vettore Plane3d plProj ; plProj.Set( ORIG, *vtStatic) ; if ( ! plProj.IsValid()) return nullptr ; - // porto la sezione nel frame definito dalla guida, tenendo il versore X nel piano definito da vtStatic - Vector3d vtX = vtStart ; - vtX.Rotate( *vtStatic, 90) ; - Point3d ptX_proj( vtX.x, vtX.y, vtX.z) ; - ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; - vtX.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; - if ( ! vtX.Normalize()) - return nullptr ; - Frame3d frInitial ; - frInitial.Set( ptStart, vtStart, vtX) ; + + // porto la sezione nel frame definito dalla guida, tenendo il versore X del frame nel piano + // definito da vtStatic + Vector3d vtX = vtStart ; // versore tangente alla curva + vtX.Rotate( *vtStatic, 90) ; // ruoto di 90 gradi rispetto a vtStatic + OrthoCompo( vtX, *vtStatic) ; // tengo la componente nel piano + vtX.Normalize() ; // normalizzo + Frame3d frInitial ; frInitial.Set( ptStart, vtStart, vtX) ; // creo il frame if ( ! frInitial.IsValid()) return nullptr ; + + // porto la sezione nel riferimento pSecLocApprox->ToLoc( frInitial) ; PL.ToLoc( frInitial) ; //... porto anche la PolyLine del bordo della sezione + // 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 ; - // punto attuale e punto successivo + + // punto attuale e punto successivo sulla guida su cui definire il frame Point3d ptCurr, ptSucc ; if ( ! PL_G.GetFirstPoint( ptCurr)) return nullptr ; bool bNextPoint = PL_G.GetNextPoint( ptSucc) ; if ( ! bNextPoint) return nullptr ; + // 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 ; + bool bFirstIter = true ; // per salvare il frame iniziale nel caso di caps 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 + + // recupero il versore tangente riferito al punto successivo sulla guida if ( ! pGuide->GetPointD1D2( dParSucc, ICurve::FROM_MINUS, ptSucc, &vtTanSucc) || ! vtTanSucc.Normalize()) return nullptr ; - // creazione del frame corrente + + // creazione del frame nel punto corrente Vector3d vtX_curr = vtTanCurr ; vtX_curr.Rotate( *vtStatic, 90) ; - Point3d ptX_proj( vtX_curr.x, vtX_curr.y, vtX_curr.z) ; - ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; - vtX_curr.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; - if ( ! vtX_curr.Normalize()) - return nullptr ; + OrthoCompo( vtX_curr, *vtStatic) ; + vtX_curr.Normalize() ; frCurr.Set( ptCurr, vtTanCurr, vtX_curr) ; if ( ! frCurr.IsValid()) return nullptr ; - if ( bFirstIter) { // memorizzo il primo frame di caso di caps + + // memorizzo il primo frame di caso di caps + if ( bFirstIter) { frCaps_start = frCurr ; bFirstIter = false ; } - // creazione del frame successivo + + // creazione del frame nel punto successivo Vector3d vtX_succ = vtTanSucc ; vtX_succ.Rotate( *vtStatic, 90) ; - ptX_proj.Set( vtX_succ.x, vtX_succ.y, vtX_succ.z) ; - ptX_proj = ProjectPointOnPlane( ptX_proj, plProj) ; - vtX_succ.Set( ptX_proj.x, ptX_proj.y, ptX_proj.z) ; - if ( ! vtX_succ.Normalize()) - return nullptr ; + OrthoCompo( vtX_curr, *vtStatic) ; + vtX_succ.Normalize() ; frSucc.Set( ptSucc, vtTanSucc, vtX_succ) ; if ( ! frSucc.IsValid()) return nullptr ; - frCaps_end = frSucc ; // aggiorno il frame finale + + + frCaps_end = frSucc ; // aggiorno il frame finale ad ogni step + // definisco la sezione allo step corrente PtrOwner pSecCurr( pSecLocApprox->Clone()) ; if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) return nullptr ; - // porto la sezione corrente nel frame attuale + + // considero la sezione ( in locale ) come vista dal globale if ( ! pSecCurr->ToGlob( frCurr)) return nullptr ; + // definisco la sezione allo step successivo PtrOwner pSecSucc( pSecLocApprox->Clone()) ; if ( IsNull( pSecSucc) || ! pSecSucc->IsValid()) return nullptr ; - // porto questa sezione nel frame allo step successivo + + // considero la sezione ( in locale ) come vista dal globale if ( ! pSecSucc->ToGlob( frSucc)) return nullptr ; + // creo la rigata tra queste due sezioni PtrOwner 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_G.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 + // la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva pSTM->Invert() ; } else { // (2) Rotation Minimize Frame + // porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida pSecLocApprox->ToLoc( frStart) ; PL.ToLoc( frStart) ; + // 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 pSecCurr( pSecLocApprox->Clone()) ; if ( IsNull( pSecCurr) || ! pSecCurr->IsValid()) return nullptr ; - // porto la sezione corrente nel frame attuale + + // considero la sezione ( in locale ) come vista dal globale if ( ! pSecCurr->ToGlob( vRMF[i])) return nullptr ; + // definisco la sezione allo step successivo PtrOwner pSecSucc( pSecLocApprox->Clone()) ; if ( IsNull( pSecSucc) || ! pSecSucc->IsValid()) return nullptr ; - // porto questa sezione nel frame allo step successivo + + // considero la sezione ( in locale ) come vista dal globale if ( ! pSecSucc->ToGlob( vRMF[i+1])) return nullptr ; + // creo la rigata tra queste due sezioni PtrOwner 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 versore 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 + // se richiesti caps e sezione chiusa e guida aperta + // (1) vtStatic, (2) Rotation Minimize Frame if ( bCapEnds && bSectClosed && ! bGuideClosed) { + // aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida ) PtrOwner pSci( CreateBasicSurfTriMesh()) ; if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) @@ -857,12 +890,15 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d pSci->ToGlob( frCaps_start) ; // unisco pSTM->DoSewing( *pSci) ; + // aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida ) PtrOwner pSce( CreateBasicSurfTriMesh()) ; if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL)) return nullptr ; pSce->ToGlob( frCaps_end) ; + pSce->Invert() ; // il versore z è definito dalle tangenti alla curva + // unisco pSTM->DoSewing( *pSce) ; } @@ -871,29 +907,32 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d double dVol ; if ( pSTM->GetVolume( dVol) && dVol < 0) pSTM->Invert() ; + // restituisco la superficie return Release( pSTM) ; } /* + GUIDA PIANA 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 pPrevCrv ; Point3d ptP ; bool bPoint = PL.GetFirstPoint( ptP) ; while ( bPoint) { - // nuova curva + // nuova curva ( definita dall'Offset ) OffsetCurve OffsCrv ; if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0) return nullptr ; @@ -901,20 +940,27 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d 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 pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; if ( IsNull( pSr)) return nullptr ; + + // unisco pSTM->DoSewing( *pSr) ; } + // 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) { + // verifico che le due estremità siano chiuse e piatte POLYLINEVECTOR vPL ; if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) @@ -924,12 +970,16 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d return nullptr ; if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL)) return nullptr ; + // aggiungo il cap sull'inizio PtrOwner 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 ; @@ -937,18 +987,23 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d Vector3d vtEnd ; pGuide->GetEndDir( vtEnd) ; frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ; + // aggiungo il cap sulla fine PtrOwner 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) ; }