EgtGeomKernel :
- modifiche per RotationMinimizingFrame e RotationXplaneFrame - aggiornato calcolo superfici TriMesh da Swept di curva o di regione.
This commit is contained in:
@@ -320,6 +320,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||
<ClCompile Include="SbzStandard.cpp" />
|
||||
<ClCompile Include="Voronoi.cpp" />
|
||||
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
|
||||
@@ -332,6 +333,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
@@ -463,8 +466,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="VolZmapGraphics.cpp" />
|
||||
<ClCompile Include="VolZmapVolume.cpp" />
|
||||
<ClCompile Include="VolZmap.cpp" />
|
||||
<ClInclude Include="RotationMinimizingFrame.h" />
|
||||
<ClInclude Include="IntersLineSurfBez.h" />
|
||||
<ClInclude Include="Voronoi.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -531,6 +531,9 @@
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RotationXplaneFrame.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1199,11 +1202,11 @@
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RotationMinimizingFrame.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IntersLineSurfBez.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
+77
-114
@@ -1,5 +1,5 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2024
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RotationMinimizingFrame.cpp Data : 05.03.24 Versione : 2.6d1
|
||||
// Contenuto : Classe per RotationMinimizeFrame
|
||||
@@ -13,23 +13,26 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "RotationMinimizingFrame.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
RotationMinimizingFrame::RotationMinimizingFrame( const ICurve* pCrv, const Frame3d& fr_Start)
|
||||
bool
|
||||
RotationMinimizingFrame::Set( const ICurve* pCrv, const Frame3d& fr_Start)
|
||||
{
|
||||
// pulisco
|
||||
Clear() ;
|
||||
// verifico i parametri
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid() ||
|
||||
! fr_Start.IsValid())
|
||||
return false ;
|
||||
// assegno i parametri
|
||||
m_pCrv = pCrv->Clone() ;
|
||||
m_Frame0 = fr_Start ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
RotationMinimizingFrame::~RotationMinimizingFrame( void)
|
||||
{
|
||||
Clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -40,7 +43,6 @@ RotationMinimizingFrame::Clear( void)
|
||||
if ( m_pCrv != nullptr)
|
||||
delete m_pCrv ;
|
||||
m_pCrv = nullptr ;
|
||||
|
||||
// reset del frame di partenza
|
||||
m_Frame0.Reset() ;
|
||||
|
||||
@@ -49,7 +51,7 @@ RotationMinimizingFrame::Clear( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizingFrame::IsValid()
|
||||
RotationMinimizingFrame::IsValid( void)
|
||||
{
|
||||
// controllo validità della curva
|
||||
if ( m_pCrv == nullptr || ! m_pCrv->IsValid())
|
||||
@@ -69,12 +71,11 @@ RotationMinimizingFrame::IsValid()
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizingFrame::GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext)
|
||||
RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dParNext, Frame3d& frNext)
|
||||
{
|
||||
/*
|
||||
Double Reflection
|
||||
@@ -86,28 +87,21 @@ RotationMinimizingFrame::GetFrameAtLength( const Frame3d& frAct, const double dL
|
||||
if ( ! frAct.IsValid())
|
||||
return false ;
|
||||
|
||||
// origine del frame e versori ( ptAct, [ vt_r, vt_s, vt_t])
|
||||
// origine del frame e versori ( ptCurr, [ vtCurrR, vtCurrS, vtCurrT])
|
||||
Point3d ptCurr = frAct.Orig() ;
|
||||
Vector3d vt_r = frAct.VersX() ;
|
||||
Vector3d vt_t = frAct.VersZ() ;
|
||||
// ( vt_s è implicito )
|
||||
Vector3d vtCurrR = frAct.VersX() ;
|
||||
Vector3d vtCurrT = 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
|
||||
// punto i-esimo sulla curva e suo vettore tangente
|
||||
Point3d ptNext ;
|
||||
Vector3d vtNextT ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) ||
|
||||
! vtNextT.Normalize())
|
||||
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
|
||||
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
|
||||
abs( ( ptNext - ptCurr) * ( vtNextT + vtCurrT)) < EPS_ZERO) // non esiste il piano R2
|
||||
return false ;
|
||||
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
@@ -119,11 +113,11 @@ RotationMinimizingFrame::GetFrameAtLength( const Frame3d& frAct, const double dL
|
||||
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 ;
|
||||
Vector3d vt_r_L = vtCurrR - ( 2 / dPar1) * ( vR1_norm * vtCurrR) * vR1_norm ;
|
||||
Vector3d vt_t_L = vtCurrT - ( 2 / dPar1) * ( vR1_norm * vtCurrT) * vR1_norm ;
|
||||
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR2_norm = vt_t_next - vt_t_L ;
|
||||
Vector3d vR2_norm = vtNextT - vt_t_L ;
|
||||
if ( ! vR2_norm.IsValid())
|
||||
return false ;
|
||||
|
||||
@@ -131,65 +125,47 @@ RotationMinimizingFrame::GetFrameAtLength( const Frame3d& frAct, const double dL
|
||||
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 ;
|
||||
|
||||
return frNext.Set( ptNext, vtNextT, vt_r_next) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizingFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform)
|
||||
RotationMinimizingFrame::GetFramesByStep( double dStep, bool bUniform, FRAME3DVECTOR& vRMFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sullo step
|
||||
dStep = max( 10 * EPS_SMALL, dStep) ;
|
||||
|
||||
// controllo validità
|
||||
if ( ! IsValid()) {
|
||||
Clear() ;
|
||||
// lunghezza della curva
|
||||
double dCrvLen = 0. ;
|
||||
if ( ! m_pCrv->GetLength( dCrvLen) || dCrvLen < 10 * EPS_SMALL)
|
||||
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 ;
|
||||
int nStep = int( ceil( dCrvLen / dStep)) ;
|
||||
double dMyStep = ( bUniform ? dCrvLen / nStep : dStep) ;
|
||||
|
||||
// lunghezza della curva identificata dal punto successivo
|
||||
double dLenNext ;
|
||||
|
||||
// step corrente
|
||||
double dMyStep = dStep ;
|
||||
if ( bUniform)
|
||||
dMyStep = dLen / nStep ;
|
||||
// inserisco il frame iniziale nel vettore dei riferimenti
|
||||
vRMFrames.clear() ;
|
||||
vRMFrames.reserve( nStep + 1) ;
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
|
||||
// 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))
|
||||
for ( int i = 1 ; i <= nStep ; ++ i) {
|
||||
// ricavo il parametro della curva allo step i-esimo
|
||||
double dParNext ;
|
||||
if ( ! m_pCrv->GetParamAtLength( min( i * dMyStep, dCrvLen - EPS_SMALL), dParNext))
|
||||
return false ;
|
||||
// aggiornamento vettore dei frame
|
||||
// ricavo il frame alla posizione calcolata
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtParam( vRMFrames[i-1], dParNext, frNext))
|
||||
return false ;
|
||||
// inserisco nuovo frame nel vettore dei riferimenti
|
||||
vRMFrames.push_back( frNext) ;
|
||||
}
|
||||
|
||||
@@ -198,70 +174,57 @@ RotationMinimizingFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizingFrame::GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals)
|
||||
RotationMinimizingFrame::GetFramesBySplit( int nIntervals, FRAME3DVECTOR& vRMFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sul numero di intervalli
|
||||
nIntervals = max( 1, nIntervals) ;
|
||||
|
||||
// ricavo lo step associato
|
||||
// ricavo lo step
|
||||
double dLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
// ricavo lo step associato
|
||||
double dStep = dLen / nIntervals ;
|
||||
|
||||
return GetFramesByStep( vRMFrames, dStep) ;
|
||||
return GetFramesByStep( dStep, true, vRMFrames) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizingFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol)
|
||||
RotationMinimizingFrame::GetFramesByTolerance( double dTol, FRAME3DVECTOR& vRMFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// 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 ;
|
||||
int nStep = PL.GetLineNbr() ;
|
||||
|
||||
// ricavo la lunghezza della curva
|
||||
double dCrvLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dCrvLen))
|
||||
return false ;
|
||||
// inserisco il frame iniziale nel vettore dei riferimenti
|
||||
vRMFrames.clear() ;
|
||||
vRMFrames.reserve( nStep + 1) ;
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
|
||||
// devo calcolare il RMF su ogni punto ricavato dall'approssimazione
|
||||
// eseguo il calcolo dei frame 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) ;
|
||||
PL.GetFirstPoint( ptCurr) ;
|
||||
double dParNext ;
|
||||
Point3d ptNext ;
|
||||
while ( PL.GetNextUPoint( &dParNext, &ptNext)) {
|
||||
// ricavo il Frame associato a questa posizione
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtParam( vRMFrames.back(), dParNext, frNext))
|
||||
return false ;
|
||||
vRMFrames.emplace_back( frNext) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 <vector>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
typedef std::vector<Frame3d> 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
|
||||
} ;
|
||||
@@ -0,0 +1,223 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RotationXplaneFrame.cpp Data : 05.04.24 Versione : 2.6d1
|
||||
// Contenuto : Classe per RotationXplaneFrame.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 05.04.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::Set( const ICurve* pCrv, const Vector3d& vtNorm, const Vector3d& vtNearX)
|
||||
{
|
||||
// pulisco
|
||||
Clear() ;
|
||||
// verifico i parametri
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid() ||
|
||||
! vtNorm.IsValid() || vtNorm.IsSmall() || ! vtNearX.IsValid())
|
||||
return false ;
|
||||
// assegno i parametri
|
||||
m_pCrv = pCrv->Clone() ;
|
||||
m_vtNorm = vtNorm ;
|
||||
m_vtNearX = vtNearX ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::Clear( void)
|
||||
{
|
||||
// pulizia della curva
|
||||
if ( m_pCrv != nullptr)
|
||||
delete m_pCrv ;
|
||||
m_pCrv = nullptr ;
|
||||
// reset dei vettori
|
||||
m_vtNorm = V_NULL ;
|
||||
m_vtNearX = V_NULL ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::IsValid( void)
|
||||
{
|
||||
// controllo validità della curva
|
||||
if ( m_pCrv == nullptr || ! m_pCrv->IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo della normale al piano
|
||||
if ( m_vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::GetFrameAtParam( const Frame3d& frAct, const double dParNext, Frame3d& frNext)
|
||||
{
|
||||
// verifico il riferimento corrente
|
||||
if ( ! frAct.IsValid())
|
||||
return false ;
|
||||
|
||||
// recupero punto e tangente nel nuovo punto
|
||||
Point3d ptNext ;
|
||||
Vector3d vtNext ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNext) ||
|
||||
! vtNext.Normalize())
|
||||
return false ;
|
||||
|
||||
// calcolo il nuovo riferimento
|
||||
Vector3d vtAxX = m_vtNorm ^ vtNext ;
|
||||
if ( vtAxX.IsSmall())
|
||||
vtAxX = frAct.VersX() ;
|
||||
else if ( vtAxX * frAct.VersX() < 0)
|
||||
vtAxX.Invert() ;
|
||||
|
||||
// lo imposto
|
||||
return frNext.Set( ptNext, vtNext, vtAxX) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::GetFramesByStep( double dStep, bool bUniform, FRAME3DVECTOR& vRXFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sullo step
|
||||
dStep = max( 10 * EPS_SMALL, dStep) ;
|
||||
|
||||
// lunghezza della curva
|
||||
double dCrvLen = 0. ;
|
||||
if ( ! m_pCrv->GetLength( dCrvLen) || dCrvLen < 10 * EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// numero e lunghezza effettiva di ogni step
|
||||
int nStep = int( ceil( dCrvLen / dStep)) ;
|
||||
double dMyStep = ( bUniform ? dCrvLen / nStep : dStep) ;
|
||||
|
||||
// calcolo il riferimento iniziale
|
||||
Point3d ptStart ; m_pCrv->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ; m_pCrv->GetStartDir( vtStart) ;
|
||||
Vector3d vtAxX = m_vtNorm ^ vtStart ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = OrthoCompo( m_vtNearX, m_vtNorm) ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = FromUprightOrtho( m_vtNorm) ;
|
||||
vtAxX.Rotate( m_vtNorm, 0, 1) ;
|
||||
}
|
||||
}
|
||||
Frame3d frStart ;
|
||||
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
|
||||
return false ;
|
||||
|
||||
// inserisco questo frame nel vettore dei riferimenti
|
||||
vRXFrames.clear() ;
|
||||
vRXFrames.reserve( nStep + 1) ;
|
||||
vRXFrames.push_back( frStart) ;
|
||||
|
||||
// ciclo sugli step in cui la curva è suddivisa
|
||||
for ( int i = 1 ; i <= nStep ; ++ i) {
|
||||
// ricavo il parametro della curva allo step i-esimo
|
||||
double dParNext ;
|
||||
if ( ! m_pCrv->GetParamAtLength( min( i * dMyStep, dCrvLen - EPS_SMALL), dParNext))
|
||||
return false ;
|
||||
// ricavo il frame alla posizione calcolata
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtParam( vRXFrames[i-1], dParNext, frNext))
|
||||
return false ;
|
||||
// inserisco nuovo frame nel vettore dei riferimenti
|
||||
vRXFrames.push_back( frNext) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::GetFramesBySplit( int nIntervals, FRAME3DVECTOR& vRXFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sul numero di intervalli
|
||||
nIntervals = max( 1, nIntervals) ;
|
||||
|
||||
// ricavo lo step
|
||||
double dLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
return false ;
|
||||
double dStep = dLen / nIntervals ;
|
||||
|
||||
return GetFramesByStep( dStep, true, vRXFrames) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationXplaneFrame::GetFramesByTolerance( double dTol, FRAME3DVECTOR& vRXFrames)
|
||||
{
|
||||
// controllo validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo sulla tolleranza
|
||||
dTol = max( EPS_SMALL, dTol) ;
|
||||
|
||||
// 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 ;
|
||||
int nStep = PL.GetLineNbr() ;
|
||||
|
||||
// calcolo il riferimento iniziale
|
||||
Point3d ptStart ; m_pCrv->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ; m_pCrv->GetStartDir( vtStart) ;
|
||||
Vector3d vtAxX = m_vtNorm ^ vtStart ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = OrthoCompo( m_vtNearX, m_vtNorm) ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = FromUprightOrtho( m_vtNorm) ;
|
||||
vtAxX.Rotate( m_vtNorm, 0, 1) ;
|
||||
}
|
||||
}
|
||||
Frame3d frStart ;
|
||||
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
|
||||
return false ;
|
||||
|
||||
// inserisco questo frame nel vettore dei riferimenti
|
||||
vRXFrames.clear() ;
|
||||
vRXFrames.reserve( nStep + 1) ;
|
||||
vRXFrames.push_back( frStart) ;
|
||||
|
||||
// eseguo il calcolo dei frame sui punti della polyline approssimante
|
||||
Point3d ptCurr ;
|
||||
PL.GetFirstPoint( ptCurr) ;
|
||||
double dParNext ;
|
||||
Point3d ptNext ;
|
||||
while ( PL.GetNextUPoint( &dParNext, &ptNext)) {
|
||||
// ricavo il Frame associato a questa posizione
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtParam( vRXFrames.back(), dParNext, frNext))
|
||||
return false ;
|
||||
vRXFrames.emplace_back( frNext) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+224
-304
@@ -19,16 +19,15 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "Voronoi.h"
|
||||
#include "RotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <EgtDev/Include/EGkIntersCurves.h>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -652,284 +651,36 @@ GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBev
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic)
|
||||
static ISurfTriMesh*
|
||||
GetSurfTriMeshSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
// determino se la sezione è chiusa
|
||||
bool bSectClosed = pSect->IsClosed() ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
|
||||
// calcolo la polilinea che approssima la sezione
|
||||
// riferimento all'inizio della linea guida
|
||||
Frame3d frStart ;
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
|
||||
// calcolo la polilinea che approssima la sezione
|
||||
PolyLine PL ;
|
||||
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return nullptr ;
|
||||
|
||||
// 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<SurfTriMesh> 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 ( 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<CurveComposite> 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<ICurve> 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<ICurve> 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<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
|
||||
// aggiornamento dei parametri
|
||||
ptCurr = ptSucc ; // il punto corrente diventa il successivo
|
||||
bNextPoint = PL_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<ICurve> 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<ICurve> 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<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
// la superficie definita dal RMF è invertita, il 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<SurfTriMesh> 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<SurfTriMesh> 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
|
||||
// porto la sezione in questo riferimento e ve la appiattisco
|
||||
if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
|
||||
return nullptr ;
|
||||
|
||||
// preparo collettore delle superfici componenti
|
||||
StmFromTriangleSoup StmFts ;
|
||||
if ( ! StmFts.Start())
|
||||
return nullptr ;
|
||||
|
||||
// superficie swept
|
||||
PtrOwner<ICurve> pPrevCrv ;
|
||||
Point3d ptP ;
|
||||
@@ -943,23 +694,29 @@ 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<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr))
|
||||
return nullptr ;
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
// inserisco nel collettore
|
||||
StmFts.AddSurfTriMesh( *pSr) ;
|
||||
}
|
||||
|
||||
// salvo la curva come prossima precedente
|
||||
pPrevCrv.Set( pCurrCrv) ;
|
||||
|
||||
// prossimo punto
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
|
||||
// recupero la supeficie risultante
|
||||
if ( ! StmFts.End())
|
||||
return nullptr ;
|
||||
PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
// salvo tolleranza lineare usata
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
@@ -1002,59 +759,222 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static ISurfTriMesh*
|
||||
GetSurfTriMeshSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// determino se la sezione è chiusa
|
||||
bool bSectClosed = pSect->IsClosed() ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
bool bRMF = vtAx.IsSmall() ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
Frame3d frStart ;
|
||||
if ( bRMF) {
|
||||
if ( ! frStart.Set( ptStart, vtStart))
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtAxX = vtAx ^ vtStart ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = FromUprightOrtho( vtAx) ;
|
||||
vtAxX.Rotate( vtAx, 0, 1) ;
|
||||
}
|
||||
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// calcolo la polilinea che approssima la sezione
|
||||
PolyLine PL ;
|
||||
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return nullptr ;
|
||||
|
||||
// recupero la sezione dalla PolyLine approssimata come Curva
|
||||
PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pSecLocApprox) ||
|
||||
! pSecLocApprox->FromPolyLine( PL) ||
|
||||
! pSecLocApprox->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
|
||||
PL.ToLoc( frStart) ;
|
||||
pSecLocApprox->ToLoc( frStart) ;
|
||||
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
FRAME3DVECTOR vFrames ;
|
||||
if ( bRMF) {
|
||||
RotationMinimizingFrame RMF ;
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
RotationXplaneFrame RXF ;
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// preparo collettore delle superfici componenti
|
||||
StmFromTriangleSoup StmFts ;
|
||||
if ( ! StmFts.Start())
|
||||
return nullptr ;
|
||||
|
||||
// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
|
||||
for ( int i = 0 ; i < int( vFrames.size()) - 1 ; ++ i) {
|
||||
|
||||
// definisco la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecCurr->ToGlob( vFrames[i]))
|
||||
return nullptr ;
|
||||
|
||||
// definisco la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecSucc->ToGlob( vFrames[i+1]))
|
||||
return nullptr ;
|
||||
|
||||
// creo la rigata tra queste due sezioni
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
// la inverto
|
||||
pSr->Invert() ;
|
||||
// inserisco la superficie nel collettore
|
||||
StmFts.AddSurfTriMesh( *pSr) ;
|
||||
}
|
||||
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
|
||||
// aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSci->ToGlob( vFrames.front()) ;
|
||||
// aggiungo
|
||||
StmFts.AddSurfTriMesh( *pSci) ;
|
||||
|
||||
// aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSce->ToGlob( vFrames.back()) ;
|
||||
// inverto
|
||||
pSce->Invert() ;
|
||||
// aggiungo
|
||||
StmFts.AddSurfTriMesh( *pSce) ;
|
||||
}
|
||||
|
||||
// recupero la supeficie risultante
|
||||
if ( ! StmFts.End())
|
||||
return nullptr ;
|
||||
PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
// salvo tolleranza lineare usata
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSTM->GetVolume( dVol) && dVol < 0)
|
||||
pSTM->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds,
|
||||
double dLinTol, Vector3d* vtStatic)
|
||||
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx,
|
||||
bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// se la guida è piana
|
||||
Plane3d plGuide ;
|
||||
if ( pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
return GetSurfTriMeshSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ;
|
||||
|
||||
// altrimenti swept 3d
|
||||
return GetSurfTriMeshSwept3d( pSect, pGuide, vtAx, bCapEnds, dLinTol) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, const Vector3d& vtAx,
|
||||
bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica dei parametri
|
||||
if ( pSfrSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// creo la Trimesh da restituire
|
||||
PtrOwner<ISurfTriMesh> pStmSwept( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStmSwept) || ! pStmSwept->AdjustTopology())
|
||||
return nullptr ;
|
||||
|
||||
// predispongo collettore superfici componenti
|
||||
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) {
|
||||
for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
|
||||
// recupero il loop
|
||||
PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( c, l)) ;
|
||||
PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( nC, nL)) ;
|
||||
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
|
||||
return nullptr ;
|
||||
// creo la Trimesh Swept
|
||||
PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, false, dLinTol, vtStatic)) ;
|
||||
PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, vtAx, false, dLinTol)) ;
|
||||
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
|
||||
// Recupero la superficie
|
||||
if ( ! StmSoup.End())
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pStmSwept( StmSoup.GetSurf()) ;
|
||||
if ( IsNull( pStmSwept))
|
||||
return nullptr ;
|
||||
|
||||
// se rischiesta chiusura...
|
||||
// Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa
|
||||
if ( bCapEnds && ! pGuide->IsClosed()) {
|
||||
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta )
|
||||
PtrOwner<ISurfTriMesh> pSci( pSfrSect->GetAuxSurf()->Clone()) ;
|
||||
if ( IsNull( pSci) || ! pSci->IsValid())
|
||||
// recupero i loop all'inizio (dalla regione e apportunamente approssimati)
|
||||
POLYLINEVECTOR vPLi ;
|
||||
for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
|
||||
vPLi.emplace_back() ;
|
||||
if ( ! pSfrSect->ApproxLoopWithLines( nC, nL, dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLi.back()))
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( ! pSci->CreateByRegion( vPLi))
|
||||
return nullptr ;
|
||||
pStmSwept->DoSewing( *pSci) ;
|
||||
// recupero i loops alla fine
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pStmSwept->GetLoops( vPL))
|
||||
POLYLINEVECTOR vPLe ;
|
||||
if ( ! pStmSwept->GetLoops( vPLe))
|
||||
return nullptr ;
|
||||
// creo la superficie alla fine e la attacco
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( ! pSce->CreateByRegion( vPL))
|
||||
if ( ! pSce->CreateByRegion( vPLe))
|
||||
return nullptr ;
|
||||
// attacco la superficie finale alla swept
|
||||
pSce->Invert() ;
|
||||
|
||||
@@ -169,6 +169,10 @@ Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDe
|
||||
bool
|
||||
Vector3d::Normalize( double dEps)
|
||||
{
|
||||
// verifico validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// se già normalizzato, ok
|
||||
double dSqLen = x * x + y * y + z * z ;
|
||||
if ( abs( 1.0 - dSqLen) < ( 2 * 1000 * DBL_EPSILON))
|
||||
|
||||
Reference in New Issue
Block a user