EgtGeomKernel :

- modifiche per RotationMinimizingFrame e RotationXplaneFrame
- aggiornato calcolo superfici TriMesh da Swept di curva o di regione.
This commit is contained in:
Dario Sassi
2024-04-05 16:55:20 +02:00
parent 015065f3c8
commit 2bd53476ca
7 changed files with 538 additions and 467 deletions
+3 -2
View File
@@ -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>
+7 -4
View File
@@ -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
View File
@@ -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 ;
-43
View File
@@ -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
} ;
+223
View File
@@ -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
View File
@@ -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() ;
+4
View File
@@ -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))