diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj
index cb4717d..604464a 100644
--- a/EgtGeomKernel.vcxproj
+++ b/EgtGeomKernel.vcxproj
@@ -319,6 +319,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
@@ -462,6 +463,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index 2144f62..4f6765b 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -528,6 +528,9 @@
File di origine\GeoCreate
+
+ File di origine\Base
+
@@ -1196,6 +1199,12 @@
File di intestazione\Include
+
+ File di intestazione
+
+
+ File di intestazione
+
diff --git a/RotationMinimizingFrame.cpp b/RotationMinimizingFrame.cpp
new file mode 100644
index 0000000..edb3366
--- /dev/null
+++ b/RotationMinimizingFrame.cpp
@@ -0,0 +1,268 @@
+//----------------------------------------------------------------------------
+// EgalTech 2015-2024
+//----------------------------------------------------------------------------
+// File : RotationMinimizingFrame.cpp Data : 05.03.24 Versione : 2.6d1
+// Contenuto : Classe per RotationMinimizeFrame
+//
+//
+//
+// Modifiche : 05.03.24 RE Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+//--------------------------- Include ----------------------------------------
+#include "stdafx.h"
+#include "RotationMinimizingFrame.h"
+#include "GeoConst.h"
+
+using namespace std ;
+
+//----------------------------------------------------------------------------
+RotationMinimizingFrame::RotationMinimizingFrame( const ICurve* pCrv, const Frame3d& fr_Start)
+{
+ // assegno i parametri
+ m_pCrv = pCrv->Clone() ;
+ m_Frame0 = fr_Start ;
+}
+
+//----------------------------------------------------------------------------
+RotationMinimizingFrame::~RotationMinimizingFrame( void)
+{
+ Clear() ;
+}
+
+//----------------------------------------------------------------------------
+bool
+RotationMinimizingFrame::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
+RotationMinimizingFrame::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 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 ;
+
+}
+
+//----------------------------------------------------------------------------
+bool
+RotationMinimizingFrame::GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext)
+{
+ /*
+ Double Reflection
+ Computation of Rotation Minimizing Frame in Computer Graphics
+ Wenping Wang Bert Juttler Dayue Zheng Yang Liu
+ */
+
+ // 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_t = frAct.VersZ() ;
+ // ( vt_s è implicito )
+
+ 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
+RotationMinimizingFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform)
+{
+ // controllo sullo step
+ dStep = max( 10 * EPS_SMALL, dStep) ;
+
+ // controllo validità
+ if ( ! IsValid()) {
+ Clear() ;
+ return false ;
+ }
+
+ // calcolo lunghezza della curva
+ double dLen = 0. ;
+ if ( ! m_pCrv->GetLength( dLen))
+ return false ;
+
+ // in prima posizione viene inserito il frame iniziale
+ vRMFrames.push_back( m_Frame0) ;
+
+ // ricavo il numero degli step
+ int nStep = int( ceil( dLen / dStep)) ;
+ if ( nStep == 0) // se non ho step allora serve sono il frame iniziale
+ return true ;
+
+ // lunghezza della curva identificata dal punto successivo
+ double dLenNext ;
+
+ // 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 - 10 * EPS_SMALL, ( i + 1) * dMyStep) ;
+ // ricavo il frame alla lunghezza calcolata
+ Frame3d frNext ;
+ if ( ! GetFrameAtLength( vRMFrames[i], dLenNext, frNext))
+ return false ;
+ // aggiornamento vettore dei frame
+ vRMFrames.push_back( frNext) ;
+ }
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+RotationMinimizingFrame::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
+RotationMinimizingFrame::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 ;
+
+ // 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) ;
+ 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 ;
+ // 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))
+ return false ;
+ vRMFrames.emplace_back( frNext) ;
+ }
+ // passo al punto successivo
+ bPoint = PL.GetNextPoint( ptCurr) ;
+ }
+
+ return true ;
+}
diff --git a/RotationMinimizingFrame.h b/RotationMinimizingFrame.h
new file mode 100644
index 0000000..d382125
--- /dev/null
+++ b/RotationMinimizingFrame.h
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+// EgalTech 2015-2024
+//----------------------------------------------------------------------------
+// File : RotationMinimizingFrame.h Data : 05.03.24 Versione : 2.6d1
+// Contenuto : Dichiarazione della classe RotationMinimizingFrame.
+//
+//
+//
+// Modifiche : 05.03.24 RE Creazione modulo.
+
+//
+//----------------------------------------------------------------------------
+
+#pragma once
+
+#include "/EgtDev/Include/EGkFrame3d.h"
+#include "/EgtDev/Include/EGkCurve.h"
+#include
+
+//----------------------------------------------------------------------------
+typedef std::vector FRAME3DVECTOR ;
+
+//----------------------------------------------------------------------------
+class RotationMinimizingFrame
+{
+ public :
+ RotationMinimizingFrame( const ICurve* pCrv, const Frame3d& fr_Start) ;
+ ~RotationMinimizingFrame( void) ;
+
+ public :
+ 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
+} ;
diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp
index 0af869f..7ee3d52 100644
--- a/StmFromCurves.cpp
+++ b/StmFromCurves.cpp
@@ -1,4 +1,4 @@
-//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1
@@ -19,10 +19,12 @@
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "Voronoi.h"
+#include "RotationMinimizingFrame.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
+#include "/EgtDev/Include/EGkSfrCreate.h"
#include
#include
#include
@@ -110,9 +112,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 ;
@@ -156,7 +158,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 ;
@@ -288,7 +290,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
@@ -332,7 +334,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 ;
@@ -373,7 +375,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 ;
@@ -452,7 +454,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 ;
@@ -475,7 +477,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) ;
}
@@ -552,7 +554,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 ;
@@ -651,46 +653,289 @@ 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)
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
+
+ // determino se la sezione è chiusa
bool bSectClosed = PL.IsClosed() ;
- // verifico che la linea guida sia piana
- Plane3d plGuide ;
- if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
- return nullptr ;
- // determino se la guida è chiusa
+ // determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
- // riferimento all'inizio della linea guida
- Frame3d frStart ;
- Point3d ptStart ;
- pGuide->GetStartPoint( ptStart) ;
- Vector3d vtStart ;
- pGuide->GetStartDir( vtStart) ;
- 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
+
+ // 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 ( 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)) {
+
+ /*
+ 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 dalla PolyLine approssimata come Curva
+ PtrOwner pSecLocApprox( CreateBasicCurveComposite()) ;
+ if ( IsNull( pSecLocApprox) ||
+ ! pSecLocApprox->FromPolyLine( PL) ||
+ ! pSecLocApprox->IsValid())
+ return nullptr ;
+
+ // recupero il frame iniziale sulla guida ( Origine sul punto iniziale e asse Z tangente )
+ frStart.Set( ptStart, vtStart) ;
+ if ( ! frStart.IsValid())
+ return nullptr ;
+
+ // tengo in memoria il frame nel punto iniziale e finale della guida in caso di caps
+ Frame3d frCaps_start ;
+ Frame3d frCaps_end ;
+
+ // (1) versore statico
+ if ( vtStatic != nullptr) {
+
+ // 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 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 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 ; // 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 guida
+ if ( ! pGuide->GetPointD1D2( dParSucc, ICurve::FROM_MINUS, ptSucc, &vtTanSucc) ||
+ ! vtTanSucc.Normalize())
+ return nullptr ;
+
+ // creazione del frame nel punto corrente
+ Vector3d vtX_curr = vtTanCurr ;
+ vtX_curr.Rotate( *vtStatic, 90) ;
+ OrthoCompo( vtX_curr, *vtStatic) ;
+ vtX_curr.Normalize() ;
+ frCurr.Set( ptCurr, vtTanCurr, vtX_curr) ;
+ if ( ! frCurr.IsValid())
+ return nullptr ;
+
+ // memorizzo il primo frame di caso di caps
+ if ( bFirstIter) {
+ frCaps_start = frCurr ;
+ bFirstIter = false ;
+ }
+
+ // creazione del frame nel punto successivo
+ Vector3d vtX_succ = vtTanSucc ;
+ vtX_succ.Rotate( *vtStatic, 90) ;
+ 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 ad ogni step
+
+ // definisco la sezione allo step corrente
+ PtrOwner pSecCurr( pSecLocApprox->Clone()) ;
+ if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
+ return nullptr ;
+
+ // 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 ;
+
+ // 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 versore Z è diretto come la tangente della curva
+ pSTM->Invert() ;
+
+ }
+
+ // (2) Rotation Minimizing Frame
+ else {
+
+ // 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
+ RotationMinimizingFrame 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 ;
+
+ // 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 ;
+
+ // 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
+ // (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))
+ return nullptr ;
+ 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) ;
+ }
+
+ // 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) ;
+
+ }
+
+ /*
+ 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 ;
@@ -698,21 +943,26 @@ 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)
+
+ // 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
+ // verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ;
@@ -726,6 +976,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
return nullptr ;
pSci->ToGlob( frStart) ;
+ // unisco
pSTM->DoSewing( *pSci) ;
// riferimento alla fine della linea guida
Frame3d frEnd ;
@@ -740,6 +991,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
return nullptr ;
pSce->Invert() ;
pSce->ToGlob( frEnd) ;
+ // unisco
pSTM->DoSewing( *pSce) ;
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
@@ -750,6 +1002,72 @@ 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)
+{
+ // 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) ;
+}
+
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
@@ -757,7 +1075,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 ;
@@ -771,7 +1089,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()) ;
@@ -937,7 +1255,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 ;
@@ -970,10 +1288,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 ;