Compare commits

..

1 Commits

Author SHA1 Message Date
Daniele Bariletti 6eb621d1e1 EgtGeomKernel :
- nuova versione dell'intersezione linea-linea che richiede revisioni anche delle intersezioni arco-linea e arco-arco.
2026-01-15 16:03:29 +01:00
63 changed files with 3824 additions and 11759 deletions
+1 -1
View File
@@ -151,7 +151,7 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
else { else {
double dParA = vIccInfo[i].IciA[0].dU ; double dParA = vIccInfo[i].IciA[0].dU ;
double dParB = vIccInfo[i].IciB[0].dU ; double dParB = vIccInfo[i].IciB[0].dU ;
if ( dParA > dParB) if ( abs( dParA - dEnd) < EPS_SMALL)
swap( dParA, dParB) ; swap( dParA, dParB) ;
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile // verifico se uno dei due intervalli dà origine ad un tratto trascurabile
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ; PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
-4
View File
@@ -140,20 +140,16 @@ MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) { if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
m_SCollInfo = scInfoCurr ; m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ; m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ; m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ; m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ; m_SCollInfo.nCrvF = l ;
} }
} }
else if ( dNewLenXY < dPrevLenXY) { else if ( dNewLenXY < dPrevLenXY) {
m_SCollInfo = scInfoCurr ; m_SCollInfo = scInfoCurr ;
m_SCollInfo.nChunkM = j ; m_SCollInfo.nChunkM = j ;
m_SCollInfo.nLoopM = 0 ;
m_SCollInfo.nCrvM = k ; m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = i ; m_SCollInfo.nChunkF = i ;
m_SCollInfo.nLoopF = 0 ;
m_SCollInfo.nCrvF = l ; m_SCollInfo.nCrvF = l ;
} }
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ; pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
+2 -2
View File
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
const SCollInfo& GetSCollInfo() const SCollInfo& GetSCollInfo()
{ return m_SCollInfo ;} { return m_SCollInfo ;}
protected : private :
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ; const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
const Point3d& ptCen, double& dAng) ; const Point3d& ptCen, double& dAng) ;
protected : private :
const SurfFlatRegion* m_pRegM ; const SurfFlatRegion* m_pRegM ;
const SurfFlatRegion* m_pRegF ; const SurfFlatRegion* m_pRegF ;
SCollInfo m_SCollInfo ; SCollInfo m_SCollInfo ;
-257
View File
@@ -1,257 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2026-2026
//----------------------------------------------------------------------------
// File : CASurfFrMove.cpp Data : 26.03.2026 Versione : 3.1c7
// Contenuto : Implementazione delle funzioni di movimento per SurfFlatRegion
// senza collisione con altri oggetti dello stesso tipo e nello
// stesso piano o in piani paralleli.
//
//
// Modifiche : 26.03.2026 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CAvSurfFrMove.h"
#include "SurfFlatRegion.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "CurveComposite.h"
#include "IntersLineArc.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkCAvSurfFrMove.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
// CASurfFrMove
//----------------------------------------------------------------------------
CAvSurfFrMove::CAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF)
{
// salvo puntatori alle regioni
m_pRegM = &SfrM ;
m_pRegF = &SfrF ;
}
//----------------------------------------------------------------------------
bool
CAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
{
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
m_CollInfo.nType = SCI_NONE ;
if ( ! ScdMove.Translate( vtDir, dLen))
return false ;
m_CollInfo = ScdMove.GetCollInfo() ;
return true ;
}
//----------------------------------------------------------------------------
bool
CAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
{
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
m_CollInfo.nType = SCI_NONE ;
return ScdMove.Rotate( ptCen, dAng) ;
}
//----------------------------------------------------------------------------
bool
MyCAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
{
// verifico validità regioni
if ( m_pRegM == nullptr || m_pRegF == nullptr)
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
return false ;
// reset info di collisione
m_SCollInfo.nType = SCI_NONE ;
// porto il vettore di movimento nel riferimento intrinseco e ne annullo la componente Z
Vector3d vtDirL = vtDir ;
vtDirL.ToLoc( m_pRegM->m_frF) ;
vtDirL.z = 0 ;
double dLenXY = vtDirL.Len() ;
if ( dLenXY < EPS_SMALL)
return true ;
vtDirL /= dLenXY ;
dLenXY *= dLen ;
double dNewLenXY = dLenXY ;
// ciclo sui chunk della seconda superficie
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
// ciclo sui bordi dei chunk
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
else {
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
pCrv2Loc = pCopyCrv ;
}
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
// ciclo sui chunk della prima superficie
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
// ciclo sui bordi del chunk
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
// per CAv non ha senso confrontare due loop interni tra di loro.
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
if ( nLF > 0 && nLM > 0)
continue ;
// curva corrente del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
// verifico la collisione tra le entità dei loop esterni dei due chunk
int k = 0 ;
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
while ( pCrv1 != nullptr) {
int l = 0 ;
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
while ( pCrv2 != nullptr) {
SCollInfo cInfoCurr ;
double dPrevLenXY = dNewLenXY ;
if ( ! TranslateCurveNoCollisionCurve( pCrv1, pCrv2, vtDirL, dNewLenXY, cInfoCurr))
return false ;
if ( abs( dNewLenXY - dPrevLenXY) < EPS_SMALL) {
if ( cInfoCurr.nType == SCI_LINE_LINE || cInfoCurr.nType == SCI_PNT_LINE) {
m_SCollInfo = cInfoCurr ;
m_SCollInfo.nChunkM = nCM ;
m_SCollInfo.nLoopM = nLM ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = nCF ;
m_SCollInfo.nLoopF = nLF ;
m_SCollInfo.nCrvF = l ;
}
}
else if ( dNewLenXY < dPrevLenXY) {
m_SCollInfo = cInfoCurr ;
m_SCollInfo.nChunkM = nCM ;
m_SCollInfo.nLoopM = nLM ;
m_SCollInfo.nCrvM = k ;
m_SCollInfo.nChunkF = nCF ;
m_SCollInfo.nLoopF = nLF ;
m_SCollInfo.nCrvF = l ;
}
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
++ l ;
}
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
++ k ;
}
}
}
}
}
// se da limitare il movimento
if ( dNewLenXY < dLenXY - EPS_SMALL)
dLen *= dNewLenXY / dLenXY ;
// porto i punti e le direzioni di SCollInfo da intrinseco a locale della prima regione
if ( m_SCollInfo.nType != SCI_NONE) {
m_SCollInfo.ptP1.ToGlob( m_pRegM->m_frF) ;
m_SCollInfo.vtDirM.ToGlob( m_pRegM->m_frF) ;
m_SCollInfo.vtDirF.ToGlob( m_pRegM->m_frF) ;
}
if ( m_SCollInfo.nType == SCI_LINE_LINE)
m_SCollInfo.ptP2.ToGlob( m_pRegM->m_frF) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MyCAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
{
// verifico validità regioni
if ( m_pRegM == nullptr || m_pRegF == nullptr)
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
return false ;
// reset info di collisione
m_SCollInfo.nType = SCI_NONE ;
// porto il centro di rotazione nel riferimento intrinseco e ne annullo la componente Z
Point3d ptCenL = ptCen ;
ptCenL.ToLoc( m_pRegM->m_frF) ;
ptCenL.z = 0 ;
if ( abs( dAng) < EPS_ANG_SMALL)
return true ;
double dNewAng = dAng ;
// ciclo sui chunk della seconda superficie
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
// ciclo sui bordi del Chunk
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
else {
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
pCrv2Loc = pCopyCrv ;
}
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
// ciclo sui chunk della prima superficie
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
// ciclo sui bordi del chunk
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
// per CAv non ha senso confrontare due loop interni tra di loro.
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
if ( nLF > 0 && nLM > 0)
continue ;
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
// verifico la collisione tra le entità dei loop esterni dei due chunk
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
while ( pCrv1 != nullptr) {
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
while ( pCrv2 != nullptr) {
if ( ! RotateCurveNoCollisionCurve( pCrv1, pCrv2, ptCenL, dNewAng))
return false ;
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
}
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
}
}
}
}
}
// se da limitare il movimento
if ( ( dAng > 0 && dNewAng < dAng - EPS_ANG_SMALL) ||
( dAng < 0 && dNewAng > dAng + EPS_ANG_SMALL))
dAng = dNewAng ;
return true ;
}
-29
View File
@@ -1,29 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2018
//----------------------------------------------------------------------------
// File : CAvSurfFrMove.h Data : 27.04.18 Versione : 3.1c7
// Contenuto : Dich.ne classe privata per movimento di superfici flat region
// nel loro piano evitando collisioni
//
// Modifiche : 26.03.2026 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "CAvSimpleSurfFrMove.h"
//----------------------------------------------------------------------------
class MyCAvSurfFrMove : public MyCAvSimpleSurfFrMove
{
public :
MyCAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) :
MyCAvSimpleSurfFrMove( SfrM, SfrF) {} ;
public :
bool Translate( const Vector3d& vtDir, double& dLen) ;
bool Rotate( const Point3d& ptCen, double& dAng) ;
const SCollInfo& GetCollInfo()
{ return m_SCollInfo ; }
} ;
+4 -2
View File
@@ -2440,10 +2440,12 @@ CAvDiskTriangle( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDis
// Allontanamento dall'interno // Allontanamento dall'interno
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ; double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
// Allontanamento dalla frontiera // Allontanamento dalla frontiera
Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ; Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ;
vtMoveOrt.Normalize() ; vtMoveOrt.Normalize() ;
Frame3d DiskFrame ; Frame3d DiskFrame ;
DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ; Vector3d vtJ = vtDiskAx ^ vtMoveOrt ;
vtJ.Normalize() ;
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
Triangle3d trTriaLoc = trTria ; Triangle3d trTriaLoc = trTria ;
Vector3d vtMoveLoc = vtMove ; Vector3d vtMoveLoc = vtMove ;
trTriaLoc.ToLoc( DiskFrame) ; trTriaLoc.ToLoc( DiskFrame) ;
+20 -40
View File
@@ -1,13 +1,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2026 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDeClosedSurfTmClosedSurfTm.h Data : 23.01.26 Versione : 3.1a3 // File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione funzione verifica collisione tra // Contenuto : Implementazione funzione verifica collisione tra
// SurfTm e SurfTm. // SurfTm e SurfTm.
// //
// Modifiche : 13.11.20 LM Creazione modulo. // Modifiche : 13.11.20 LM Creazione modulo.
// 24.03.24 DS Aggiunta TestSurfTmSurfTm. // 24.03.24 DS Aggiunta TestSurfTmSurfTm.
// 23.01.26 DS In TestSurfTmSurfTm aggiunto flag per collisione quando una delle due è chiusa e contiene l'altra.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -46,10 +45,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
BBox3d b3BoxA, b3BoxB ; BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ; pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ; pSrfB->GetLocalBBox( b3BoxB) ;
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza. // Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL) if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ; b3BoxB.Expand( dSafeDist) ;
// Se i box non si sovrappongono, non c'è collisione. Ho finito. // Se i box non si sovrappongono, non c'è collisione. Ho finito.
if ( ! b3BoxA.Overlaps( b3BoxB)) if ( ! b3BoxA.Overlaps( b3BoxB))
return false ; return false ;
// Recupero i triangoli di A che interferiscono col box di B // Recupero i triangoli di A che interferiscono col box di B
@@ -62,13 +61,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
continue ; continue ;
BBox3d b3BoxTriaA ; BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( b3BoxTriaA) ; trTriaA.GetLocalBBox( b3BoxTriaA) ;
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL) if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ; b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A // Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
// Settare tutti i triangoli come già processati. // Settare tutti i triangoli come già processati.
// Al termine della chiamata i TempInt dei triangoli valgono 0. // Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ; pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
@@ -85,14 +84,14 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
// Ciclo sui vertici del triangolo. // Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) { for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge // Se il triangolo adiacente al triangolo corrente su questo edge
// non è stato processato, processo il vertice e l'edge. // non è stato processato, processo il vertice e l'edge.
int nAdjTriaTempFlag ; int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ; continue ;
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA)) if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ; return true ;
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito. // Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ; Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ; double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ; vtEdgeV /= dEdgeLen ;
@@ -112,10 +111,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
} }
} }
// Non ho trovato collisioni fra triangoli delle superfici. // Non ho trovato collisioni fra triangoli delle superfici.
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione // Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA)) if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA))
return false ; return false ;
// La collisione c'è se una superficie è dentro l'altra. // La collisione c'è se una superficie è dentro l'altra.
Point3d ptPointA, ptPointB ; Point3d ptPointA, ptPointB ;
pSrfA->GetFirstVertex( ptPointA) ; pSrfA->GetFirstVertex( ptPointA) ;
pSrfB->GetFirstVertex( ptPointB) ; pSrfB->GetFirstVertex( ptPointB) ;
@@ -128,7 +127,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza. // Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist, bool bTestEnclosion) TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
{ {
// Recupero le superfici base // Recupero le superfici base
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ; const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
@@ -141,10 +140,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
BBox3d b3BoxA, b3BoxB ; BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ; pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ; pSrfB->GetLocalBBox( b3BoxB) ;
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza. // Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL) if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ; b3BoxB.Expand( dSafeDist) ;
// Se i box non si sovrappongono, non c'è collisione. Ho finito. // Se i box non si sovrappongono, non c'è collisione. Ho finito.
if ( ! b3BoxA.Overlaps( b3BoxB)) if ( ! b3BoxA.Overlaps( b3BoxB))
return false ; return false ;
// Recupero i triangoli di A che interferiscono col box di B // Recupero i triangoli di A che interferiscono col box di B
@@ -157,13 +156,13 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
continue ; continue ;
BBox3d b3BoxTriaA ; BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( b3BoxTriaA) ; trTriaA.GetLocalBBox( b3BoxTriaA) ;
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza. // Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL) if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ; b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A // Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
// Settare tutti i triangoli come già processati. // Settare tutti i triangoli come già processati.
// Al termine della chiamata i TempInt dei triangoli valgono 0. // Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ; pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
@@ -180,14 +179,14 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
// Ciclo sui vertici del triangolo. // Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) { for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge // Se il triangolo adiacente al triangolo corrente su questo edge
// non è stato processato, processo il vertice e l'edge. // non è stato processato, processo il vertice e l'edge.
int nAdjTriaTempFlag ; int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ; continue ;
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA)) if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ; return true ;
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito. // Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ; Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ; double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ; vtEdgeV /= dEdgeLen ;
@@ -206,25 +205,6 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
pSrfB->SetTempInt( nTB, 1) ; pSrfB->SetTempInt( nTB, 1) ;
} }
} }
// Se non richiesto test di inclusione, non c'è interferenza // Non c'è interferenza
if ( ! bTestEnclosion)
return false ;
// Se la prima superficie è chiusa, verifico se include totalmente la seconda
if ( pSrfA->IsClosed() && b3BoxA.Encloses( b3BoxB)) {
Point3d ptPointB ;
pSrfB->GetFirstVertex( ptPointB) ;
DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ;
if ( DistPoinBSrfA.IsPointInside() || DistPoinBSrfA.IsEpsilon( dSafeDist))
return true ;
}
// Se la seconda superficie è chiusa, verifico se include totalmente la prima
if ( pSrfB->IsClosed() && b3BoxB.Encloses( b3BoxA)) {
Point3d ptPointA ;
pSrfA->GetFirstVertex( ptPointA) ;
DistPointSurfTm DistPoinASrfB( ptPointA, *pSrfB) ;
if ( DistPoinASrfB.IsPointInside() || DistPoinASrfB.IsEpsilon( dSafeDist))
return true ;
}
// Non c'è interferenza
return false ; return false ;
} }
-233
View File
@@ -1,233 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2026
//----------------------------------------------------------------------------
// File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1
// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima.
//
//
//
// Modifiche : 03.02.26 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "stdafx.h"
#include "CalcDerivate.h"
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EgtNumCollection.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
//----------------------------------------------------------------------------
bool
ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
{
// pulisco i vettori dei parametri e delle tangenti
vPrevDer.clear() ;
vNextDer.clear() ;
// numero di punti
int nSize = int( vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
vPrevDer.reserve( nSize) ;
vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
vPrevDer.emplace_back( 0, 0, 0) ;
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
vPrevDer.push_back( vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = vPrevDer[0] ;
vtNextDer = vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[1] + vPar[i+1], vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
vPrevDer.push_back( vtPrevDer) ;
vNextDer.push_back( vtNextDer) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
{
// pulisco i vettori dei parametri e delle tangenti
vPrevDer.clear() ;
vNextDer.clear() ;
// numero di punti
int nSize = int( vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
vPrevDer.reserve( nSize) ;
vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
vPrevDer.emplace_back( 0, 0, 0) ;
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
vPrevDer.push_back( vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
vPar[i+2], vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = vPrevDer[0] ;
vtNextDer = vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
vPar[i], vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
vPar[i+1], vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
vPrevDer.push_back( vtPrevDer) ;
vNextDer.push_back( vtNextDer) ;
}
return true ;
}
-5
View File
@@ -14,8 +14,6 @@
#pragma once #pragma once
#include "/EgtDev/Include/EGkPoint3d.h" #include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EgtNumCollection.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -181,6 +179,3 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP
} }
return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ; return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ;
} }
bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
+511 -1200
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -16,7 +16,6 @@
#include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkGeomDB.h"
#include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include <algorithm> #include <algorithm>
using namespace std ; using namespace std ;
@@ -169,7 +168,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ; ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ; vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
// verifico se sono arrivato al punto di chiusura // verifico se sono arrivato al punto di chiusura
if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) { if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
bStopped = true ; bStopped = true ;
break ; break ;
} }
+1 -2
View File
@@ -45,8 +45,7 @@ static const NamedColor StdColor[] = {
{ "FUCHSIA", FUCHSIA}, { "FUCHSIA", FUCHSIA},
{ "PURPLE", PURPLE}, { "PURPLE", PURPLE},
{ "ORANGE", ORANGE}, { "ORANGE", ORANGE},
{ "BROWN", BROWN}, { "BROWN", BROWN}
{ "INVISIBLE", INVISIBLE}
} ; } ;
static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ; static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ;
+51 -580
View File
@@ -13,8 +13,6 @@
//--------------------------- Include ---------------------------------------- //--------------------------- Include ----------------------------------------
#include "stdafx.h" #include "stdafx.h"
#include "CalcDerivate.h"
#include "Bernstein.h"
#include "CurveAux.h" #include "CurveAux.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "CurveLine.h" #include "CurveLine.h"
@@ -26,26 +24,11 @@
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkCurveByInterp.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkCurveByInterp.h"
#define EIGEN_NO_IO #define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Extern/Eigen/Dense"
#define SAVEAPPROX 0
#define SAVECURVEPASSED 0
#define SAVELINEARAPPROX 0
#define SAVESYNCLINES 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX || SAVESYNCLINES
#include "/EgtDev/Include/EGkGeoPoint3d.h"
static int nCrvPassed = 0 ;
std::vector<IGeoObj*> VT ;
std::vector<Color> VC ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ; static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ;
@@ -539,9 +522,9 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot)
return nullptr ; return nullptr ;
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ; PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
pCrvBezier->Init( nDeg, false) ; // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
if ( ! pCrvBezier->FromLine( *pCrvLine)) pCrvBezier->Init( nDeg, true) ;
return nullptr ; pCrvBezier->FromLine( *pCrvLine) ;
if ( bMakeRatOrNot) if ( bMakeRatOrNot)
pCrvBezier->MakeRational() ; pCrvBezier->MakeRational() ;
return Release( pCrvBezier) ; return Release( pCrvBezier) ;
@@ -594,13 +577,6 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot)
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ; PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc)) if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc))
return nullptr ; return nullptr ;
if ( ! bMakeRatOrNot) {
Point3d ptCen = pArc->GetCenter() ;
Vector3d vtN = pArc->GetNormVersor() ;
pCrvBez.Set( ApproxArcCurveBezierWithSingleCubic( pCrvBez, ptCen, vtN)) ;
}
if ( IsNull( pCrvBez))
return nullptr ;
// aumento il grado della curva come richiesto // aumento il grado della curva come richiesto
while ( pCrvBez->GetDegree() < nDeg) while ( pCrvBez->GetDegree() < nDeg)
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
@@ -1159,7 +1135,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
return true ; return true ;
} }
// trovo a quale span appartiene il parametro dU // trovo a quale span appartiene il parametro dU
int nKnots = ssize( vKnots) ; int nKnots = int( vKnots.size()) ;
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) { if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
nSpan = nKnots - 1 - nDeg ; nSpan = nKnots - 1 - nDeg ;
return true ; return true ;
@@ -1185,7 +1161,7 @@ static bool
CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis) CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
{ {
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1 // mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
if ( ssize( vBasis) != nDeg + 1) if ( vBasis.size() != nDeg + 1)
return false ; return false ;
vBasis[0] = 1 ; vBasis[0] = 1 ;
@@ -1210,8 +1186,7 @@ CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTO
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot, InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot)
const Vector3d& vtStartDir = V_NULL, const Vector3d& vtEndDir = V_NULL)
{ {
PtrOwner<ICurve> pCrvInt ; PtrOwner<ICurve> pCrvInt ;
@@ -1240,8 +1215,6 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
return nullptr ; return nullptr ;
} }
bool bUseStartEndDir = vtStartDir.IsValid() && vtEndDir.IsValid() ;
DBLVECTOR vPntParam ; DBLVECTOR vPntParam ;
vPntParam.resize( nPoints) ; vPntParam.resize( nPoints) ;
vPntParam[0] = 0 ; vPntParam[0] = 0 ;
@@ -1250,15 +1223,13 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ; vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ;
DBLVECTOR vKnots ; DBLVECTOR vKnots ;
int nKnots = bUseStartEndDir ? nPoints + nDeg - 1 + 2 : nPoints + nDeg - 1 ; vKnots.resize( nPoints + nDeg - 1) ;
vKnots.resize( nKnots) ;
for ( int i = 0 ; i < nDeg ; ++i) { for ( int i = 0 ; i < nDeg ; ++i) {
vKnots[i] = 0 ; vKnots[i] = 0 ;
vKnots.end()[-i-1] = 1 ; vKnots.end()[-i-1] = 1 ;
} }
int nKnotsToEdit = bUseStartEndDir ? nPoints + 1 : nPoints - 1 ; for ( int i = nDeg ; i < nPoints - 1 ; ++i) {
for ( int i = nDeg ; i < nKnotsToEdit ; ++i) {
double dKnot = 0 ; double dKnot = 0 ;
for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j) for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j)
dKnot += vPntParam[j - nDeg] ; dKnot += vPntParam[j - nDeg] ;
@@ -1266,14 +1237,13 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
vKnots[i] = dKnot ; vKnots[i] = dKnot ;
} }
int nEq = bUseStartEndDir ? nPoints + 2 : nPoints ; Eigen::MatrixXd mA( nPoints, nPoints) ;
Eigen::MatrixXd mA( nEq, nEq) ;
mA.fill( 0) ; mA.fill( 0) ;
for ( int i = 0 ; i < nEq ; ++i) { for ( int i = 0 ; i < nPoints ; ++i) {
if ( i == 0) if ( i == 0)
mA.row(0).col(0) << 1 ; mA.row(0).col(0) << 1 ;
else if ( i == nEq - 1) else if ( i == nPoints - 1)
mA.row(i).col( nEq - 1) << 1 ; mA.row(i).col(nPoints - 1) << 1 ;
else { else {
int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ; int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ;
DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ; DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ;
@@ -1324,7 +1294,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
int nItCount = 0 ; int nItCount = 0 ;
while ( dErr > dLinTol && nItCount < 10) { while ( dErr > dLinTol && nItCount < 10) {
pCrvInt->Clear() ; pCrvInt->Clear() ;
int nPoints = ssize( vPnt) ; int nPoints = int( vPnt.size()) ;
int nDeg = 3 ; int nDeg = 3 ;
if ( nPoints < 2) if ( nPoints < 2)
return nullptr ; return nullptr ;
@@ -1340,7 +1310,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
else if ( nPoints == 3) { else if ( nPoints == 3) {
// se ho solo tre punti uso un altro algoritmo // se ho solo tre punti uso un altro algoritmo
CurveByInterp cbi ; CurveByInterp cbi ;
for ( int i = 0 ; i < ssize( vPnt) ; ++i) for ( int i = 0 ; i < int( vPnt.size()) ; ++i)
cbi.AddPoint( vPnt[i]) ; cbi.AddPoint( vPnt[i]) ;
pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ; pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ;
if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) if ( ! IsNull( pCrvInt) && pCrvInt->IsValid())
@@ -1372,16 +1342,10 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
} }
} }
if ( ! vLen.empty()) { if ( vLen.size() != 0) {
if ( nEnd == 0) if ( nEnd == 0)
nEnd = nPoints - 1 ; nEnd = nPoints - 1 ;
Vector3d vtStartDir = V_INVALID ; pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot)) ;
Vector3d vtEndDir = V_INVALID ;
//if ( nStart != 0 && nEnd != nPoints - 1) {
// pCrvInt->GetEndDir( vtStartDir) ;
// vtEndDir =
//}
pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot, vtStartDir, vtEndDir)) ;
} }
if ( bFoundLine) { if ( bFoundLine) {
@@ -1393,7 +1357,6 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
nStart = nEnd ; nStart = nEnd ;
} }
//dErr = 0 ;
CalcApproxError( pCrvOri, pCrvInt, dErr) ; CalcApproxError( pCrvOri, pCrvInt, dErr) ;
if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL) if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL)
dMaxLen /= 2 ; dMaxLen /= 2 ;
@@ -1407,333 +1370,47 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
return nullptr ; return nullptr ;
} }
//----------------------------------------------------------------------------
static bool
ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
{
int nPoints = nLast - nFirst + 1 ;
if ( nPoints < 2)
return false ;
if ( vParam.empty())
vParam.resize( nPoints) ;
if ( vParam[nFirst] == 0 && vParam[nLast] == 1)
return true ;
vParam[nFirst] = 0 ;
for ( int i = nFirst + 1 ; i <= nLast ; ++i) {
double dDist = Dist( vPnt[i], vPnt[i-1]) ;
vParam[i] = vParam[i- 1] + dDist ;
}
for ( int i = nFirst + 1 ; i < nLast ; ++i)
vParam[i] /= vParam[nLast] ;
vParam[nLast] = 1 ;
return true ;
}
//----------------------------------------------------------------------------
ICurveBezier*
ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast,
const Vector3d& vtStartDir, const Vector3d& vtEndDir, const DBLVECTOR& vParam)
{
// cerco di approssimare un set di punti con una sola bezier cubica non razionale
int nPoints = nLast - nFirst + 1 ;
// se ho solo quattro punti allora costruisco direttamente la curva
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
int nDeg = 3 ;
bool bRat = false ;
pCrvBez->Init( nDeg, bRat) ;
const Point3d& pt0 = vPnt[nFirst] ;
const Point3d& pt3 = vPnt[nLast] ;
pCrvBez->SetControlPoint( 0, pt0) ;
pCrvBez->SetControlPoint( 3, pt3) ;
Eigen::Vector2d mA ;
if ( nPoints > 4) {
// risoluzione sistema
Eigen::Matrix2d mC ; mC.setZero() ;
Eigen::Vector2d mX ; mX.setZero() ;
for ( int i = nFirst ; i <= nLast ; ++i) {
double dU = vParam[i] ;
DBLVECTOR vBern(4) ;
GetAllBernstein( dU, 3, vBern) ;
Vector3d A1 = vtStartDir * vBern[1] ;
Vector3d A2 = vtEndDir * vBern[2] ;
Vector3d tmp = vPnt[i] - ( pt0 * ( vBern[0] + vBern[1])) - (( pt3 * ( vBern[2] + vBern[3])) - ORIG) ; // ORIG serve solo per trasformare l'ultimo termine in un vettore
mC(0,0) += A1 * A1 ;
mC(0,1) += A1 * A2 ;
mC(1,0) += A1 * A2 ;
mC(1,1) += A2 * A2 ;
mX(0) += A1 * tmp ;
mX(1) += A2 * tmp ;
}
mA = mC.fullPivLu().solve(mX) ;
}
// l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene)
// io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo
if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) {
if ( mA(0) < 0 || mA(1) > 0)
LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti")
double dDistCorr = Dist( pt3, pt0) / 3 ;
mA(0) = dDistCorr ;
mA(1) = - dDistCorr ;
}
Point3d pt1 = pt0 + vtStartDir * mA(0) ;
Point3d pt2 = pt3 + vtEndDir * mA(1) ;
pCrvBez->SetControlPoint( 1, pt1) ;
pCrvBez->SetControlPoint( 2, pt2) ;
return Release( pCrvBez) ;
}
//----------------------------------------------------------------------------
bool
CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam,
int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr)
{
dErr = 0 ;
// calcolo l'errore di approssimazione
for ( int i = nFirst ; i <= nLast ; ++i) {
Point3d ptBez ; pCrvNew->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez) ;
double dErrTemp = Dist( vPntOrig[i], ptBez) ;
if ( dErrTemp > dErr) {
dErr = dErrTemp ;
nPointMaxErr = i ;
}
}
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ICurve* ICurve*
FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol, bool bLimitSplit = false)
{ {
ParamByLen( vPnt, vParam, nFirst, nLast) ;
PtrOwner<ICurveComposite> pCrvFit( CreateCurveComposite()) ;
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
double dErr = INFINITO ;
double dErrPrec = INFINITO ;
double dErrSplit = dTol * 25 ;
int nIter = 0 ;
while ( dErr > dTol && nIter < 10) {
if ( dErr < INFINITO) {
// riparametrizzo i punti
for ( int i = nFirst + 1 ; i < nLast ; ++i) {
// questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione
double dCorr = 1 ;
do {
Vector3d vtDer1, vtDer2 ;
Point3d ptBez ; pCrvBez->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez, &vtDer1, &vtDer2) ;
Vector3d vtLink = ptBez - vPnt[i] ;
double dNum = vtLink * vtDer1 ;
double dDen = vtLink * vtDer2 + vtDer1 * vtDer1 ;
dCorr = dDen > EPS_ZERO ? dNum / dDen : 0 ;
vParam[i] = vParam[i] - dCorr ;
} while ( abs( dCorr) > EPS_ZERO) ;
Clamp( vParam[i], 0., 1.) ;
}
}
// fit della curva
Vector3d vtStartDir, vtEndDir ;
if ( bLimitSplit) {
vtStartDir = vNextDer[nFirst / 3] ;
vtEndDir = vPrevDer[nLast / 3] ;
}
else {
vtStartDir = vNextDer[nFirst] ;
vtEndDir = vPrevDer[nLast] ;
}
pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vtStartDir, vtEndDir, vParam)) ;
if ( IsNull( pCrvBez) || ! pCrvBez->IsValid())
return nullptr ;
#if SAVEAPPROX
SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\"+ToString(nCrvPassed) + "first_approx.nge") ;
#endif
int nPointMaxErr = 0 ;
CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ;
// se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti
if ( ((nLast - nFirst == 1) || ( bLimitSplit && nLast - nFirst == 3)) && dErr > dTol) {
CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ;
pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ;
dErr = 0 ;
}
if ( bLimitSplit && nPointMaxErr % 3 != 0) {
nPointMaxErr = 3 * int( round( nPointMaxErr / 3.)) ;
if ( nPointMaxErr == nFirst)
nPointMaxErr += 3 ;
else if( nPointMaxErr == nLast)
nPointMaxErr -= 3 ;
}
++nIter ;
bool bSplit = false ;
if ( ( nIter == 10 && dErr > dTol) || dErr > dErrPrec || dErrPrec - dErr < dErrPrec / 20)
bSplit = true ;
dErrPrec = dErr ;
// se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due
if ( dErr > dErrSplit || bSplit) {
if ( nLast - nFirst > 1 && nPointMaxErr - nFirst > 1 && nLast - nPointMaxErr > 1) {
if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol, bLimitSplit)) ||
! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol, bLimitSplit)))
return nullptr ;
break ;
}
else
return nullptr ;
}
}
if ( pCrvFit->GetCurveCount() > 0)
return Release( pCrvFit) ;
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
return Release( pCrvBez) ;
else
return nullptr ;
}
//----------------------------------------------------------------------------
ICurve*
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, const Vector3d& vtStart, const Vector3d& vtEnd)
{
if ( pCrv == nullptr || ! pCrv->IsValid())
return nullptr ;
#if SAVECURVEPASSED
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ;
++nCrvPassed ;
#endif
//// uso l'algoritmo di Schneider in Grafic Gems I
// mi aspetto che non ci siano angoli ( discontinuità della derivata prima) nel risultato desiderato
PolyLine plApprox ; PolyLine plApprox ;
double dAngTolFine = 1 ; double dAngTolFine = 2 ;
double dLinTolFine = 0.05 ; pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ;
pCrv->ApproxWithLines( dLinTolFine, dAngTolFine, ICurve::APL_STD, plApprox) ;
#if SAVELINEARAPPROX
CurveComposite CC ; CC.FromPolyLine(plApprox) ;
SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ;
#endif
PNTVECTOR vPnt ; PNTVECTOR vPnt ;
PNTVECTOR vPntOverSampling ;
Point3d pt ; plApprox.GetFirstPoint( pt) ; Point3d pt ; plApprox.GetFirstPoint( pt) ;
do { do {
if ( ! vPntOverSampling.empty()) {
vPntOverSampling.push_back( Media( vPnt.back(), pt,1./3.)) ;
vPntOverSampling.push_back( Media( vPnt.back(), pt,2./3.)) ;
}
vPntOverSampling.push_back( pt) ;
vPnt.push_back( pt) ; vPnt.push_back( pt) ;
} while ( plApprox.GetNextPoint( pt)) ; } while ( plApprox.GetNextPoint( pt)) ;
// calcolo la curvatura nei vari punti per identificare zone a curvatura costante // campiono punti lungo la curva e poi li interpolo
DBLVECTOR vRad ( ssize( vPnt)) ;
for ( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) {
Vector3d vtA = vPnt[i] - vPnt[i-1] ;
Vector3d vtB = vPnt[i+1] - vPnt[i-1] ;
double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * ( vtA ^ vtB).Len()) ;
vRad[i] = dR ;
}
vRad[0] = vRad[1] ;
vRad.back() = vRad.end()[-2] ;
// identifico le zone a curvatura costante // primo e ultimo punto degli intervalli non devono avere curvatura uguale agli altri perché sono di frontiera
INTINTVECTOR vConstCurv ;
double dRadPrec = vRad[0] ;
int nStart = 0 ;
int nEnd = 1 ;
double dRatio = 1.5 ;
while ( nStart < ssize( vPnt) - 1) {
double dRadTol = max( max( vRad[nEnd], dRadPrec) / 10 , 1.) ;
if ( dRadPrec > dRatio * vRad[nEnd] || dRatio * dRadPrec < vRad[nEnd])
dRadTol = 0 ;
while ( nEnd < ssize( vPnt) - 1 && abs( vRad[nEnd] - dRadPrec) < dRadTol) {
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
vConstCurv.emplace_back( nStart * 3, nEnd * 3) ;
nStart = nEnd ;
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
if ( vConstCurv.empty())
vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ;
int nPoints = ssize( vPnt) ; PtrOwner<ICurve> pCC( InterpolatePointSetWithBezier( vPnt, dTol, 100)) ;
DBLVECTOR vParam( nPoints) ; if ( ! IsNull( pCC) && pCC->IsValid())
int nFirst = 0 ; return Release( pCC) ;
int nLast = ssize( vPnt) - 1 ; else
ParamByLen( vPnt, vParam, nFirst, nLast) ; return nullptr ;
}
VCT3DVECTOR vPrevDer ; //----------------------------------------------------------------------------
VCT3DVECTOR vNextDer ; ICurve*
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ; ApproxPointSetWithBezier( const ICurve* pCrv, double dTol)
if ( ! AreSameVectorExact(vtStart, V_NULL)) { {
vNextDer[0] = vtStart ; // campiono punti lungo la curva e poi li interpolo
vPrevDer.back() = vtEnd ;
}
int nOverSampling = ssize( vPntOverSampling) ; PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ;
vParam.resize( nOverSampling) ; return Release( pCC) ;
nFirst = 0 ;
nLast = nOverSampling - 1 ;
ParamByLen( vPntOverSampling, vParam, nFirst, nLast) ;
//normalizzo tutte le derivate
for ( int i = 0 ; i < ssize( vPrevDer) ; ++i) {
vPrevDer[i].Normalize() ;
vNextDer[i].Normalize() ;
}
// potrei verificare prima se un tratto è retto e aggiustare le tangenti del tratto precedente e successivo prima di approssimare
PtrOwner<ICurveComposite> pCCApproxTot( CreateCurveComposite()) ;
for ( INTINT iiSE : vConstCurv) {
nFirst = iiSE.first ;
nLast = iiSE.second ;
// riconosco se ho un tratto retto
int nPnt = nFirst / 3 ;
if ( nLast - nFirst == 3 && ( nPnt > 0 && vRad[nPnt] > dRatio * vRad[nPnt - 1]) && ( nPnt < ssize( vRad) && vRad[nPnt]> dRatio * vRad[nPnt + 1])) {
CurveLine CL ; CL.Set( vPntOverSampling[nFirst], vPntOverSampling[nLast]) ;
PtrOwner<ICurveBezier> pCApprox( LineToBezierCurve( &CL, 3, false)) ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
else {
//definisco la bezier che vado a raffinare iterativamente
PtrOwner<ICurve> pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ;
if ( IsNull( pCApprox) || ! pCApprox->IsValid())
return nullptr ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
}
return Release( pCCApproxTot) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints) CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints)
{ {
if ( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
dErr = INFINITO ;
return false ;
}
// controllo l'errore effettivo campionando più finemente // controllo l'errore effettivo campionando più finemente
double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ; double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ;
double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ; double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ;
Point3d ptStart0 ; pCrvOri->GetStartPoint( ptStart0) ; dErr = 0 ;
Point3d ptStart1 ; pCrvNew->GetStartPoint( ptStart1) ;
Point3d ptEnd0 ; pCrvOri->GetEndPoint( ptEnd0) ;
Point3d ptEnd1 ; pCrvNew->GetEndPoint( ptEnd1) ;
dErr = max( Dist( ptStart1, ptStart0), Dist( ptEnd1, ptEnd0)) ;
for ( int i = 1 ; i < nPoints ; ++i) { for ( int i = 1 ; i < nPoints ; ++i) {
Point3d ptOri, ptNew ; Point3d ptOri, ptNew ;
double dParOri, dParNew ; double dParOri, dParNew ;
@@ -1811,7 +1488,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
{ {
// se con nodi extra // se con nodi extra
if ( cnData.bExtraKnotes) { if ( cnData.bExtraKnotes) {
int nKnotesNbr = ssize( cnData.vU) ; int nKnotesNbr = int( cnData.vU.size()) ;
if ( nKnotesNbr < 4) if ( nKnotesNbr < 4)
return false ; return false ;
cnData.bExtraKnotes = false ; cnData.bExtraKnotes = false ;
@@ -1825,7 +1502,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
bool bAlreadyChecked = false ; bool bAlreadyChecked = false ;
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva // se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
// wrap della curva su se stessa // wrap della curva su se stessa
if ( cnData.bPeriodic && ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1)) { if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
bool bRepeated = true ; bool bRepeated = true ;
for ( int i = 0 ; i < cnData.nDeg ; ++i) { for ( int i = 0 ; i < cnData.nDeg ; ++i) {
if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) { if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) {
@@ -1834,11 +1511,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
} }
} }
bool bFirstAddedAtEnd = false ; bool bFirstAddedAtEnd = false ;
if ( ! bRepeated || ( bRepeated && AreSamePointApprox( cnData.vCP[0], cnData.vCP[cnData.nDeg]))) { if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
DBLVECTOR vU = cnData.vU ; DBLVECTOR vU = cnData.vU ;
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo // se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
if ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1 ) { if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) {
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) { if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
bFirstAddedAtEnd = true ; bFirstAddedAtEnd = true ;
@@ -1850,11 +1527,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ; cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
// controllo eventualmente anche i nodi extra // controllo eventualmente anche i nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo // se ne ho due in più ne tolgo uno in cima e uno in fondo
if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
} }
// se ne ho solo uno in più lo tolgo in cima // se ne ho solo uno in più lo tolgo in cima
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) { else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) {
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
} }
} }
@@ -1881,7 +1558,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// recupero il vettore dei nodi // recupero il vettore dei nodi
cnData.vU = vU ; cnData.vU = vU ;
// verifico se ho nodi extra // verifico se ho nodi extra
if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1 ) { if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
// significa che ci sono due nodi extra: // significa che ci sono due nodi extra:
// se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli // se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) { if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
@@ -1892,7 +1569,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
} }
// se ne ho solo uno in più lo tolgo in cima // se ne ho solo uno in più lo tolgo in cima
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ; cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
} }
bAlreadyChecked = true ; bAlreadyChecked = true ;
@@ -1917,7 +1594,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare // qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
bool bCollapsed = true ; bool bCollapsed = true ;
Point3d ptFirst = cnData.vCP.front() ; Point3d ptFirst = cnData.vCP.front() ;
for ( int i = 1 ; i < ssize( cnData.vCP) ; ++i) { for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) { if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
bCollapsed = false ; bCollapsed = false ;
break ; break ;
@@ -1934,7 +1611,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p // agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// comincio ad aumentare la molteplictià del nodo u_m-p+1 // comincio ad aumentare la molteplictià del nodo u_m-p+1
int nCP = ssize( cnData.vCP) ; int nCP = int( cnData.vCP.size()) ;
int nU = nCP + cnData.nDeg - 1 ; int nU = nCP + cnData.nDeg - 1 ;
int nDeg = cnData.nDeg ; int nDeg = cnData.nDeg ;
PNTVECTOR vBC ; PNTVECTOR vBC ;
@@ -2130,9 +1807,9 @@ NurbsToBezierCurve( const CNurbsData& cnData)
if ( cnData.bPeriodic || cnData.bExtraKnotes) if ( cnData.bPeriodic || cnData.bExtraKnotes)
return nullptr ; return nullptr ;
// numero dei nodi // numero dei nodi
int nU = ssize( cnData.vCP) + cnData.nDeg - 1 ; int nU = int( cnData.vCP.size()) + cnData.nDeg - 1 ;
// controllo relazione nodi - punti di controllo // controllo relazione nodi - punti di controllo
if ( nU != ssize( cnData.vU)) if ( nU != int( cnData.vU.size()))
return nullptr ; return nullptr ;
// numero degli intervalli // numero degli intervalli
int nInt = nU - 2 * cnData.nDeg + 1 ; int nInt = nU - 2 * cnData.nDeg + 1 ;
@@ -2502,7 +2179,7 @@ CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, in
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) { for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i])) if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ; return false ;
} }
@@ -2529,7 +2206,7 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) { for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i])) if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ; return false ;
} }
@@ -2590,7 +2267,7 @@ bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, doubl
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) { for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ; return false ;
} }
@@ -2620,7 +2297,7 @@ bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, do
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ; PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr) if ( pVoronoiObj == nullptr)
return false ; return false ;
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) { for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ; return false ;
} }
@@ -2649,209 +2326,3 @@ ResetCurveVoronoi( const ICurve& crvC)
break ; break ;
} }
} }
//----------------------------------------------------------------------------
bool
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
{
if ( ssize( vCrv) == 1)
return true ;
ChainCurves chainCrv ;
// modifico direttamente le curve passate in input
chainCrv.Init( bAllowInvert, dChainTol, ssize( vCrv)) ;
for ( int c = 0 ; c < ssize( vCrv) ; ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vCrv[c]->GetStartPoint( ptStart) ;
vCrv[c]->GetEndPoint( ptEnd) ;
vCrv[c]->GetStartDir( vtStart) ;
vCrv[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
INTVECTOR vIds ;
Point3d ptStart = ORIG ;
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
int nFirst = vIds[0] ;
bool bInvert = false ;
if ( nFirst < 0)
bInvert = true ;
nFirst = abs( nFirst) - 1 ;
if ( bInvert)
vCrv[nFirst]->Invert() ;
ICurveComposite* pFirstCrv = vCrv[nFirst] ;
for ( int nId : vIds) {
bInvert = false ;
if ( nId < 0)
bInvert = true ;
nId = abs( nId) - 1 ;
if ( nId == nFirst)
continue ;
if ( bInvert)
vCrv[nId]->Invert() ;
if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
return false ;
}
pFirstCrv->GetEndPoint( ptStart) ;
}
// elimino gli elementi del vettore che non contengono più curve
int c = ssize( vCrv) - 1 ;
while ( c > -1) {
if ( IsNull( vCrv[c]))
vCrv.erase( vCrv.begin() + c) ;
--c ;
}
return true ;
}
//----------------------------------------------------------------------------
double
CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2)
{
pCrv->GetParamAtLength( dLen, dUStep2) ;
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
double dStepCos2 = vtCurr1 * vtStep2 ;
double dDist = Dist( ptCurr1, ptStep2) ;
return (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
}
//----------------------------------------------------------------------------
bool
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
double dLenPrev2, double& dLenCurr2, double dLen2)
{
Point3d ptCurr1 ;
Vector3d vtCurr1 ;
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
vtCurr1.Normalize() ;
// --- Piano di taglio per punto a minima distanza
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
int nIndParCloser = - 1, nIndPointCloser = -1 ;
double dSqMinDist = INFINITO ;
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
IntCrvPlnInfo aInfo ;
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo) && aInfo.Ici[0].dU > dUPrev2) {
if ( nIndParCloser == -1)
nIndParCloser = nInfo ;
double dSqDist = SqDist( ptCurr1, aInfo.Ici[0].ptI) ;
if ( dSqDist < dSqMinDist) {
dSqMinDist = dSqDist ;
nIndPointCloser = nInfo ;
}
}
}
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
if ( bOkPlane) {
// Se gli indici sono tra loro coerenti allora ho individuato il punto
if ( nIndParCloser == nIndPointCloser) {
IntCrvPlnInfo aInfo ;
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
dUCurr2 = aInfo.Ici[0].dU ;
}
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
else {
// scelgo il punto più vicino al corrente
IntCrvPlnInfo aInfoPt, aInfoPar ;
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
dUCurr2 = ( SqDist( ptCurr1, aInfoPt.Ici[0].ptI) < SqDist( ptCurr1, aInfoPar.Ici[0].ptI) ?
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
#if SAVESYNCLINES
VT.clear() ; VC.clear() ;
VT.emplace_back( pCrvEdge1->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
VT.emplace_back( pCrvEdge2->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
PtrOwner<IGeoPoint3d> ptCurr1Geo( CreateGeoPoint3d()) ; ptCurr1Geo->Set( ptCurr1) ;
VT.emplace_back( Release( ptCurr1Geo)) ; VC.emplace_back( BLUE) ;
PtrOwner<IGeoPoint3d> ptPar( CreateGeoPoint3d()) ; ptPar->Set( aInfoPar.Ici[0].ptI) ;
PtrOwner<IGeoPoint3d> ptPt( CreateGeoPoint3d()) ; ptPt->Set( aInfoPt.Ici[0].ptI) ;
VT.emplace_back( Release( ptPar)) ; VC.emplace_back( LIME) ;
VT.emplace_back( Release( ptPt)) ; VC.emplace_back( FUCHSIA) ;
SaveGeoObj( VT, VC, "C:\\Temp\\bezier\\ruled\\TestTrimmingPlane.nge") ;
#endif
}
// Verifico di non essermi allontanato troppo
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
bOkPlane = ( dLen < dLenPrev2 + 2. * dMyDist) ;
}
if ( ! bOkPlane) {
// --- Altrimenti, cerco il punto a minima distanza
DistPointCurve DPC( ptCurr1, *pCrvEdge2) ;
int nFlag ;
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrev2, dUCurr2, nFlag) && dUCurr2 > dUPrev2) ;
// Verifico di non essermi allontanato troppo
if ( bOkMinDist) {
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
bOkMinDist = ( dLen < dLenPrev2 + 2. * dMyDist) ;
}
if ( ! bOkMinDist) {
// --- Aumento la distanza corrente del passo di campionamento
double dLen = Clamp( dLenPrev2 + dMyDist, 0., dLen2) ;
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
}
}
// Recupero il punto corrente e la direzione tangente sul secondo bordo
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
Point3d ptCurr2 ;
Vector3d vtCurr2 ;
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
vtCurr2.Normalize() ;
// Verifico se le direzioni tangenti sono tra di loro circa parallele
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
double dSearchLen = dMyDist / 2 ;
int NUM_STEP = 10 ;
const double dCoeff = 0.1 ;
double dCos = vtCurr1 * vtCurr2 ;
double dDistCurr = Dist( ptCurr1, ptCurr2) ;
double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ;
double bUpdated = false ;
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
dSearchLen = dMyDist ;
NUM_STEP = 20 ;
}
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
DBLVECTOR vVal ;
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
double dUStep2 ;
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
if ( vVal.back() < dMin) {
dMin = vVal.back() ;
dUCurr2 = dUStep2 ;
}
}
DBLDBLVECTOR vInterv ;
for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) {
if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1])
vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP,
dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ;
}
if ( ssize( vInterv) != 0) {
for ( int j = 0 ; j < ssize( vInterv) ; ++j) {
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ;
double dUStep2 ;
double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ;
if ( dVal < dMin) {
dUCurr2 = dUStep2 ;
dMin = dVal ;
bUpdated = true ;
}
}
}
}
}
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
if ( bUpdated)
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
return true ;
}
-1
View File
@@ -35,4 +35,3 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ; bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ; ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
Voronoi* GetCurveVoronoi( const ICurve& crvC) ; Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
+4 -3
View File
@@ -275,19 +275,20 @@ CurveBezier::FromLine( const ICurveLine& crLine)
{ {
if ( m_nStatus != OK || ! crLine.IsValid()) if ( m_nStatus != OK || ! crLine.IsValid())
return false ; return false ;
double dWeight = 1 ;
int nCount = 0 ; int nCount = 0 ;
Point3d ptStart ; crLine.GetStartPoint( ptStart) ; Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
SetControlPoint( nCount, ptStart) ; SetControlPoint( nCount, ptStart, dWeight) ;
++nCount ; ++nCount ;
double dPart = 1. / m_nDeg ; double dPart = 1. / m_nDeg ;
for ( int i = 1 ; i < m_nDeg ; ++i) { for ( int i = 1 ; i < m_nDeg ; ++i) {
double dU = i * dPart ; double dU = i * dPart ;
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ; Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
SetControlPoint( nCount, ptMid) ; SetControlPoint( nCount, ptMid, dWeight) ;
++nCount ; ++nCount ;
} }
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ; Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
SetControlPoint( nCount, ptEnd) ; SetControlPoint( nCount, ptEnd, dWeight) ;
++nCount ; ++nCount ;
return true ; return true ;
} }
+201 -2
View File
@@ -202,14 +202,213 @@ CurveByApprox::CalcParameterization( void)
bool bool
CurveByApprox::CalcAkimaTangents( bool bDetectCorner) CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
{ {
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; // pulisco i vettori delle tangenti
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveByApprox::CalcBesselTangents( void) CurveByApprox::CalcBesselTangents( void)
{ {
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; // pulisco i vettori delle tangenti
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+235 -34
View File
@@ -50,42 +50,12 @@ CurveByInterp::AddPoint( const Point3d& ptP)
ICurve* ICurve*
CurveByInterp::GetCurve( int nMethod, int nType) CurveByInterp::GetCurve( int nMethod, int nType)
{ {
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs) // calcolo le tangenti
if ( nType == CUBIC_BEZIERS_LONG) {
// creo la curva composita
PtrOwner<ICurve> pCrv ;
//pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
//debug
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ;
if ( IsNull(pCrv) || ! pCrv->IsValid())
return nullptr ;
return Release( pCrv) ;
}
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return nullptr ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le tangenti
if ( nMethod == BESSEL) { if ( nMethod == BESSEL) {
if ( ! CalcBesselTangents()) if ( ! CalcBesselTangents())
return nullptr ; return nullptr ;
} }
else { else if ( nType != CUBIC_BEZIERS_LONG) {
if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER)) if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER))
return nullptr ; return nullptr ;
} }
@@ -133,6 +103,16 @@ CurveByInterp::GetCurve( int nMethod, int nType)
return ::Release( pCrvCompo) ; return ::Release( pCrvCompo) ;
} }
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs)
if ( nType == CUBIC_BEZIERS_LONG) {
// creo la curva composita
PtrOwner<ICurve> pCrv ;
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
if ( IsNull(pCrv) || ! pCrv->IsValid())
return nullptr ;
return Release( pCrv) ;
}
return nullptr ; return nullptr ;
} }
@@ -140,12 +120,233 @@ CurveByInterp::GetCurve( int nMethod, int nType)
bool bool
CurveByInterp::CalcAkimaTangents( bool bDetectCorner) CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
{ {
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; // pulisco i vettori dei parametri e delle tangenti
m_vPar.clear() ;
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
// se non ci sono almeno 5 punti
if ( nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti, uso arco sui primi tre punti
else {
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso arco sugli ultimi tre punti
else {
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
// se secondo punto
if ( i == 1) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// se penultimo punto
else if ( i == nSize - 2) {
// se curva aperta o non ci sono almeno 5 punti
if ( ! bClosed || nSize < 5) {
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// altrimenti
else {
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
vtPrevDer, vtNextDer))
return false ;
}
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveByInterp::CalcBesselTangents( void) CurveByInterp::CalcBesselTangents( void)
{ {
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; // pulisco i vettori dei parametri e delle tangenti
m_vPar.clear() ;
m_vPrevDer.clear() ;
m_vNextDer.clear() ;
// numero di punti
int nSize = int( m_vPnt.size()) ;
// sono necessari almeno due punti
if ( nSize < 2)
return false ;
// calcolo le distanze tra i punti per derivarne i parametri
m_vPar.reserve( nSize) ;
double dPar = 0 ;
m_vPar.push_back( dPar) ;
for ( int i = 1 ; i < nSize ; ++ i) {
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
dPar += dDist ;
m_vPar.push_back( dPar) ;
}
// calcolo le derivate
m_vPrevDer.reserve( nSize) ;
m_vNextDer.reserve( nSize) ;
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
if ( nSize == 2) {
// non esiste derivata prima del primo punto
m_vPrevDer.emplace_back( 0, 0, 0) ;
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
m_vPrevDer.push_back( m_vNextDer[0]) ;
// non esiste derivata dopo il secondo e ultimo punto
m_vNextDer.emplace_back( 0, 0, 0) ;
return true ;
}
// verifico se curva chiusa (primo e ultimo punto coincidono)
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
// calcolo le derivate
for ( int i = 0 ; i < nSize ; ++ i) {
Vector3d vtPrevDer ;
Vector3d vtNextDer ;
// primo punto
if ( i == 0) {
// se curva chiusa, come precedente uso il penultimo punto
if ( bClosed) {
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
return false ;
vtPrevDer = vtNextDer ;
}
// altrimenti, uso i primi tre punti
else {
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
return false ;
vtPrevDer = Vector3d( 0, 0, 0) ;
}
}
// ultimo punto
else if ( i == nSize - 1) {
// se curva chiusa, le tg devono coincidere con quelle del primo
if ( bClosed) {
vtPrevDer = m_vPrevDer[0] ;
vtNextDer = m_vNextDer[0] ;
}
// altrimenti, uso gli ultimi tre punti
else {
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
m_vPar[i], m_vPnt[i], vtPrevDer))
return false ;
vtNextDer = Vector3d( 0, 0, 0) ;
}
}
// punti intermedi
else {
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
return false ;
vtNextDer = vtPrevDer ;
}
// salvo la derivata
m_vPrevDer.push_back( vtPrevDer) ;
m_vNextDer.push_back( vtNextDer) ;
}
return true ;
} }
+1 -166
View File
@@ -1967,120 +1967,7 @@ CurveComposite::AddJoint( double dU)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
{
int nCrvCount = GetCurveCount() ;
// verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount)
return false ;
// salvo le vecchie curve e nel caso le ripristino
int nPrevCrv = -1 ;
// recupero l'indice e il puntatore alla curva precedente (se esiste)
if ( nU >= 0)
nPrevCrv = nU - 1 ;
else if ( IsClosed())
nPrevCrv = nCrvCount - 1 ;
PtrOwner<CurveComposite> pOrigCrv( CreateBasicCurveComposite()) ;
if ( nPrevCrv >= 0)
pOrigCrv->AddCurve( m_CrvSmplS[ nPrevCrv]->Clone()) ;
// recupero il puntatore alla curva successiva (se esiste)
int nNextCrv = -1 ;
if ( nU < nCrvCount)
nNextCrv = nU ;
else if ( IsClosed())
nNextCrv = 0 ;
else
nNextCrv = - 1 ;
if ( nNextCrv >= 0)
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
int nCrvNmbr = GetCurveCount() ;
int nFlagDel = DeletedCurve::NONE ;
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
return false ;
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
bool bErasedPrev = ( nFlagDel == DeletedCurve::PREV) ;
bool bErasedNext = ( nFlagDel == DeletedCurve::NEXT) ;
if ( ( bErasedPrev && nNextCrv == -1) || ( bErasedNext && nPrevCrv == -1)) {
// se sono su un estremo di una curva aperta e ho cancellato la sottocurva di estremità devo verificare che fosse più piccola della tolleranza
if ( bErasedPrev && nNextCrv == -1) {
Point3d ptOrigEnd ; pOrigCrv->GetEndPoint( ptOrigEnd) ;
Point3d ptNewEnd ; GetEndPoint( ptNewEnd) ;
if ( Dist( ptOrigEnd, ptNewEnd) > dTol)
m_CrvSmplS.push_back( Release( pOrigCrv)) ;
return true ;
}
if ( bErasedNext && nPrevCrv == -1) {
Point3d ptOrigStart ; pOrigCrv->GetStartPoint( ptOrigStart) ;
Point3d ptNewStart ; GetStartPoint( ptNewStart) ;
if ( Dist( ptOrigStart, ptNewStart) > dTol)
m_CrvSmplS.insert( m_CrvSmplS.begin(), Release( pOrigCrv)) ;
return true ;
}
}
double dStart ;
double dEnd ;
if ( bErasedPrev) {
dStart = nU ;
dEnd = nNextCrv + 1 ;
}
else if ( bErasedNext) {
dStart = nPrevCrv ;
dEnd = nU ;
if ( nU == 0)
dStart -= 1 ;
}
else { // ! bErasedSomeCrv
dStart = ( nPrevCrv != -1 ? nPrevCrv : 0) ;
dEnd = ( nNextCrv != -1 ? nNextCrv + 1 : nCrvNmbr) ;
}
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
double dErr = 0 ;
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr, 6) || dErr > dTol) {
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
if ( ! bErasedSomeCrv) {
if ( nNextCrv != -1) {
delete m_CrvSmplS[nNextCrv] ;
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
}
if ( nPrevCrv != -1) {
delete m_CrvSmplS[nPrevCrv] ;
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
}
}
else {
if ( bErasedNext) {
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
nPos = 0 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
else {
int nPos = nU == 0 ? nU : nPrevCrv ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
nPos = nCrvNmbr - 1 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
{ {
// verifico lo stato // verifico lo stato
if ( m_nStatus != OK) if ( m_nStatus != OK)
@@ -2090,8 +1977,6 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
// verifico l'indice della giunzione // verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount) if ( nU < 0 || nU > nCrvCount)
return false ; return false ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NONE ;
// recupero l'indice e il puntatore alla curva precedente (se esiste) // recupero l'indice e il puntatore alla curva precedente (se esiste)
int nPrevCrv = -1 ; int nPrevCrv = -1 ;
if ( nU > 0) if ( nU > 0)
@@ -2120,8 +2005,6 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
if ( AreSamePointApprox( ptStart, ptNewJoint)) { if ( AreSamePointApprox( ptStart, ptNewJoint)) {
delete pPrevCrv ; delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ; m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::PREV ;
} }
// altrimenti diventa un segmento di retta // altrimenti diventa un segmento di retta
else { else {
@@ -2141,8 +2024,6 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
if ( AreSamePointApprox( ptNewJoint, ptEnd)) { if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
delete pNextCrv ; delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ; m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = DeletedCurve::NEXT ;
} }
// altrimenti diventa un segmento di retta // altrimenti diventa un segmento di retta
else { else {
@@ -3977,49 +3858,3 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
ptStart = m_ptStart ; ptStart = m_ptStart ;
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
CurveComposite::ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
{
// prendo il possesso e verifico la curva
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
return false ;
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico l'indice sia sensato
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
return false ;
// verifico che start e end coincidano entro la tolleranza
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
return false ;
}
else
return false ;
}
// se presente una tolleranza lungo la curva controllo che sia rispettata
if ( dTolAlong < INFINITO) {
double dErr = 0 ;
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
if ( dErr > dTolAlong)
return false ;
}
delete m_CrvSmplS[nSubCrv] ;
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
return true ;
}
+1 -8
View File
@@ -26,9 +26,6 @@ class Voronoi ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class CurveComposite : public ICurveComposite, public IGeoObjRW class CurveComposite : public ICurveComposite, public IGeoObjRW
{ {
public :
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
public : // IGeoObj public : // IGeoObj
~CurveComposite( void) override ; ~CurveComposite( void) override ;
CurveComposite* Clone( void) const override ; CurveComposite* Clone( void) const override ;
@@ -159,9 +156,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ; bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ; bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddJoint( double dU) override ; bool AddJoint( double dU) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
{ return ModifyJoint( nU, ptNewJoint, nullptr) ; }
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
bool RemoveJoint( int nU) override ; bool RemoveJoint( int nU) override ;
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ; bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ; bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
@@ -183,7 +178,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ; bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ; bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool GetOnlyPoint( Point3d& ptStart) const override ; bool GetOnlyPoint( Point3d& ptStart) const override ;
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
@@ -217,7 +211,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ; bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ; bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
bool CalcVoronoiObject( void) const ; bool CalcVoronoiObject( void) const ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
private : private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ; enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
+2 -15
View File
@@ -116,7 +116,6 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
vtDiff = ptQ - ptP ; vtDiff = ptQ - ptP ;
// angolo tra vettore e tangente // angolo tra vettore e tangente
dTemp = vtDer1 * vtDiff ; dTemp = vtDer1 * vtDiff ;
bool bEquiverse = dTemp > 0 ;
if ( abs( dTemp) > EPS_ZERO) if ( abs( dTemp) > EPS_ZERO)
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ; dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
else else
@@ -124,20 +123,8 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U)) // stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
dPrevPar = dPar ; dPrevPar = dPar ;
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ; dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ;
if ( abs( dTemp) > EPS_ZERO)
// se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ;
// provo quindi ad aggiustare a mano, anziché usare il segno suggerito da newton, che con queste premesse potrebbe divergere
double dCos75 = 0.2588 ;
if ( abs( dTemp) > EPS_ZERO) {
double dDelta = ( vtDer1 * vtDiff) / dTemp ;
if ( dSqCosA > dCos75) {
if ( ( bEquiverse && dDelta > 0) || ( ! bEquiverse && dDelta < 0))
dDelta *= -1 ;
dPar = dPrevPar + dDelta ;
}
else
dPar = dPrevPar - dDelta ;
}
// clipping parametro // clipping parametro
if ( dPar < approxMin.dParMin) { if ( dPar < approxMin.dParMin) {
if ( approxMin.bParMinSing && ! bClampedFromSing) { if ( approxMin.bParMinSing && ! bClampedFromSing) {
+1 -12
View File
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
// distanza non calcolata // distanza non calcolata
m_dDist = - 1 ; m_dDist = - 1 ;
if ( ! CrvBez.IsValid()) if ( &CrvBez == nullptr || ! CrvBez.IsValid())
return ; return ;
// determino tolleranza di approssimazione in base a ingombro curva // determino tolleranza di approssimazione in base a ingombro curva
@@ -42,17 +42,6 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL)) if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
return ; return ;
int nDeg = CrvBez.GetDegree() ;
if ( PL.GetPointNbr() < nDeg + 1) {
// costruisco una polilinea con un numero di curve scelto in base al grado della curva
PL.Clear() ;
for ( int i = 0 ; i <= nDeg + 1 ; ++i) {
double dU = double(i) / (nDeg + 1) ;
Point3d ptBez ;
CrvBez.GetPointD1D2( dU, ICurve::Side::FROM_MINUS, ptBez) ;
PL.AddUPoint( dU, ptBez) ;
}
}
// cerco la minima distanza per la polilinea // cerco la minima distanza per la polilinea
MDCVECTOR vApproxMin ; MDCVECTOR vApproxMin ;
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin)) if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
+5 -5
View File
@@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide) const
{ {
if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size())
return false ; return false ;
// se distanza nulla, il punto giace sulla curva // se distanza nulla, il punto giace sulla curva
if ( m_dDist <= dTol) { if ( m_dDist <= EPS_SMALL) {
nSide = MDS_ON ; nSide = MDS_ON ;
return true ; return true ;
} }
@@ -259,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
// determino il lato di giacitura del punto // determino il lato di giacitura del punto
double dSide = vtRef * ( m_ptP - ptQ) ; double dSide = vtRef * ( m_ptP - ptQ) ;
if ( abs( dSide) < dTol) if ( abs( dSide) < EPS_SMALL)
nSide = MDS_ON ; nSide = MDS_ON ;
else if ( dSide > 0) else if ( dSide > 0)
nSide = MDS_LEFT ; nSide = MDS_LEFT ;
@@ -270,7 +270,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide) const
{ {
if ( m_dDist < 0 || m_Info.empty()) if ( m_dDist < 0 || m_Info.empty())
return false ; return false ;
@@ -286,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
} }
} }
// mi sono ricondotto al caso precedente // mi sono ricondotto al caso precedente
return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ; return GetSideAtMinDistPoint( nInd, vtN, nSide) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+9 -10
View File
@@ -23,10 +23,10 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz) DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
: m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false) : m_dDist( -1), m_bIsInside( false)
{ {
// Bezier non valida // Bezier non valida
if ( ! pSrfBz.IsValid()) if ( &pSrfBz == nullptr || ! pSrfBz.IsValid())
return ; return ;
// Calcolo la distanza // Calcolo la distanza
Calculate( ptP, pSrfBz) ; Calculate( ptP, pSrfBz) ;
@@ -37,9 +37,9 @@ void
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz) DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
{ {
// Inizializzo distanza non calcolata // Inizializzo distanza non calcolata
m_dDist = -1 ; m_dDist = - 1. ;
// Controllo se la superficie è chiusa // Controllo se la superficie è chiusa
m_bIsSurfClosed = srfBz.IsClosed() ; m_bIsSurfClosed = srfBz.IsClosed() ;
// Lavoro con l'oggetto superficie trimesh di base // Lavoro con l'oggetto superficie trimesh di base
@@ -49,17 +49,17 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
DistPointSurfTm dpst( ptP, *pStmRef) ; DistPointSurfTm dpst( ptP, *pStmRef) ;
// recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo //recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ; Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ;
int nT ; dpst.GetMinDistTriaIndex( nT) ; int nT ; dpst.GetMinDistTriaIndex( nT) ;
// salvo il punto corrispondente nel parametrico //salvo il punto corrispondente nel parametrico
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ; srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
// salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto // salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto
srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ; srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ;
// salvo la distanza minima // salvo la distanza minima
m_dDist = Dist( ptP, m_ptMinDistPoint) ; m_dDist = Dist( ptP, m_ptMinDistPoint) ;
// se il punto è sulla superficie // se il punto è sulla superficie
if ( m_dDist < EPS_SMALL) { if ( m_dDist < EPS_SMALL) {
m_bIsInside = false ; m_bIsInside = false ;
return ; return ;
@@ -96,14 +96,13 @@ DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const
{ {
// Distanza non valida // Distanza non valida
if ( m_dDist < -EPS_ZERO) if ( m_dDist < -EPS_ZERO)
return false ; return false ;
// Distanza valida // Distanza valida
dU = m_ptParam.x ; ptParamPoint = m_ptParam ;
dV = m_ptParam.y ;
return true ; return true ;
} }
BIN
View File
Binary file not shown.
-4
View File
@@ -281,10 +281,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="BBox3d.cpp" /> <ClCompile Include="BBox3d.cpp" />
<ClCompile Include="BiArcs.cpp" /> <ClCompile Include="BiArcs.cpp" />
<ClCompile Include="CalcPocketing.cpp" /> <ClCompile Include="CalcPocketing.cpp" />
<ClCompile Include="CalcDerivate.cpp" />
<ClCompile Include="CAvSilhouetteSurfTm.cpp" /> <ClCompile Include="CAvSilhouetteSurfTm.cpp" />
<ClCompile Include="CAvSimpleSurfFrMove.cpp" /> <ClCompile Include="CAvSimpleSurfFrMove.cpp" />
<ClCompile Include="CAvSurfFrMove.cpp" />
<ClCompile Include="CAvToolSurfTm.cpp" /> <ClCompile Include="CAvToolSurfTm.cpp" />
<ClCompile Include="CAvToolTriangle.cpp" /> <ClCompile Include="CAvToolTriangle.cpp" />
<ClCompile Include="CDeBoxClosedSurfTm.cpp" /> <ClCompile Include="CDeBoxClosedSurfTm.cpp" />
@@ -324,7 +322,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersLineVolZmap.cpp" /> <ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" /> <ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" /> <ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="OffsetCurve3d.cpp" />
<ClCompile Include="Trimming.cpp" /> <ClCompile Include="Trimming.cpp" />
<ClCompile Include="MultiGeomDB.cpp" /> <ClCompile Include="MultiGeomDB.cpp" />
<ClCompile Include="SurfTriMeshOffset.cpp" /> <ClCompile Include="SurfTriMeshOffset.cpp" />
@@ -355,7 +352,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" /> <ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" /> <ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" /> <ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CAvSurfFrMove.h" />
<ClInclude Include="CDeBoxTria.h" /> <ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" /> <ClInclude Include="CDeCapsTria.h" />
<ClInclude Include="CDeConeFrustumTria.h" /> <ClInclude Include="CDeConeFrustumTria.h" />
-15
View File
@@ -567,18 +567,6 @@
<ClCompile Include="Trimming.cpp"> <ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter> <Filter>File di origine\GeoStriping</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="CalcDerivate.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="CAvSurfFrMove.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter>
</ClCompile>
<ClCompile Include="OffsetCurve3d.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@@ -1265,9 +1253,6 @@
<ClInclude Include="..\Include\EGkMultiGeomDB.h"> <ClInclude Include="..\Include\EGkMultiGeomDB.h">
<Filter>File di intestazione\Include</Filter> <Filter>File di intestazione\Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="CAvSurfFrMove.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc"> <ResourceCompile Include="EgtGeomKernel.rc">
+137 -510
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -43,9 +43,6 @@ class IntersCrvCompoCrvCompo
bool bAutoInters, bool bClosed, int nCurvesNbr) ; bool bAutoInters, bool bClosed, int nCurvesNbr) ;
bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ; bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ;
bool EraseOtherInfo( int& nIndCurr, int& nIndOther) ; bool EraseOtherInfo( int& nIndCurr, int& nIndOther) ;
bool EraseBothInfo( int& nIndCurr, int& nIndOther) ;
bool CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
bool MergeNewOverlap( int i, bool bCrvAOrB) ;
private : private :
bool m_bOverlaps ; bool m_bOverlaps ;
+22 -66
View File
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
// ciclo sulle curve per verificare se da approssimare // ciclo sulle curve per verificare se da approssimare
for ( int i = 0 ; i < 2 ; ++ i) { for ( int i = 0 ; i < 2 ; ++ i) {
// se curva è arco da approssimare oppure è curva di Bezier // se curva è arco da approssimare oppure è curva di Bezier
if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) || if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) ||
m_pCurve[i]->GetType() == CRV_BEZIER) { m_pCurve[i]->GetType() == CRV_BEZIER) {
// approssimo con rette // approssimo con rette
@@ -127,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
const CurveArc* pArc = GetBasicCurveArc( &Curve) ; const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
if ( pArc == nullptr) if ( pArc == nullptr)
return false ; return false ;
// verifico se non è nel piano XY o ha più di un giro al centro // verifico se non è nel piano XY o ha più di un giro al centro
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) || return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ; abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
} }
@@ -252,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
bool bool
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB) IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
{ {
// se non ci sono intersezioni, non va fatto alcunché // se non ci sono intersezioni, non va fatto alcunché
if ( m_Info.empty()) if ( m_Info.empty())
return true ; return true ;
// se le curve originali non sono state approssimate, non va fatto alcunché // se le curve originali non sono state approssimate, non va fatto alcunché
if ( ! bAdjCrvA && ! bAdjCrvB) if ( ! bAdjCrvA && ! bAdjCrvB)
return true ; return true ;
// procedo ad aggiustare // procedo ad aggiustare
@@ -296,8 +296,8 @@ int
IntersCurveCurve::GetInters3DCount( void) IntersCurveCurve::GetInters3DCount( void)
{ {
int nCount = 0 ; int nCount = 0 ;
for ( int i = 0 ; i < m_nIntersCount ; ++i) { for( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
@@ -365,8 +365,8 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( nInd < 0 || nInd >= GetInters3DCount()) if ( nInd < 0 || nInd >= GetInters3DCount())
return false ; return false ;
int nCount = - 1 ; int nCount = - 1 ;
for ( int i = 0 ; i < m_nIntersCount ; ++i) { for( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
@@ -374,7 +374,7 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
++nCount ; ++nCount ;
} }
if ( nCount == nInd) { if( nCount == nInd) {
aInfo = m_Info[nInd] ; aInfo = m_Info[nInd] ;
return true ; return true ;
} }
@@ -389,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1) if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
return false ; return false ;
// ricerca del punto più vicino tra le intersezioni singole // ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ; bool bFound = false ;
double dMinSqDist = SQ_INFINITO ; double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < m_nIntersCount ; ++ i) { for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se è un'intersezione singola // se è un'intersezione singola
if ( ! m_Info[i].bOverlap) { if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto // faccio la verifica sul punto
Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ; Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ;
@@ -458,7 +458,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione // se esiste almeno una intersezione
if ( m_nIntersCount >= 1) if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ; return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna // altrimenti la curva è completamente interna oppure completamente esterna
else else
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ; return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
} }
@@ -475,7 +475,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
// se esiste almeno una intersezione // se esiste almeno una intersezione
if ( m_nIntersCount >= 1) if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ; return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna // altrimenti la curva è completamente interna oppure completamente esterna
else else
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ; return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
} }
@@ -540,7 +540,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dU2 = Info[j].IciA[1].dU ; double dU2 = Info[j].IciA[1].dU ;
if ( dU2 < dU1 && pCurve->IsClosed()) if ( dU2 < dU1 && pCurve->IsClosed())
dU2 += dEndPar ; dU2 += dEndPar ;
// se cade nell'intervallo è da saltare // se cade nell'intervallo è da saltare
if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) { if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) {
bToSkip = true ; bToSkip = true ;
break ; break ;
@@ -559,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dCurrPar = dStartPar ; double dCurrPar = dStartPar ;
double dCurrLen = 0 ; double dCurrLen = 0 ;
double dEndLen ; pCurve->GetLength( dEndLen) ; double dEndLen ; pCurve->GetLength( dEndLen) ;
// se è chiusa, recupero come finisce // se è chiusa, recupero come finisce
if ( pCurve->IsClosed()) { if ( pCurve->IsClosed()) {
if ( ! InfoCorr[nNumInters-1].bOverlap) if ( ! InfoCorr[nNumInters-1].bOverlap)
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ; nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
@@ -577,24 +577,8 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
} }
// costruisco il vettore delle classificazioni // costruisco il vettore delle classificazioni
for ( int i = 0 ; i < nNumInters ; ++ i) { for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente // se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ; double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
/*int j = i < nNumInters - 1 ? i + 1 : -1 ;
if ( pCurve->IsClosed() && j == - 1)
j = 0 ;*/
int j = i == 0 ? -1 : i - 1 ;
if ( pCurve->IsClosed() && j == - 1)
j = nNumInters - 1 ;
bool bSpike = false ;
if ( j != -1) {
bSpike = InfoCorr[i].bOverlap && InfoCorr[j].bOverlap && InfoCorr[i].bCBOverEq != InfoCorr[j].bCBOverEq ;
if ( bSpike) {
bSpike = abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ;
}
}
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) { if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida // verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ; int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
@@ -615,7 +599,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// altrimenti, salvo il tipo // altrimenti, salvo il tipo
else else
nLastTy = InfoCorr[i].IciA[0].nNextTy ; nLastTy = InfoCorr[i].IciA[0].nNextTy ;
// se è definito un tratto in sovrapposizione // se è definito un tratto in sovrapposizione
if ( InfoCorr[i].bOverlap) { if ( InfoCorr[i].bOverlap) {
// assegno i dati // assegno i dati
CrvClass segClass ; CrvClass segClass ;
@@ -626,11 +610,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
// salvo dati correnti // salvo dati correnti
dCurrPar = InfoCorr[i].IciA[1].dU ; dCurrPar = InfoCorr[i].IciA[1].dU ;
dCurrLen = dLenU ; dCurrLen = dLenU ;
// se sono in un caso di spike devo trattare l'overlap in modo diverso nLastTy = InfoCorr[i].IciA[1].nNextTy ;
if ( ! bSpike)
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
else
nLastTy = InfoCorr[i].IciA[0].nPrevTy ;
} }
} }
// eventuale tratto finale rimasto // eventuale tratto finale rimasto
@@ -659,7 +639,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
double dStartParB, dEndParB ; double dStartParB, dEndParB ;
if ( ! pCurveB->GetDomain( dStartParB, dEndParB)) if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
return false ; return false ;
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne // se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
BBox3d boxCrvA, boxCrvB ; BBox3d boxCrvA, boxCrvB ;
if ( ! pCurveA->GetLocalBBox( boxCrvA) || if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
! pCurveB->GetLocalBBox( boxCrvB)) ! pCurveB->GetLocalBBox( boxCrvB))
@@ -702,37 +682,13 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
IntersCurveCurve iCC( clLine, *pCurveB) ; IntersCurveCurve iCC( clLine, *pCurveB) ;
// dichiaro la classe della curva per default // dichiaro la classe della curva per default
int nClass = CRVC_OUT ; int nClass = CRVC_OUT ;
// se c'è almeno una intersezione // se c'è almeno una intersezione
if ( iCC.GetIntersCount() > 0) { if ( iCC.GetIntersCount() > 0) {
// se quanto precede la prima intersezione è interno, allora la curva è interna // se quanto precede la prima intersezione è interno, allora la curva è interna
IntCrvCrvInfo aInfo ; IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ; iCC.GetIntCrvCrvInfo( 0, aInfo) ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN) if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_IN ; nClass = CRVC_IN ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
nClass = CRVC_OUT ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_NULL) {
// se il primo punto scelto non va bene allora ne cerco uno che mi dia informazioni sull'essere interno o esterno
CurveLine clLine ;
Point3d ptNewChoice ; pCurveA->GetPointD1D2( 0.25, ICurve::FROM_MINUS, ptNewChoice) ;
if ( ! clLine.SetPDL( ptNewChoice, 0, dLen))
return false ;
// calcolo l'intersezione
IntersCurveCurve iCC( clLine, *pCurveB) ;
if ( iCC.GetIntersCount() > 0) {
// se quanto precede la prima intersezione è interno, allora la curva è interna
IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_IN ;
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
nClass = CRVC_OUT ;
else
return false ; // se arrivo qui potrei ritentare la ricerca
}
else
return false ;
}
} }
// altrimenti sono esterni tra loro // altrimenti sono esterni tra loro
else { else {
@@ -756,7 +712,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
double dArea ; double dArea ;
if ( ! pCurve->GetAreaXY( dArea)) if ( ! pCurve->GetAreaXY( dArea))
return false ; return false ;
nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ; nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
return true ; return true ;
} }
+2 -10
View File
@@ -139,6 +139,8 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur
void void
IntersCurvePlane::OrderAndCompleteIntersections() IntersCurvePlane::OrderAndCompleteIntersections()
{ {
if ( m_Info.size() < 2)
return ;
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione // cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
// riempio le info PrevTy e NexyTy // riempio le info PrevTy e NexyTy
sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ; sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ;
@@ -235,16 +237,6 @@ IntersCurvePlane::GetIntersCount( void)
return m_nIntersCount ; return m_nIntersCount ;
} }
//----------------------------------------------------------------------------
bool
IntersCurvePlane::GetIntCrvPlnInfo( int nInd, IntCrvPlnInfo& aInfo)
{
if ( nInd < 0 || nInd >= m_nIntersCount)
return false ;
aInfo = m_Info[nInd] ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam) IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
+40 -158
View File
@@ -15,7 +15,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "IntersLineCyl.h" #include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h" #include "/EgtDev/Include/ENkPolynomialRoots.h"
using namespace std ; using namespace std ;
@@ -26,176 +25,99 @@ using namespace std ;
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2. // In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp, IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals) double dRad, double dHeight,
double& dU1, double& dU2)
{ {
dU1 = NAN ; // Verifico il versore
dU2 = NAN ; if ( vtL.IsSmall())
// Verifico il versore
if ( vtV.IsSmall())
return false ; return false ;
// Verifico il cilindro // Verifico il cilindro
if ( dRad < EPS_SMALL || dH < EPS_SMALL) if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
return false ; return false ;
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse) // Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
int nBasInt = 0 ; int nBasInt = 0 ;
if ( abs( vtV.z) > EPS_ZERO) { if ( abs( vtL.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti // le linee tangenti al cilindro non sono considerate intersecanti
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ; double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
if ( bIgnoreTap) Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ;
dEpsRad = 0. ; if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ; dU1 = ( ptInt1 - ptL) * vtL ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 1 ; nBasInt += 1 ;
vtN1 = - Z_AX ;
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
} }
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ; Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) { if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
dU2 = ( ptInt2 - ptL) * vtL ;
nBasInt += 2 ; nBasInt += 2 ;
vtN2 = Z_AX ;
dU2 = ( ( dH - ptP.z) / vtV.z) ;
} }
} }
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni // Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
if ( nBasInt == 3) { if ( nBasInt == 3) {
if ( dU1 > dU2) { if ( dU1 > dU2)
swap( dU1, dU2) ; swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ; // Trovate intersezioni
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Determino le intersezioni con la superficie laterale del cilindro // Determino le intersezioni con la superficie laterale del cilindro
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad, DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad,
2 * ( ptP.x * vtV.x + ptP.y * vtV.y), 2 * ( ptL.x * vtL.x + ptL.y * vtL.y),
vtV.x * vtV.x + vtV.y * vtV.y} ; vtL.x * vtL.x + vtL.y * vtL.y} ;
DBLVECTOR vdRoots ; DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ; int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
// Epsilon per piani di tappo // Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
if ( bIgnoreTap) {
dEpsLow = 0. ;
dEpsUp = 0. ;
}
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
if ( nRoot == 2) { if ( nRoot == 2) {
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ; double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ;
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp) if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL)
-- nRoot ; -- nRoot ;
} }
if ( nRoot >= 1) { if ( nRoot >= 1) {
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ; double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ;
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) { if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) {
if ( nRoot == 2) if ( nRoot == 2)
vdRoots[0] = vdRoots[1] ; vdRoots[0] = vdRoots[1] ;
-- nRoot ; -- nRoot ;
} }
} }
// Due soluzioni: la retta interseca due volte la superficie laterale // Due soluzioni: la retta interseca due volte la superficie laterale
if ( nRoot == 2) { if ( nRoot == 2) {
// Punti di intersezione con la superficie del cilindro
ptInt1 = ptP + vdRoots[0] * vtV ;
ptInt2 = ptP + vdRoots[1] * vtV ;
dU1 = vdRoots[0] ; dU1 = vdRoots[0] ;
dU2 = vdRoots[1] ; dU2 = vdRoots[1] ;
// Determino le normali if ( dU1 > dU2)
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
vtN1.Normalize() ;
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
vtN2.Normalize() ;
if ( dU1 > dU2) {
swap( dU1, dU2) ; swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ; // Trovate intersezioni
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Una soluzione : la retta interseca la superficie laterale e un piano // Una soluzione : la retta interseca la superficie laterale e un piano
else if ( nRoot == 1) { else if ( nRoot == 1) {
// Se piano superiore // Se piano superiore
if ( nBasInt == 2) { if ( nBasInt == 2) {
// Punto di intersezione
dU1 = vdRoots[0] ; dU1 = vdRoots[0] ;
ptInt1 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
vtN1.Normalize() ;
} }
// altrimenti piano inferiore // altrimenti piano inferiore
else if ( nBasInt == 1) { else if ( nBasInt == 1) {
// Punto di intersezione
dU2 = vdRoots[0] ; dU2 = vdRoots[0] ;
ptInt2 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
vtN2.Normalize() ;
} }
// altrimenti niente // altrimenti niente
else else
return false ; return false ;
if ( dU1 > dU2) { if ( dU1 > dU2)
swap( dU1, dU2) ; swap( dU1, dU2) ;
swap( ptInt1, ptInt2) ; // Trovate intersezioni
swap( vtN1, vtN2) ;
}
if ( bInvertNormals) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Trovate intersezioni
return true ; return true ;
} }
// Nessuna soluzione : nessuna intersezione // Nessuna soluzione : nessuna intersezione
else else
return false ; return false ;
} }
//----------------------------------------------------------------------------
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti.
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
if ( IntersLineCyl( ptP, vtV, dH, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap, bInvertNormals))
{
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
return true ;
}
return false ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Linea e cilindro sono nel medesimo riferimento. // Linea e cilindro sono nel medesimo riferimento.
// Il cilindro è definito con centro della base, asse, raggio e altezza. // Il cilindro è definito con centro della base, asse, raggio e altezza.
@@ -211,13 +133,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
if ( ! frCyl.Set( ptCyl, vtCyl)) if ( ! frCyl.Set( ptCyl, vtCyl))
return false ; return false ;
// Ora eseguo i conti nel riferimento intrinseco // Ora eseguo i conti nel riferimento intrinseco
bool bTapLow = false ; return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
bool bTapUp = false ;
bool bIgnoreTap = true ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -241,39 +157,5 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
if ( ! frCyl.Set( ptCyl1, vtCyl)) if ( ! frCyl.Set( ptCyl1, vtCyl))
return false ; return false ;
// Ora eseguo i conti nel riferimento intrinseco // Ora eseguo i conti nel riferimento intrinseco
bool bTapLow = false ; return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
bool bTapUp = false ;
bool bIgnoreTap = true ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
}
//----------------------------------------------------------------------------
// linea già nel riferimento intrinseco del cilindro
//----------------------------------------------------------------------------
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2)
{
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
bool bTapLow = false, bTapUp = false ;
bool bIgnoreTap = true ;
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
}
//----------------------------------------------------------------------------
// funzione esposta per altre dll
//----------------------------------------------------------------------------
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2)
{
return IntersLineCyl( ptLineSt, vtLineDir, CylFrame, dH, dRad, false, false,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true, false) ;
} }
+4 -23
View File
@@ -20,27 +20,17 @@
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY. // Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
// Con intersezione viene restituito true e i parametri in dU1 e dU2. // Con intersezione viene restituito true e i parametri in dU1 e dU2.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp, double dRad, double dHeight,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ; double& dU1, double& dU2) ;
// come sopra ma passo il riferimento intrinseco del cilindro in cui portare la linea
bool
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
inline bool inline bool
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL, TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight) double dRad, double dHeight)
{ {
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
double dU1, dU2 ; double dU1, dU2 ;
bool bTapLow = false, bTapUp = false ; return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ;
bool bIgnoreTap = true ;
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -60,12 +50,3 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL, bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad, const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
double& dU1, double& dU2) ; double& dU1, double& dU2) ;
//----------------------------------------------------------------------------
// // Linea e cilindro sono nel medesimo riferimento.
// Il cilindro è definito con raggio e altezza. ( la linea è già nel riferimento intrinseco del cilindro)
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
double dRad, double dHeight,
double& dU1, double& dU2) ;
+56 -28
View File
@@ -14,6 +14,7 @@
//--------------------------- Include ---------------------------------------- //--------------------------- Include ----------------------------------------
#include "stdafx.h" #include "stdafx.h"
#include "IntersLineLine.h" #include "IntersLineLine.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <algorithm> #include <algorithm>
using namespace std ; using namespace std ;
@@ -156,34 +157,34 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
double dCrossXY = CrossXY( vtDir1, vtDir2) ; double dCrossXY = CrossXY( vtDir1, vtDir2) ;
// flag per linee parallele // flag per linee parallele
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ; bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
// flag per segmenti che si allontanano significativamente // flag per segmenti che si allontanano significativamente
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ; bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
// analisi casi speciali di quasi parallelismo // analisi casi speciali di quasi parallelismo
// segmento sovrapposto all'altro // segmento sovrapposto all'altro
double dDist1, dDist2 ; double dDist1, dDist2 ;
if ( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) { if( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ; dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ;
dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ; dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ;
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) { if( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
bParallel = true ; bParallel = true ;
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ; bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
} }
} }
else if ( nS2Side == 0 || nE2Side == 0 || nS2Side == nE2Side) { else if( nS2Side == 0 || nE2Side == 0 || nS2Side == nE2Side) {
dDist1 = CrossXY( ptS2 - ptS1, vtDir1) ; dDist1 = CrossXY( ptS2 - ptS1, vtDir1) ;
dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ; dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ;
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY) { if( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY){
bParallel = true ; bParallel = true ;
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ; bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
} }
} }
// estremità sovrapposte di poco // estremità sovrapposte di poco
if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) { if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) || if (( nS1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) || ( nS1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) || ( nE1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) { ( nE1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
bParallel = true ; bParallel = true ;
bFarEnds = false ; bFarEnds = false ;
} }
@@ -194,27 +195,54 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
// posizioni parametriche dell'intersezione sulle linee // posizioni parametriche dell'intersezione sulle linee
m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ; m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ;
m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ; m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ;
// verifica posizione intersezione su prima linea // verifica posizione intersezione su prima linea
int nPos1 = ICurve::PP_NULL ; // fuori int nPos1 = ICurve::PP_NULL ; // fuori
if ( abs( m_Info.IciA[0].dU * dLen1XY) < EPS_SMALL) if ( nS1Side == 0 || nE1Side == 0) {
nPos1 = ICurve::PP_START ; // vicino a inizio if( nS1Side == 0) {
else if ( abs(( 1 - m_Info.IciA[0].dU) * dLen1XY) < EPS_SMALL) nPos1 = ICurve::PP_START ;
nPos1 = ICurve::PP_END ; // vicino a fine m_Info.IciA[0].dU = 0 ;
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1) m_Info.IciB[0].dU = vtDir2 * ( ptS1 - ptS2) / Pow( vtDir2.Len(), 2) ;
nPos1 = ICurve::PP_MID ; // nell'interno }
else else {
return ; nPos1 = ICurve::PP_END ;
m_Info.IciA[0].dU = 1 ;
m_Info.IciB[0].dU = vtDir2 * ( ptE1 - ptS2) / Pow( vtDir2.Len(), 2) ;
}
}
else {
if ( abs( m_Info.IciA[0].dU * dLen1XY) < EPS_SMALL)
nPos1 = ICurve::PP_START ; // vicino a inizio
else if ( abs(( 1 - m_Info.IciA[0].dU) * dLen1XY) < EPS_SMALL)
nPos1 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
nPos1 = ICurve::PP_MID ; // nell'interno
else
return ;
}
// verifica posizione intersezione su seconda linea // verifica posizione intersezione su seconda linea
int nPos2 = ICurve::PP_NULL ; // fuori int nPos2 = ICurve::PP_NULL ; // fuori
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL) if ( nS2Side == 0 || nE2Side == 0) {
nPos2 = ICurve::PP_START ; // vicino a inizio if( nS2Side == 0) {
else if ( abs(( 1 - m_Info.IciB[0].dU) * dLen2XY) < EPS_SMALL) nPos2 = ICurve::PP_START ;
nPos2 = ICurve::PP_END ; // vicino a fine m_Info.IciB[0].dU = 0 ;
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1) m_Info.IciA[0].dU = vtDir1 * (ptS2 - ptS1) / Pow( vtDir1.Len(), 2) ;
nPos2 = ICurve::PP_MID ; // nell'interno }
else else {
return ; nPos2 = ICurve::PP_END ;
// limito i parametri a stare sui segmenti (0...1) m_Info.IciB[0].dU = 1 ;
m_Info.IciA[0].dU = vtDir1 * (ptE2 - ptS1) / Pow( vtDir1.Len(), 2) ;
}
}
else {
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
nPos2 = ICurve::PP_START ; // vicino a inizio
else if ( abs(( 1 - m_Info.IciB[0].dU) * dLen2XY) < EPS_SMALL)
nPos2 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
nPos2 = ICurve::PP_MID ; // nell'interno
else
return ;
} // limito i parametri a stare sui segmenti (0...1)
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ; m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ;
m_Info.IciB[0].dU = min( max( m_Info.IciB[0].dU, 0.), 1.) ; m_Info.IciB[0].dU = min( max( m_Info.IciB[0].dU, 0.), 1.) ;
// calcolo i punti sulle due linee (possono differire in Z) // calcolo i punti sulle due linee (possono differire in Z)
+19 -357
View File
@@ -72,28 +72,14 @@ static void
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos, UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo) const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
{ {
int nType = LSBT_NONE ;
if ( dCos > EPS_ZERO)
nType = LSBT_IN ;
else if ( dCos < EPS_ZERO)
nType = LSBT_OUT ;
else
nType = LSBT_TOUCH ;
if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) { if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) {
double dU = ( ptIBz - ptL) * vtDir ; double dU = ( ptIBz - ptL) * vtDir ;
vInfo.emplace_back( nType, dU, nT, dCos, ptIBz, ptSP) ; vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
} }
else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) { else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
double dU = ( ptIBz - ptL) * vtDir ; double dU = ( ptIBz - ptL) * vtDir ;
double dU2 = ( ptIBz2 - ptL) * vtDir ; double dU2 = ( ptIBz2 - ptL) * vtDir ;
int nType2 = LSBT_NONE ; vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
if ( dCos2 > EPS_ZERO)
nType2 = LSBT_IN ;
else if ( dCos2 < EPS_ZERO)
nType2 = LSBT_OUT ;
vInfo.emplace_back( nType, dU, 0, nT, dCos, ptIBz, P_INVALID, ptSP, P_INVALID) ;
vInfo.emplace_back( nType2, dU2, 0, nT, dCos2, ptIBz2, P_INVALID, ptSP2, P_INVALID) ;
} }
} }
@@ -107,7 +93,9 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea // ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(), sort( vInfo.begin(), vInfo.end(),
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b) []( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
{ return ( a.dU < b.dU) ; }) ; { double dUa = ( ( a.nILTA == ILTA_SEGM || a.nILTA == ILTA_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -193,9 +181,19 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
// ciclo sulle intersezioni // ciclo sulle intersezioni
for ( const auto& Info : vInfo) { for ( const auto& Info : vInfo) {
// se intersezione puntuale // se intersezione puntuale
vInters.emplace_back( Info.nILSB, Info.dU) ; if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) {
// se intersezione sovrapposta int nFlag = LSBT_TOUCH ;
// da sviluppare if ( Info.dCosDN > EPS_ZERO)
nFlag = LSBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LSBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTA == ILTA_SEGM || Info.nILTA == ILTA_SEGM_ON_EDGE) {
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
}
} }
// elimino intersezioni ripetute // elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) { for ( size_t j = 1 ; j < vInters.size() ; ) {
@@ -241,343 +239,7 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Intersezione di una linea con una superficie di Bezier di grado 3x1 monopatch // Intersezione di una linea con una superficie di Bezier
//----------------------------------------------------------------------------
bool
IntersLineSurfBzCubicLinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
ILSBIVECTOR& vInfo, bool bFinite)
{
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
// funzione pensata per funzionare solo con una monopatch di grado 3x1
if ( nDegU != 3 || nDegV != 1 || nSpanU > 1 || nSpanV > 1 || bRat)
return false ;
int nInters = int( vInfo.size()) ;
Point3d r = ptL ;
Vector3d q = vtL ;
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
Frame3d frRot ;
if ( bNeedToRotX)
frRot.Set( ORIG, X_AX) ;
if ( bNeedToRotY)
frRot.Set( ORIG, Y_AX) ;
if ( bNeedToRot) {
r.ToLoc( frRot) ;
q.ToLoc( frRot) ;
}
PNTVECTOR vPntCtrl = pSurfBz->GetAllControlPoints() ;
if ( bNeedToRot) {
for ( Point3d& pt: vPntCtrl)
pt.ToLoc( frRot) ;
}
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
Vector3d E = vPntCtrl[0] - ORIG ;
Vector3d F = vPntCtrl[1] - ORIG ;
Vector3d G = vPntCtrl[2] - ORIG ;
Vector3d H = vPntCtrl[3] - ORIG ;
Vector3d a3 = -A + 3 * B - 3 * C + D ;
Vector3d a2 = 3 * A - 6 * B + 3 * C ;
Vector3d a1 = -3 * A + 3 * B ;
Vector3d a0 = A ;
Vector3d b3 = -E + 3 * F - 3 * G + H ;
Vector3d b2 = 3 * E - 6 * F + 3 * G ;
Vector3d b1 = -3 * E + 3 * F ;
Vector3d b0 = E ;
DBLVECTOR vdCoeff, vdRoots ;
// coefficienti dal grado più basso al grado più alto
vdCoeff = { // c0
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
// c1
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
// c2
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) + q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
// c3
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) + q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
// c4
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
// c5
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
// c6
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
q.y*q.z*a3.z*b3.x - q.z*q.z*a3.y*b3.x + // 4
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
bool bFound = false ;
for ( int w = 0 ; w < nRoots ; ++w) {
double dU = 0, dV = 0 ;
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
dU = vdRoots[w] ;
// verifico che non sia una soluzione con molteplicità > 1
bool bAlreadyFound = false ;
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
bAlreadyFound = ( abs( dU - vdRoots[k]) < EPS_PARAM) ;
if ( ! bAlreadyFound) {
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
double dDen = ( vAlpha.x * q.z - vAlpha.z * q.x) ;
if ( abs( dDen) > EPS_ZERO)
dV = ( ( vBeta.z - r.z) * q.x - ( vBeta.x - r.x ) * q.z) / dDen ;
else {
// se la prima equazione risulta un x/0 allora uso la seconda equazione per trovare il secondo parametro
double dDen2 = ( vAlpha.y * q.z - vAlpha.z * q.y) ;
dV = ( ( vBeta.z - r.z) * q.y - ( vBeta.y - r.y ) * q.z) / dDen2 ;
}
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
Point3d ptIBez, ptIBez2 ;
Vector3d vtN ;
pSurfBz->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez, vtN) ;
Point3d ptSP( dU, dV, 0), ptSP2 ;
double dCos = vtN * vtL, dCos2 = 0 ;
int nType = ILTA_NO_TRIA ;
UpdateInfoIntersLineSurfBz( ptL, vtL, nType, -1, ptSP, ptIBez, dCos, ptSP2, ptIBez2, dCos2, vInfo) ;
bFound = true ;
}
}
}
}
//// se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie
//// per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie
//if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
// ICRVCOMPOPOVECTOR vCrvEdge( 4) ;
// vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ;
// vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ;
// vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ;
// vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ;
// double dAngTolDeg = 5 ;
// for ( int i = 0 ; i < 4 ; ++i) {
// PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ;
// //CurveComposite cCC ;
// //cCC.FromPolyLine( plApprox) ;
// int nClosestLine = -1 ;
// double dMinDist = INFINITO ;
// Point3d pt ; plApprox.GetFirstPoint( pt) ;
// Point3d ptClosest ;
// int c = 0 ;
// int nTot = plApprox.GetPointNbr() ;
// for ( int j = 0 ; j < nTot ; ++j) {
// DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ;
// double dDist = INFINITO ;
// dpl.GetDist( dDist) ;
// if ( dDist < dMinDist) {
// nClosestLine = c ;
// dMinDist = dDist ;
// }
// plApprox.GetNextPoint( pt) ;
// ++ c ;
// }
// Point3d ptInt1, ptInt2 ;
// if ( nClosestLine < nTot - 1 && nClosestLine > 0) {
// // tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ;
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
// plApprox.GetNextPoint( ptStart) ;
// plApprox.GetNextPoint( ptEnd) ;
// // linea precedente al punto
// Vector3d vtLinePre = ptEnd - ptStart ;
// double dLenPre = vtLinePre.Len() ;
// DistLineLine dllPre( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
// double dDistPre = INFINITO ;
// dllPre.GetDist( dDistPre) ;
// // linea che inzia con quel punto
// ptStart = ptEnd ;
// plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLineCurr = ptEnd - ptStart ;
// double dLenCurr = vtLineCurr.Len() ;
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
// double dDistCurr = INFINITO ;
// dllCurr.GetDist( dDistCurr) ;
// if ( dDistPre < dDistCurr)
// dllPre.GetMinDistPoints( ptInt1, ptInt2) ;
// else
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
// else if ( nClosestLine == 0) {
// // il punto più vicino è sulla prima linea
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLineCurr = ptEnd - ptStart ;
// double dLenCurr = vtLineCurr.Len() ;
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
// else if ( nClosestLine == nTot- 1) {
// // il punto più vicino è sull'ultima linea
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
// Point3d ptEnd ;
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
// plApprox.GetNextPoint( ptStart) ;
// plApprox.GetNextPoint( ptEnd) ;
// Vector3d vtLinePre = ptEnd - ptStart ;
// double dLenPre = vtLinePre.Len() ;
// DistLineLine dllCurr( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
// }
//
// double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ;
// // se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve
// if ( ! AreSamePointExact( ptInt2, ORIG)) {
// if ( i == 0) {
// //dV1 = 0 ; dV2 = 0 ;
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
// vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ;
// }
// else if ( i == 1) {
// //dU1 = 1 ; dU2 = 1 ;
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
// vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ;
// }
// else if ( i == 2){
// //dV1 = 1 ; dV2 = 1 ;
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
// vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ;
// }
// else if ( i == 3){
// //dU1 = 0 ; dU2 = 0 ;
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
// vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ;
// }
// Point3d ptIBez1, ptIBez2 ;
// Vector3d vtN1, vtN2 ;
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
// pSurfBz->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez2, vtN2) ;
// Point3d ptSP1( dU1, dV1, 0) ;
// double dCos1 = vtN1 * vtL ;
// Point3d ptSP2( dU2, dV2, 0) ;
// double dCos2 = vtN2 * vtL ;
// // se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che
// // avevo salvato e aggiungo quella sovrapposto che ho trovato ora
// if ( bFound) {
// int nNewTot = int(vInfo.size()) ;
// int nNewInters = nNewTot - nInters ;
// bool bAlreadyFound = false ;
// for ( int i = 0 ; i < nNewInters ; ++i) {
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ;
// if ( bAlreadyFound) {
// vInfo.erase( vInfo.begin() + nNewTot - i) ;
// break ;
// }
// }
// }
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
// bFound = true ;
// break ;
// }
// // se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione
// else if ( dMinDist < EPS_SMALL) {
// if ( i == 0) {
// //dV1 = 0 ;
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
// }
// else if ( i == 1) {
// //dU1 = 1 ;
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
// }
// else if ( i == 2) {
// //dV1 = 1 ;
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
// }
// else if ( i == 3) {
// //dU1 = 0 ;
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
// }
// Point3d ptSP1( dU1, dV1, 0), ptSP2 ;
// // se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie)
// if ( bFound) {
// int nNewTot = int(vInfo.size()) ;
// int nNewInters = nNewTot - nInters ;
// bool bAlreadyFound = false ;
// for ( int i = 0 ; i < nNewInters ; ++i)
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ;
// if ( bAlreadyFound)
// continue ;
// }
// Point3d ptIBez1, ptIBez2 ;
// Vector3d vtN1, vtN2 ;
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
// double dCos1 = vtN1 * vtL, dCos2 = 0 ;
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
// bFound = true ;
// }
// }
//}
// se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato
if ( bTrimmed && bFound) {
int nNewTot = int(vInfo.size()) ;
int nNewInters = nNewTot - nInters ;
const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ;
for ( int i = 0 ; i < nNewInters ; ++i) {
Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ;
bool bInside = false ;
double dDist = INFINITO ;
IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ;
if ( ! bInside)
vInfo.erase( vInfo.begin() + nNewTot - i) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Intersezione di una linea con una superficie di Bezier bilineare monopatch
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz, IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
-547
View File
@@ -1,547 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2026
//----------------------------------------------------------------------------
// File : OffsetCurve3d.cpp Data : 10.06.26 Versione : 3.1f1
// Contenuto : Classe per offset di Curve 3d.
//
//
//
// Modifiche : 10.06.26 DB Creazione modulo.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "CurveLine.h"
#include "CurveComposite.h"
#include "RemoveCurveDefects.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkPoint3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
using namespace std ;
#define SAVECVRORIG 0
#define SAVEOFFDIR 0
#define SAVECYL 0
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
vector<IGeoObj*> vGeo ;
vector<Color> vCol ;
#include "CurveArc.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#endif
//----------------------------------------------------------------------------
struct OffsetSegm {
PtrOwner<ICurve> pCrv ;
int nFlag ;
int nParent ;
OffsetSegm( ICurve* _pCrv, int _nFlag, int _nParent) :
nFlag( _nFlag), nParent( _nParent) { pCrv.Set( _pCrv); } ;
} ;
typedef vector<OffsetSegm> vOffsetSeg ;
bool AdjustConcavePartsInPath( const ICurveComposite* pCrv, vOffsetSeg& vOffsetCrvs, double dRad) ;
//----------------------------------------------------------------------------
OffsetCurve3d::~OffsetCurve3d( void)
{
Reset() ;
}
//----------------------------------------------------------------------------
bool
OffsetCurve3d::Reset( void)
{
for ( auto& pCrv : m_CrvLst) {
if ( pCrv != nullptr) {
delete pCrv ;
pCrv = nullptr ;
}
}
m_CrvLst.clear() ;
return true ;
}
//----------------------------------------------------------------------------
bool
OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType)
{
// la funzione è pensata per lavorare con il risultato dell'operazione ProjectCurveOnSurf
// vOffDir devono essere normalizzati
// mi aspetto che siano più o meno perpendicolari alla curva
// pulisco tutto
Reset() ;
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
if ( ! pCrv->FromPolyLine( PL))
return false ;
#if SAVECVRORIG || SAVEOFFDIR
vGeo.clear() ;
vCol.clear() ;
vGeo.push_back( pCrv->Clone()) ;
vCol.push_back( AQUA) ;
#if SAVEOFFDIR
Point3d ptBase ; PL.GetFirstPoint( ptBase) ;
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
IGeoVector3d* pVec = CreateGeoVector3d() ;
pVec->Set( vOffDir[i] * dOffDist, ptBase) ;
PL.GetNextPoint( ptBase) ;
vGeo.push_back( pVec) ;
vCol.push_back( BLUE) ;
}
#endif
#endif
// verifico se la curva è un segmento di retta
bool bIsLine = PL.GetPointNbr() == 2 ;
if ( bIsLine) {
// faccio l'offset di una linea
return true ;
}
// se offset nullo, copio la curva ed esco
if ( abs( dOffDist) < 10 * EPS_SMALL) {
PtrOwner<CurveComposite> pCopy( CreateBasicCurveComposite()) ;
if ( IsNull( pCopy) || ! pCopy->CopyFrom( pCrv))
return false ;
// unisco parti allineate (tranne gli estremi)
pCopy->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
// sposto in lista
m_CrvLst.push_back( Release( pCopy)) ;
return true ;
}
bool bClosed = pCrv->IsClosed() ;
INTVECTOR vFlag ;
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
const double dSinAngSmall = sin( 1 * DEGTORAD) ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pSubCrv = pCrv->GetNextCurve() ;
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
vtDirCurr.Normalize() ;
int nFlag ;
double dProj = vtDirCurr * vOffDir[i-1] ;
if ( dProj > dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
else if ( dProj > - dSinAngSmall)
nFlag = OffsetCurve3d::AngType::ANG_STR ;
else
nFlag = OffsetCurve3d::AngType::ANG_CVEX ;
vFlag.push_back( nFlag) ;
}
for ( int i = 1 ; i < ssize( vFlag) - 1 ; ++i) {
if ( vFlag[i-1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
vFlag[i+1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC &&
vFlag[i] != OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
vFlag[i] = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ;
}
double dRadCorr ;
Point3d ptPrev ; pCrv->GetStartPoint( ptPrev) ;
ptPrev += vOffDir[0] * dOffDist ;
Vector3d vtNormPrev ;
Vector3d vtCorrPrev ;
Vector3d vtTangPrev ;
Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ;
const ICurve* pCrvPrev = pCrv->GetFirstCurve() ;
const ICurve* pCrvCurr ;
vOffsetSeg vOffsetCrvs ;
Vector3d vtDirPrevOff = V_INVALID ;
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
pCrvCurr = pCrv->GetNextCurve() ;
Vector3d vtOffDir = vOffDir[i] ;
Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ;
pCrvPrev->GetStartDir( vtDirPrev) ;
Vector3d vtTang ;
if ( vFlag[i] != OffsetCurve3d::AngType::ANG_CVEX)
vtTang = Media( vtDirCurr, vtDirPrev) ;
else if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] != OffsetCurve3d::AngType::ANG_CVEX)
vtTang = vtDirPrev ;
else
vtTang = vtDirCurr ;
vtTang.Normalize() ;
Vector3d vtNorm = vtOffDir ;
vtNorm.Rotate( vtTang, -90) ;
//Vector3d vtCorr = vtTang ^ vtNorm ; vtCorr.Normalize() ;
// devo invertire vtCorr??? se sì, quando?/////////////////////////////////////////
Vector3d vtCorr = vtOffDir ;
double dCorrK = 1 ;
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CONC) {
double dHalfAlfa = acos( vtTang * vtTangPrev) ;
dCorrK = 1 / sin( 90 - dHalfAlfa) ;
}
Point3d ptP ; pCrvCurr->GetStartPoint( ptP) ;
dRadCorr = dOffDist ;
ptP = ptP + dRadCorr * dCorrK * vtCorr ;
// se secondo punto di angolo esterno di fianco, inserisco movimenti intermedi
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] == OffsetCurve3d::AngType::ANG_CVEX) {
double dAlfa = acos( vtTang * vtTangPrev) ;
double dDelta = dOffDist * tan( dAlfa / 4) ;
Point3d ptAdd1 = ptPrev + dDelta * vtTangPrev ;
ICurveLine* pCL1 = CreateBasicCurveLine() ;
pCL1->Set( ptPrev, ptAdd1) ;
vOffsetCrvs.emplace_back( pCL1, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
Point3d ptAdd2 = ptP - dDelta * vtTang ;
ICurveLine* pCL2 = CreateBasicCurveLine() ;
pCL2->Set( ptAdd1, ptAdd2) ;
vOffsetCrvs.emplace_back( pCL2, OffsetCurve3d::AngType::ANG_CVEX, -1) ;
ptPrev = ptAdd2 ;
}
//// se punto di angolo interno di fianco, elimino eventuali movimenti precedenti invertiti
//if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX == 3) {
// local nLastId = EgtGetLastInGroup( nClPathId)
// while nLastId do
// local vtMlast = ptP - EgtEP( nLastId, GDB_ID.ROOT) ; vtMlast:normalize()
// if vtMlast * vtGpre < 0.5 then
// ptPpre = EgtSP( nLastId, GDB_ID.ROOT)
// EgtErase( nLastId)
// else
// break
// end
// nLastId = EgtGetLastInGroup( nClPathId)
// end
//}
//// se appena dopo angolo interno di fianco, verifico se da aggiungere
//bool bToAdd = true
//if ( nFlpre == 3 and abs( dSideAng) > GEO.EPS_ANG_SMALL) {
// local vtMove = ptP - ptPpre ; vtMove:normalize()
// if vtMove * vtTang < 0.5 then
// bToAdd = false
// end
//}
Vector3d vtDirCurrOff = ptP - ptPrev ; vtDirCurrOff.Normalize() ;
double dProj = 1 ;
if ( vtDirPrevOff.IsValid())
dProj = vtDirCurrOff * vtDirPrevOff ;
if ( dProj > - 0.5 || vFlag[i] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
// aggiungo tratto
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL, vFlag[i], i - 1) ;
// aggiorno punto precedente
ptPrev = ptP ;
vtNormPrev = vtNorm ;
vtCorrPrev = vtCorr ;
vtTangPrev = vtTang ;
vtDirPrev = vtDirCurr ;
pCrvPrev = pCrvCurr ;
vtDirPrevOff = vtDirCurrOff ;
}
}
// se chiusa aggiungo il tratto di chiusura
if ( bClosed) {
Point3d ptP ; vOffsetCrvs.front().pCrv->GetStartPoint( ptP) ;
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptPrev, ptP) ;
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ;
}
// qui faccio la correzione per gli angoli interni
if ( ! AdjustConcavePartsInPath( pCrv, vOffsetCrvs, dOffDist))
return false ;
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
vGeo.push_back( vOffsetCrvs[i].pCrv->Clone()) ;
if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC)
vCol.push_back( GREEN) ;
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_STR)
vCol.push_back( PURPLE) ;
else if ( vOffsetCrvs[i].nFlag == OffsetCurve3d::AngType::ANG_CVEX)
vCol.push_back( RED) ;
}
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
return true ;
#endif
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i].pCrv)))
return false ;
}
m_CrvLst.push_back( Release( pCrvOffset)) ;
return true ;
// raccordi
// angoli interni
// angoli esterni
// auto intersezioni
//// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
//// ottavo passo : concateno i percorsi risultanti (senza cambiare verso)
//// nono passo : se con smusso o estensione, sostituisco i fillet con questi
//// ordino le curve in ordine decrescente di lunghezza
//if ( m_CrvLst.size() > 1) {
// for ( auto pCrv : m_CrvLst) {
// double dLen ;
// if ( pCrv->GetLength( dLen))
// pCrv->SetTempProp( int( 1000 * dLen)) ;
// else
// pCrv->SetTempProp( 0) ;
// }
// m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
//}
//// se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle
//if ( bClosed) {
// for ( auto pCrv : m_CrvLst) {
// CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
// if ( pCrvCo != nullptr)
// pCrvCo->Close() ;
// }
//}
//return true ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetCurve( void)
{
return GetLongerCurve() ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetLongerCurve( void)
{
if ( m_CrvLst.empty())
return nullptr ;
// le curve sono ordinate in senso decrescente di lunghezza
ICurve* pCrv = m_CrvLst.front() ;
m_CrvLst.pop_front() ;
return pCrv ;
}
//----------------------------------------------------------------------------
ICurve*
OffsetCurve3d::GetShorterCurve( void)
{
if ( m_CrvLst.empty())
return nullptr ;
// le curve sono ordinate in senso decrescente di lunghezza
ICurve* pCrv = m_CrvLst.back() ;
m_CrvLst.pop_back() ;
return pCrv ;
}
struct Cyl {
Cyl( void): frCyl( GLOB_FRM), dH( 0.), dRad( 0.) {;} ;
Cyl( const Frame3d& _frCyl, double _dH, double _dRad, double _dLinTol) :
frCyl( _frCyl), dH( _dH), dRad( _dRad) { ;}
Cyl( const Point3d& _ptBase, const Vector3d& vtZ, double _dH, double _dRad, double _dLinTol) :
dH( _dH), dRad( _dRad){
frCyl.Set( _ptBase, vtZ); }
public :
Frame3d frCyl ;
public:
double dH ;
double dRad ;
};
typedef vector<Cyl> CYLVECT ;
//----------------------------------------------------------------------------
bool
IsPointInsideCylinder( const Point3d& ptTest, const Cyl& offCyl, double dLinTol)
{
Point3d ptTestLoc = ptTest ; ptTestLoc.ToLoc( offCyl.frCyl) ;
if ( ptTestLoc.z > offCyl.dH || ptTestLoc.z < 0)
return false ;
double dDist = ptTestLoc.x * ptTestLoc.x + ptTestLoc.y * ptTestLoc.y ;
double dRadSq = ( offCyl.dRad - dLinTol) * ( offCyl.dRad - dLinTol) ;
if ( dDist > dRadSq)
return false ;
return true ;
}
bool
AdjustConcavePartsInPath( const ICurveComposite* pCrv, vOffsetSeg& vOffsetCrvs, double dRad)
{
const double dLinTol = 5 * EPS_SMALL ;
INTVECTOR vErase ;
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
int nFlag = vOffsetCrvs[i].nFlag ;
if ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
// scorro i prossimi finchè trovo la fine della zona concava
INTVECTOR vLines ;
while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
vLines.push_back( i) ;
++i ;
nFlag = vOffsetCrvs[i].nFlag ;
}
CYLVECT vCyl ;
// creo un cilindro della dimensione del raggio
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
if ( vOffsetCrvs[vLines[j]].nParent == -1)
continue ;
const ICurve* pSubCrv = pCrv->GetCurve( vOffsetCrvs[vLines[j]].nParent) ;
Point3d ptStart, ptEnd ;
pSubCrv->GetStartPoint( ptStart) ;
pSubCrv->GetEndPoint( ptEnd) ;
Vector3d vtHeight = ptEnd - ptStart ;
double dHeight = vtHeight.Len() ;
vtHeight.Normalize() ;
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
#if SAVECYL
CurveArc ca ; ca.Set( ptStart, vtHeight, dRad) ;
ISurfTriMesh* pSurfTm = GetSurfTriMeshByExtrusion( &ca, vtHeight, false, 2 * EPS_SMALL) ;
vGeo.push_back( pSurfTm) ;
vCol.push_back( LGRAY) ;
#endif
}
// controllo l'end di ogni linea per verificare se sta nel cilindro definito da uno degli altri tratti
// controllo tutto i punti
bool bErasedSomePart = false ;
bool bErasedPrev = false ;
INTVECTOR vInters ;
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
Point3d ptStart, ptEnd ;
const ICurve* pSubCrv = vOffsetCrvs[vLines[j]].pCrv ;
if ( pSubCrv == nullptr)
return false ;
pSubCrv->GetEndPoint( ptEnd) ;
pSubCrv->GetStartPoint( ptStart) ;
// se stanno in uno dei cilindri degli altri tratti della zona concava
for ( int k = 0 ; k < ssize( vLines) ; ++k) {
if ( j == k)
continue ;
bool bToErase = IsPointInsideCylinder( ptEnd, vCyl[k], dLinTol) ;
if ( bErasedPrev && ! bToErase)
bToErase = bToErase || IsPointInsideCylinder( ptStart, vCyl[k], dLinTol) ;
if ( bToErase) {
bErasedSomePart = true ;
bErasedPrev = true ;
vInters.push_back( vLines[j]) ;
if ( j < ssize( vLines) - 1)
vInters.push_back( vLines[j+1]) ;
++j ;
break ;
}
else
bErasedPrev = false ;
}
}
if ( bErasedSomePart) {
// calcolo le intersezioni effettive del primo e ultimo tratto cancellati con i cilindri che li hanno cancellati
// controllo che effettivamente tutti i tratti cancellati siano consecutivi
for ( int j = 1 ; j < ssize( vInters) ; ++j) {
if ( vInters[j] != vInters[j-1] + 1)
return false ;
}
for ( int j = 0 ; j < ssize( vInters) ; ++j) {
// cancello i tratti intermedi
if ( j > 0 && j < ssize( vInters) - 1) {
vErase.push_back( vInters[j]) ;
continue ;
}
// per il primo e ultimo controllo le intersezioni con tutti i cilindri
ICurve* pCL = vOffsetCrvs[vInters[j]].pCrv ;
Point3d ptStart ; pCL->GetStartPoint( ptStart) ;
Vector3d vtStart ; pCL->GetStartDir( vtStart) ;
double dLen ; pCL->GetLength( dLen) ;
double dUTrim = ( j == 0 ? INFINITO : 0) ;
Point3d ptTrim = P_INVALID ;
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
if ( vInters[j] == k)
continue ;
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
double dU1, dU2 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCyl( ptStart, vtStart * dLen, vCyl[k].frCyl, vCyl[k].dH, vCyl[k].dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true)) {
bool bUpdate = ( j == 0 ? dU1 < dUTrim : dU1 > dUTrim) ;
bUpdate = bUpdate && ptInt1.IsValid() && dU1 > 0 && dU1 < 1 ;
bUpdate = bUpdate && vtN1 * vtStart < 0 ;
if ( bUpdate) {
dUTrim = dU1 ;
ptTrim = ptInt1 ;
}
bUpdate = ( j == 0 ? dU2 < dUTrim : dU2 > dUTrim) ;
bUpdate = bUpdate && ptInt2.IsValid() && dU2 > 0 && dU2 < 1 ;
bUpdate = bUpdate && vtN2 * vtStart > 0 ;
if ( bUpdate) {
dUTrim = dU2 ;
ptTrim = ptInt2 ;
}
}
}
if ( ptTrim.IsValid()) {
if ( j == 0) {
pCL->ModifyEnd( ptTrim) ;
double dNewLen ; pCL->GetLength( dNewLen) ;
if ( dNewLen < 0.1 && vInters[0] != 0) { // se fosse il primo allora potrei modificare il successivo
int nPrev = vInters[0] - 1 ;
vErase.push_back( vInters[0]) ;
vInters[0] = nPrev ;
ICurve* pCLPrev = vOffsetCrvs[nPrev].pCrv ;
pCLPrev->ModifyEnd( ptTrim) ;
}
}
else {
pCL->ModifyStart( ptTrim) ;
double dNewLen ; pCL->GetLength( dNewLen) ;
if ( dNewLen < 0.1 && vInters[j] != ssize( vOffsetCrvs) - 1) { // se fosse l'ultima curva allora potrei modificare la precedente
int nNext = vInters[j] + 1 ;
vErase.push_back( vInters[j]) ;
vInters[j] = nNext ;
ICurve* pCLNext = vOffsetCrvs[nNext].pCrv ;
pCLNext->ModifyStart( ptTrim) ;
}
}
}
}
}
i = vLines.back() ;
}
}
// cancello le curve indicate in vErase
for ( int i = ssize( vErase) - 1 ; i >= 0 ; --i) {
vOffsetCrvs.erase( vOffsetCrvs.begin() + vErase[i]) ;
}
// scorro tutto il vettore delle linee di offset e unisco aggiungendo una linea dove ne ho cancellate
for ( int i = 0 ; i < ssize( vOffsetCrvs) - 1 ; ++i) {
Point3d ptEndCurr, ptStartNext ;
vOffsetCrvs[i].pCrv->GetEndPoint( ptEndCurr) ;
vOffsetCrvs[i+1].pCrv->GetStartPoint( ptStartNext) ;
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
ICurveLine* pCL = CreateBasicCurveLine() ;
pCL->Set( ptEndCurr, ptStartNext) ;
vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR,-1) ;
rotate( vOffsetCrvs.begin() + i + 1, vOffsetCrvs.end() - 1, vOffsetCrvs.end()) ;
++i ;
}
}
return true ;
}
+8 -2
View File
@@ -1991,11 +1991,17 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
nAddedSpan = 0 ; nAddedSpan = 0 ;
nCrv1 = 0 ; nCrv1 = 0 ;
nCrv2 = 0 ; nCrv2 = 0 ;
bool bLast1 = false ;
bool bLast2 = false ;
while ( nAddedSpan < nPnt) { while ( nAddedSpan < nPnt) {
if ( nCrv1 >= nPnt1) if ( nCrv1 >= nPnt1) {
nCrv1 = nPnt1 - 1 ; nCrv1 = nPnt1 - 1 ;
if ( nCrv2 >= nPnt2) bLast1 = true ;
}
if ( nCrv2 >= nPnt2) {
nCrv2 = nPnt2 - 1 ; nCrv2 = nPnt2 - 1 ;
bLast2 = true ;
}
bool bRep1 = vbRep1[nCrv1] ; bool bRep1 = vbRep1[nCrv1] ;
bool bRep2 = vbRep2[nCrv2] ; bool bRep2 = vbRep2[nCrv2] ;
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ; const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
+1 -1
View File
@@ -173,7 +173,7 @@ Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN,
{ {
Plane3d plPlane ; Plane3d plPlane ;
plPlane.Set( ptOn, vtN) ; plPlane.Set( ptOn, vtN) ;
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt, dToler) ; return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt) ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+14 -22
View File
@@ -172,9 +172,9 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
return true ; return true ;
} }
} }
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO) else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
dElev = max( dElev, Inters.dU) ; dElev = max( dElev, Inters.dU) ;
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE) else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
dElev = max( dElev, Inters.dU2) ; dElev = max( dElev, Inters.dU2) ;
} }
} }
@@ -206,30 +206,22 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL) if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
continue ; continue ;
// calcolo il segmento di linea // calcolo il segmento di linea
CurveLine clLine ; CurveLine clLine ;
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second)) if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
return false ; return false ;
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop // l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
IntersCurveCurve intLL( clLine, ccLoop) ; IntersCurveCurve intLL( clLine, ccLoop) ;
if ( intLL.GetIntersCount() == 0) { IntCrvCrvInfo aInfo ;
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ; for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
ptM.z = 0 ; dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL)) if ( aInfo.bOverlap)
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ; dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
} // se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
else { if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
IntCrvCrvInfo aInfo ; dElev = max( dElev, vEdges[i].first.z) ;
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) { // se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
dElev = max( dElev, aInfo.IciA[0].ptI.z) ; else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
if ( aInfo.bOverlap) dElev = max( dElev, vEdges[i].second.z) ;
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
dElev = max( dElev, vEdges[i].first.z) ;
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
dElev = max( dElev, vEdges[i].second.z) ;
}
} }
} }
+127 -307
View File
@@ -19,7 +19,6 @@
#include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h" #include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
@@ -40,7 +39,6 @@ const int P5AX_CVEX = 2 ; // su angolo convesso
const int P5AX_CONC = 3 ; // in angolo concavo const int P5AX_CONC = 3 ; // in angolo concavo
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static double static double
@@ -65,7 +63,6 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
static bool static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{ {
const double dSinSmallAngle = sin( 0 * DEGTORAD) ;
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
// precedente // precedente
int j = i - 1 ; int j = i - 1 ;
@@ -81,28 +78,20 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Point3d ptInt ; Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo // verifico se spigolo convesso o concavo
bool bConvex = (vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 < 0 ; bool bConvex ;
bool bValidInters = true ; if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
if ( i > 2) { bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
int k = i - 2 ; else
// verifico la concavità anche tornando indietro lungo la linea bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
if ( ( ( vPt5ax[k].ptP - vPt5ax[j].ptP) * vPt5ax[i].vtDir1 < 0) != bConvex) {
LOG_WARN( GetEGkLogger(), "La superficie su cui si sta proiettando la curva ha delle normali incoerenti")
return false ;
}
// verifico che l'intersezione sia tra i e j e non prima di j
bValidInters = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[j].ptP - vPt5ax[k].ptP) > 0 ;
}
// se convesso, metto due punti con direzione appena prima e appena dopo // se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) { if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 10 * EPS_SMALL && bValidInters) { if ( dLen1 > 2 * EPS_SMALL) {
Point5ax Pt5ax ; Point5ax Pt5ax ;
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ; Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
Pt5ax.vtDirV = vPt5ax[j].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ; Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -110,18 +99,11 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
} }
else else
vPt5ax[j].nFlag = P5AX_CVEX ; vPt5ax[j].nFlag = P5AX_CVEX ;
if ( dLen2 > 10 * EPS_SMALL) { if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( bValidInters) Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
else {
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
Pt5ax.ptP = vPt5ax[j].ptP + vtNewLine * 2 * EPS_SMALL ;
}
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ; Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
Pt5ax.vtDirV = vPt5ax[i].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ; Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -136,8 +118,6 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ; Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ; Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ;
Pt5ax.vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; Pt5ax.vtDirU.Normalize() ;
Pt5ax.vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; Pt5ax.vtDirV.Normalize() ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ; Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -146,21 +126,6 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
} }
} }
} }
else {
// guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth)
Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ;
vtDirNext.Normalize() ;
if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) {
// se concavo senza spigolo netto segnalo zona concava smooth
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
}
}
}
// riscorro tutto il vettore per vedere se ho creato delle zone concave smooth frammentate (separate solo da un tratto non classificato concavo), che quindi uniformo
for ( int i = 1 ; i < ssize( vPt5ax) - 1 ; ++ i) {
if ( vPt5ax[i].nFlag != P5AX_SMOOTH_CONC && vPt5ax[i-1].nFlag == P5AX_SMOOTH_CONC && vPt5ax[i+1].nFlag == P5AX_SMOOTH_CONC)
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
} }
return true ; return true ;
} }
@@ -267,56 +232,24 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
return true ; return true ;
} }
//----------------------------------------------------------------------------
static const SurfTriMesh*
MyGetAuxSurf( const ISurf* pSrf)
{
if ( pSrf == nullptr)
return nullptr ;
switch ( pSrf->GetType()) {
case SRF_TRIMESH :
return GetBasicSurfTriMesh( pSrf) ;
case SRF_FLATRGN :
return GetBasicSurfFlatRegion( pSrf)->GetAuxSurf() ;
case SRF_BEZIER :
return GetBasicSurfBezier( pSrf)->GetAuxSurf() ;
default :
return nullptr ;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax) ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
{ {
// punto sulle superfici a minima distanza // punto sulle supefici a minima distanza
int nSurfMin = -1 ; int nSurfMin = -1 ;
int nTriaMin = -1 ; int nTriaMin ;
double dUMin = -1, dVMin = -1 ;
Point3d ptMin ; Point3d ptMin ;
double dMinDist = NAN ; double dMinDist ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
// punto sulla superficie a minima distanza // punto sulla superficie a minima distanza
int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ; DistPointSurfTm dPS( ptP, *vpStm[i]) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) { double dDist ;
DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ; if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
double dDist ; nSurfMin = i ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { dPS.GetMinDistPoint( ptMin) ;
nSurfMin = i ; dPS.GetMinDistTriaIndex ( nTriaMin) ;
dPS.GetMinDistPoint( ptMin) ; dMinDist = dDist ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
}
}
else if ( nSrfType == SRF_BEZIER) {
DistPointSurfBz dPS( ptP, *GetBasicSurfBezier( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetParamsAtMinDistPoint( dUMin, dVMin) ;
dMinDist = dDist ;
}
} }
} }
@@ -324,44 +257,19 @@ ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar
if ( nSurfMin >= 0) { if ( nSurfMin >= 0) {
// assegno il punto // assegno il punto
Point3d ptInt = ptMin ; Point3d ptInt = ptMin ;
// calcolo gli altri dati // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ; Triangle3dEx trTria ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) { if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria))
// recupero superficie trimesh return false ;
const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ; Vector3d vtN ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) if ( ! CalcNormal( ptMin, trTria, vtN))
Triangle3dEx trTria ; vtN = trTria.GetN() ;
if ( ! pSurfTm->GetTriangle( nTriaMin, trTria)) // assegno valori al punto 5assi
return false ; Pt5ax.ptP = ptInt ;
Vector3d vtN ; Pt5ax.vtDir1 = vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN)) Pt5ax.vtDir2 = vtN ;
vtN = trTria.GetN() ; Pt5ax.dPar = dPar ;
// assegno valori al punto 5assi Pt5ax.nFlag = P5AX_STD ;
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
else if ( nSrfType == SRF_BEZIER) {
Point3d ptSB ;
Vector3d vtN, vtDerU, vtDerV ;
if ( ! GetBasicSurfBezier( vpSurf[nSurfMin])->GetPointNrmD1D2( dUMin, dVMin, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS,
ptSB, vtN, &vtDerU, &vtDerV))
return false ;
vtDerU.Normalize() ;
vtDerV.Normalize() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = vtDerU ;
Pt5ax.vtDirV = vtDerV ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
// ritorno con successo // ritorno con successo
return true ; return true ;
} }
@@ -374,6 +282,31 @@ bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// controllo le tolleranze // controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ; dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
@@ -398,17 +331,15 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
} }
// se richiesto, inserimento punti intermedi in presenza di spigoli // se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) { if ( bSharpEdges)
if ( ! AddPointsOnCorners( vPt5ax)) AddPointsOnCorners( vPt5ax) ;
return false ;
}
// rimozione punti in eccesso rispetto alle tolleranze // rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
@@ -423,7 +354,7 @@ typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM, ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
double dPar, bool bFromVsTo, Point5ax& Pt5ax) double dPar, Point5ax& Pt5ax)
{ {
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta) // intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
Point3d ptL = GetToLoc( ptP, frRefLine) ; Point3d ptL = GetToLoc( ptP, frRefLine) ;
@@ -432,48 +363,23 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) { for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) { if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
// se dalla direzione // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( bFromVsTo) { int nI = ssize( vIntRes) - 1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
int nI = ssize( vIntRes) - 1 ; --nI ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // se trovata
--nI ; if ( nI >= 0) {
// se trovata if ( nInd < 0) {
if ( nI >= 0) { IntRes = vIntRes[nI] ;
if ( nInd < 0) { nInd = i ;
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} else {
// altrimenti verso la direzione double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
else { double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
// cerco la prima intersezione valida a partire dalla prima (è la più alta) if ( dU > dUref) {
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ; IntRes = vIntRes[nI] ;
nInd = i ; nInd = i ;
} }
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} }
} }
@@ -497,8 +403,6 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = frRefLine.VersZ() ; Pt5ax.vtDir2 = frRefLine.VersZ() ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -510,7 +414,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -576,7 +480,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -598,8 +502,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, bool bFromVsTo, ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
Point5ax& Pt5ax)
{ {
// punto di riferimento // punto di riferimento
Point3d ptMin = gpRef.GetPoint() ; Point3d ptMin = gpRef.GetPoint() ;
@@ -614,48 +517,23 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dal punto // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( bFromVsTo) { int nI = ssize( vIntRes) - 1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
int nI = ssize( vIntRes) - 1 ; --nI ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // se trovata
--nI ; if ( nI >= 0) {
// se trovata if ( nInd < 0) {
if ( nI >= 0) { IntRes = vIntRes[nI] ;
if ( nInd < 0) { nInd = i ;
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} else {
// altrimenti verso il punto double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
else { double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
// cerco la prima intersezione valida a partire dalla prima (è la più alta) if ( dU > dUref) {
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ; IntRes = vIntRes[nI] ;
nInd = i ; nInd = i ;
} }
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} }
} }
@@ -679,8 +557,6 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ; Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -693,7 +569,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -744,7 +620,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -762,8 +638,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, bool bFromVsTo, ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
Point5ax& Pt5ax)
{ {
// punto a minima distanza // punto a minima distanza
DistPointCurve dPC( ptP, crRef) ; DistPointCurve dPC( ptP, crRef) ;
@@ -781,48 +656,23 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dalla curva // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( bFromVsTo) { int nI = ssize( vIntRes) - 1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
int nI = ssize( vIntRes) - 1 ; --nI ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // se trovata
--nI ; if ( nI >= 0) {
// se trovata if ( nInd < 0) {
if ( nI >= 0) { IntRes = vIntRes[nI] ;
if ( nInd < 0) { nInd = i ;
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} else {
// altrimenti verso la curva double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
else { double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
// cerco la prima intersezione valida a partire dalla prima (è la più alta) if ( dU > dUref) {
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ; IntRes = vIntRes[nI] ;
nInd = i ; nInd = i ;
} }
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} }
} }
@@ -845,9 +695,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
// assegno valori al punto 5assi // assegno valori al punto 5assi
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ; Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -861,7 +709,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// Sistemazioni per tipo di superficie // Sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -912,7 +760,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -930,8 +778,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, bool bFromVsTo, ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
Point5ax& Pt5ax)
{ {
// punto sulla superficie guida a minima distanza // punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ; DistPointSurfTm dPS( ptP, stmRef) ;
@@ -958,48 +805,23 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ; ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dalla superficie // cerco la prima intersezione valida a partire dall'ultima (è la più alta)
if ( bFromVsTo) { int nI = ssize( vIntRes) - 1 ;
// cerco la prima intersezione valida a partire dall'ultima (è la più alta) while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
int nI = ssize( vIntRes) - 1 ; --nI ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) // se trovata
--nI ; if ( nI >= 0) {
// se trovata if ( nInd < 0) {
if ( nI >= 0) { IntRes = vIntRes[nI] ;
if ( nInd < 0) { nInd = i ;
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} else {
// altrimenti verso la superficie double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
else { double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
// cerco la prima intersezione valida a partire dalla prima (è la più alta) if ( dU > dUref) {
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ; IntRes = vIntRes[nI] ;
nInd = i ; nInd = i ;
} }
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
} }
} }
} }
@@ -1030,8 +852,6 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
Pt5ax.ptP = ptInt ; Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ; Pt5ax.vtDir2 = vtN2 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ; Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ; Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo // ritorno con successo
@@ -1044,7 +864,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef, ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax) double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{ {
// sistemazioni per tipo di superficie // sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ; CISRFTMPVECTOR vpSurfTm ;
@@ -1116,7 +936,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
while ( bFound) { while ( bFound) {
// se trovo proiezione, la salvo // se trovo proiezione, la salvo
Point5ax Pt5ax ; Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, Pt5ax)) if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ; vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo // passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ; bFound = PL.GetNextUPoint( &dPar, &ptP) ;
+3 -10
View File
@@ -92,18 +92,11 @@ RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dPa
Vector3d vtCurrR = frAct.VersX() ; Vector3d vtCurrR = frAct.VersX() ;
Vector3d vtCurrT = frAct.VersZ() ; Vector3d vtCurrT = frAct.VersZ() ;
// punto i-esimo sulla curva e suo vettore tangente medio // punto i-esimo sulla curva e suo vettore tangente
Point3d ptNextM, ptNextP ;
Vector3d vtNextM, vtNextP ;
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNextM, &vtNextM) ||
! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_PLUS, ptNextP, &vtNextP) ||
! vtNextM.Normalize() || ! vtNextP.Normalize())
return false ;
Point3d ptNext ; Point3d ptNext ;
Vector3d vtNextT ; Vector3d vtNextT ;
ptNext = Media( ptNextM, ptNextP) ; if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) ||
vtNextT = Media( vtNextM, vtNextP) ; ! vtNextT.Normalize())
if ( ! vtNextT.Normalize())
return false ; return false ;
// controllo per casi degeneri // controllo per casi degeneri
+3 -38
View File
@@ -735,7 +735,8 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfBezier* ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen) GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv,
const INTVECTOR& vShown, const INTINTVECTOR& vNewOrEdited, double dLinTol)
{ {
// verifica parametri // verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr) if ( pCurve1 == nullptr || pCurve2 == nullptr)
@@ -762,43 +763,7 @@ GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVEC
// creo e setto la superficie trimesh // creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines)) if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv, vNewCrv, vShown, vNewOrEdited))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
return nullptr ; return nullptr ;
// restituisco la superficie // restituisco la superficie
+549 -1128
View File
File diff suppressed because it is too large Load Diff
+7 -14
View File
@@ -76,18 +76,11 @@ FromString( const string& sVal, Frame3d& frFrame)
bool bool
FromString( const string& sVal, Color& cCol) FromString( const string& sVal, Color& cCol)
{ {
// dovrebbero essere 4 parametri : Red, Green, Blue, Alpha // devono essere 4 parametri : Red, Green, Blue, Alpha
int vnRGBA[4] ; int vnVal[4] ;
if ( FromString( sVal, vnRGBA)) { if ( ! FromString( sVal, vnVal))
cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ; return false ;
return true ; // assegno il colore
} cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
// riprovo con 3 parametri : Red, Green, Blue return true ;
int vnRGB[3] ;
if ( FromString( sVal, vnRGB)) {
cCol.Set( vnRGB[0], vnRGB[1], vnRGB[2]) ;
return true ;
}
// altrimenti errore
return false ;
} }
+68 -310
View File
@@ -24,14 +24,6 @@
#include "/EgtDev/Include/EGkSurfAux.h" #include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#define SAVEMKUNIF_CRVS 0
#if SAVEMKUNIF_CRVS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
@@ -538,25 +530,6 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
return Release( pSrfBz) ; return Release( pSrfBz) ;
} }
//----------------------------------------------------------------------------
ICurveComposite*
GetRectangleCurve( const Point3d& ptStart, double dWidth, double dHeight)
{
PolyLine PL ;
PL.AddUPoint( 0, ptStart) ;
PL.AddUPoint( 1, Point3d( ptStart.x + dWidth, ptStart.y)) ;
PL.AddUPoint( 2, Point3d( ptStart.x + dWidth, ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 3, Point3d( ptStart.x , ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 4, ptStart) ;
// creo la curva e la inserisco nel GDB
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
bool bOk = true ;
bOk = bOk && ! IsNull( pCrvCompo) ;
// inserisco i segmenti che uniscono i punti
bOk = bOk && pCrvCompo->FromPolyLine( PL) ;
return Release( pCrvCompo) ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0, MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
@@ -566,33 +539,36 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
bool bRescaledU = false ; bool bRescaledU = false ;
bool bRescaledV = false ; bool bRescaledV = false ;
int nSpanU = 1, nSpanV = 1 ; int nSpanU = 1, nSpanV = 1 ;
ICRVCOMPOPOVECTOR vUniformedCurves ; PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
BOOLVECTOR vbUniform(2) ;
fill( vbUniform.begin(), vbUniform.end(), true) ;
DBLMATRIX mKnots(2) ;
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) { for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
// vettore dei nodi // vettore dei nodi
DBLVECTOR& vU = mKnots[nDir] ; DBLVECTOR vU ;
int nExtraKnots = 0 ; int nExtraKnots = 0 ;
// controllo in U // controllo in U
if ( nDir == 0) { if ( nDir == 0) {
for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) { if ( nDegU > 1) {
nExtraKnots = nDegU - 1 ;
}
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
double dKnot = vU0[i] * SBZ_TREG_COEFF ; double dKnot = vU0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente // lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL) if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
vU.push_back( dKnot) ; vU.push_back( dKnot) ;
} }
nSpanU = ssize( vU) - 1 ; nSpanU = (int)vU.size() - 1 ;
} }
// controllo in V // controllo in V
else if ( nDir == 1 ) { else if ( nDir == 1 ) {
for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) { if ( nDegV > 1) {
nExtraKnots = nDegV - 1 ;
}
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
double dKnot = vV0[i] * SBZ_TREG_COEFF ; double dKnot = vV0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente // lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL) if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
vU.push_back( dKnot) ; vU.push_back( dKnot) ;
} }
nSpanV = ssize( vU) - 1 ; nSpanV = (int)vU.size() - 1 ;
} }
// controllo se il vettore dei nodi è uniforme // controllo se il vettore dei nodi è uniforme
@@ -605,268 +581,76 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
if ( b < (int)vU.size()) if ( b < (int)vU.size())
d1 = abs( vU[b] - vU[a]) ; d1 = abs( vU[b] - vU[a]) ;
} }
if ( b != (int)vU.size()) if ( b != (int)vU.size()) {
vbUniform[nDir] = false ;
}
// vettore delle curve di loop della regione di trim
ICRVCOMPOPOVECTOR vLoop ;
if ( ! vbUniform[0] || ! vbUniform[1]) {
for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pSfr->GetLoopCount( c); ++l)
vLoop.emplace_back( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vLoop); ++i){
vGeo.push_back(vLoop[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_loops.nge") ;
//debug
#endif
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
DBLVECTOR& vU = mKnots[nDir] ;
if ( ! vbUniform[nDir]) {
nDir == 0 ? bRescaledU = true : bRescaledV = true ; nDir == 0 ? bRescaledU = true : bRescaledV = true ;
// creo il vettore delle curve all'interno di una striscia pRescaledSfr.Set( CreateSurfFlatRegion()) ;
ICRVCOMPOPOVECTOR vCrvStrip ; if ( IsNull( pRescaledSfr))
for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) { return false ;
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
if ( IsNull( pSfr_copy))
return false ;
double dLenStrip = abs( vU[p+1] - vU[p]) ; double dLenStrip = abs( vU[p+1] - vU[p]) ;
if ( dLenStrip < EPS_SMALL) if ( dLenStrip < EPS_SMALL)
continue ; continue ;
// creo la maschera per tagliare la superficie originale e ottenere una striscia // creo la maschera per tagliare la superficie originale e ottenere una striscia
PtrOwner<ICurveComposite> pTrimMask ; PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale // ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
Vector3d vtTrim ;
if ( nDir == 0) { if ( nDir == 0) {
Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ; pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ; vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
} }
else{ else{
Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ; pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ; vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
} }
pSfrTrim->Translate( vtTrim) ;
// qui potrei decidere di eliminare tutti i tratti dei loop paralleli alla direzione del parametro che sto analizzando ( e di valore coincidente a quello di un nodo) if ( ! pSfr_copy->Intersect( *pSfrTrim))
return false ;
for ( int l = 0 ; l < ssize( vLoop); ++l) {
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
vGeo.push_back(pTrimMask->Clone()) ;
vGeo.push_back(vLoop[l]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
//debug
#endif
IntersCurveCurve icc( *vLoop[l], *pTrimMask) ;
int nInters = icc.GetIntersCount() ;
ICCIVECTOR vICCI ;
for ( int i = 0 ; i < nInters ; ++i) {
IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
vICCI.push_back( std::move( icci)) ;
}
CRVCVECTOR vCrvClass, vMaskClass ;
icc.GetCurveClassification( 0, EPS_SMALL, vCrvClass) ;
icc.GetCurveClassification( 1, EPS_SMALL, vMaskClass) ;
// se dei pezzi di trim risultano esterni allo spazio parametrico tengo il bordo della maschera di trim
double dLastParam1 = 0 ;
double dStartA = 0, dEndA = 0 ; vLoop[l]->GetDomain( dStartA, dEndA) ;
double dEndB = 4 ;
for ( int i = 0 ; i < ssize( vCrvClass); ++i) {
if ( vCrvClass[i].nClass == CRVC_IN || vCrvClass[i].nClass == CRVC_ON_P) {
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs( vICCI[j].IciA[k].dU - vCrvClass[i].dParE) < EPS_PARAM) {
dLastParam1 = vICCI[j].IciB[k].dU ;
break ;
}
}
}
else if ( vCrvClass[i].nClass == CRVC_OUT && ( p == 0 || p == ssize(vU) - 2)){
double dMin, dMax ;
if ( p == 0) {
dMin = nDir == 0 ? 3 : 0 ;
dMax = nDir == 0 ? 4 : 1 ;
}
else {
dMin = nDir == 0 ? 1 : 2 ;
dMax = nDir == 0 ? 2 : 3 ;
}
// aggiungo la parte di curva di edge al posto della parte di curva che esce dal parametrico
// se non ho ancora aggiunto un tratto parto dal primo punto di intersezione
if ( ssize( vCrvStrip) == 0) {
double dPar0 = vCrvClass[i].dParS ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs(vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM ||
( abs( dEndA - vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM)) {
if ( abs( dEndB - vICCI[j].IciB[k].dU) < EPS_PARAM)
dLastParam1 = 0 ;
else
dLastParam1 = vICCI[j].IciB[k].dU ;
break ;
}
}
}
int c = 0 ;
while ( c < ssize( vMaskClass) - 1 && abs( vMaskClass[c].dParS - dLastParam1) > EPS_PARAM)
++c ;
if ( vMaskClass[c].nClass == CRVC_IN && vMaskClass[c].dParS < dMax && vMaskClass[c].dParS >= dMin) {
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
dLastParam1 = vMaskClass[c].dParE ;
// se sono alla fine curva verifico se devo aggiungere anche un pezzo di inizio
if ( dLastParam1 == dEndB && vMaskClass[0].nClass == CRVC_IN) {
c = 0 ;
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
dLastParam1 = vMaskClass[c].dParE ;
}
}
}
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// riscalo le curve nella striscia
if ( ! vCrvStrip.empty()) {
double dCoeffX = 1, dCoeffY = 1 ;
// aggiungo la nuova striscia solo se è valida
if ( pSfr_copy->IsValid() ) {
if ( nDir == 0) if ( nDir == 0)
dCoeffX = SBZ_TREG_COEFF / dLenStrip ; pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else else
dCoeffY = SBZ_TREG_COEFF / dLenStrip ; pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
if( ! IsNull( vCrvStrip[i])) // prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
else Point3d pt ;
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
if ( nDir == 0)
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
Vector3d vtJoin ;
if ( nDir == 0)
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
else
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
pSfr_copy->Translate( vtJoin) ;
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
if ( bRetry)
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
if ( pRescaledSfr->IsValid()) {
if ( ! pRescaledSfr->Add( *pSfr_copy))
return false ; return false ;
} }
else
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo (nDir == 0) pRescaledSfr.Set( pSfr_copy) ;
// oppure sul bordo superiore ( nDir == 1)
Point3d pt ;
Vector3d vtJoin ;
if ( nDir == 0) {
pt.Set( abs( vU[p] - vU.front()), 0, 0) ;
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
}
else {
pt.Set( 0, abs(vU[p] - vU.front()), 0) ;
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
}
for( int i = 0 ; i < ssize( vCrvStrip); ++i)
vCrvStrip[i]->Translate( vtJoin) ;
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// faccio la chain con le curve delle striscie precedenti
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
ChainCurves chainCrv ;
double dChainTol = 5 * EPS_SMALL ;
chainCrv.Init( false, dChainTol, max(ssize( vUniformedCurves), ssize(vCrvStrip))) ;
for ( int c = 0 ; c < ssize( vUniformedCurves) ; ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vUniformedCurves[c]->GetStartPoint( ptStart) ;
vUniformedCurves[c]->GetEndPoint( ptEnd) ;
vUniformedCurves[c]->GetStartDir( vtStart) ;
vUniformedCurves[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
for ( int c = 0 ; c < ssize( vCrvStrip); ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vCrvStrip[c]->GetStartPoint( ptStart) ;
vCrvStrip[c]->GetEndPoint( ptEnd) ;
vCrvStrip[c]->GetStartDir( vtStart) ;
vCrvStrip[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + ssize( vUniformedCurves) + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
INTVECTOR vIds ;
ICRVCOMPOPOVECTOR vNewCrv ;
int nCrvPrec = ssize( vUniformedCurves) ;
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) {
// se ho una solo curva piccola allora la salto
if ( ssize(vIds) == 1) {
double dLen = 0 ;
int nId = vIds[0] - 1 ;
bool bSkip = false ;
if ( nId < nCrvPrec)
bSkip = vUniformedCurves[nId]->GetLength( dLen) && dLen < dChainTol ;
else
bSkip = vCrvStrip[nId - ssize(vUniformedCurves)]->GetLength(dLen) && dLen < dChainTol ;
if ( bSkip)
continue ;
}
vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
for ( int nId : vIds) {
nId -= 1 ;
if ( nId < nCrvPrec)
vNewCrv.back()->AddCurve( Release( vUniformedCurves[nId]), true, dChainTol) ;
else
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vGeo.clear() ;
for( int i = 0 ; i < ssize( vNewCrv); ++i){
vGeo.push_back(vNewCrv[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\trim_crv_unif_AFTERchain.nge") ;
//debug
#endif
// aggiorno le curve
vUniformedCurves.clear() ;
vUniformedCurves.swap( vNewCrv) ;
}
} }
vCrvStrip.clear() ;
} }
if ( nDir == 0) { if ( nDir == 0) {
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ; dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
if( ! vbUniform[1]) { if ( pRescaledSfr->IsValid()) {
vLoop.swap( vUniformedCurves) ; if ( bRetry)
vUniformedCurves.clear() ; pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
} }
} }
else else
@@ -874,38 +658,12 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
} }
} }
if ( ! vUniformedCurves.empty()) { if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
#if SAVEMKUNIF_CRVS if ( bRetry)
//debug pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
vector<IGeoObj*> vGeo ; delete pSfr ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){ pSfr = Release( pRescaledSfr) ;
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
if ( ! vUniformedCurves[i]->IsClosed() && ! vUniformedCurves[i]->Close())
return false ;
}
// creo una regione dalle curve riscalate
SurfFlatRegionByContours sfrRescaled ;
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i)
sfrRescaled.AddCurve( Release( vUniformedCurves[i])) ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( sfrRescaled.GetSurf()) ;
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
}
else
return false ;
} }
else if( ! vbUniform[0] || ! vbUniform[1])
return false ;
if ( ! bRescaledU && ! bRescaledV) if ( ! bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ; pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
+340 -1667
View File
File diff suppressed because it is too large Load Diff
+7 -10
View File
@@ -116,9 +116,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ; const SurfTriMesh* GetAuxSurf( void) const override ;
const SurfTriMesh* GetAuxSurfRefined( void) const override ; const SurfTriMesh* GetAuxSurfRefined( void) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 10 * EPS_SMALL, bool bUpdateEdges = false) const override ; SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ;
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione. // funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined = false) const override ; bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ; bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier // funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ;
@@ -143,19 +143,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool IsPlanar( void) const override ; bool IsPlanar( void) const override ;
bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByFlatContour( const PolyLine& PL) override ;
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) override ; bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ; bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ; bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ; bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
PNTVECTOR GetAllControlPoints( void) const override ; PNTVECTOR GetAllControlPoints( void) const ;
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ; bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ; bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv, const INTVECTOR& vShown ,const INTINTVECTOR& vNewOrEdited) ;
bool RemoveCollapsedSpans( void) override ; bool RemoveCollapsedSpans() override ;
bool SwapParameters( void) ; bool SwapParameters() ;
bool LimitSurfToTrimmedRegion( void) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
+35 -188
View File
@@ -28,13 +28,6 @@
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#define SAVECLASSCRV 0
#define SAVEADJUSTCRV 0
#if SAVECLASSCRV || SAVEADJUSTCRV
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -114,20 +107,8 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
pMyCrv->SetThickness( 0) ; pMyCrv->SetThickness( 0) ;
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano) // rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
ICURVEPLIST CrvLst ; ICURVEPLIST CrvLst ;
#if SAVEADJUSTCRV
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
#endif
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true)) if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
return false ; return false ;
#if SAVEADJUSTCRV
for ( auto& pSingCrv : CrvLst)
vGeo.push_back( pSingCrv->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\after_adjust.nge") ;
#endif
// aggiungo le singole curve // aggiungo le singole curve
int nExtAdded = 0 ; int nExtAdded = 0 ;
bool bOk = true ; bool bOk = true ;
@@ -188,18 +169,14 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
Vector3d vtExtr ; Vector3d vtExtr ;
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
pMyCrv->SetExtrusion( Z_AX) ; pMyCrv->SetExtrusion( Z_AX) ;
// verifico non abbia auto-intersezioni che si attraversano o si sovrappongano
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// verifico che sia esterna alle curve esterne degli altri chunk // verifico che sia esterna alle curve esterne degli altri chunk
bool bOk = true ; bool bOk = true ;
CRVCVECTOR ccClass ; CRVCVECTOR ccClass ;
for ( auto i : m_vExtInd) { for ( auto i : m_vExtInd) {
#if SAVEADJUSTCRV
vGeo.clear() ;
vGeo.push_back( pMyCrv->Clone()) ;
vGeo.push_back( m_vpLoop[i]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\during_add_simpleExt.nge") ;
#endif
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ; IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) || ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
@@ -239,9 +216,14 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
bool bool
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv) SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
{ {
m_vpLoop.push_back( pCrv) ; try {
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ; m_vpLoop.push_back( pCrv) ;
m_nStatus = OK ; m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
m_nStatus = OK ;
}
catch (...) {
return false ;
}
return true ; return true ;
} }
@@ -322,7 +304,10 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0) // sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0)) if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
pMyCrv->Invert() ; pMyCrv->Invert() ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// ricerca del chunk in cui andrebbe inserito // ricerca del chunk in cui andrebbe inserito
int nChunk = -1 ; int nChunk = -1 ;
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) { for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
@@ -369,18 +354,23 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
bool bool
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk) SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
{ {
//se da aggiungere all'ultimo chunk try {
if ( nChunk == -1) // se da aggiungere all'ultimo chunk
m_vpLoop.push_back( pCrv) ; if ( nChunk == -1)
//altrimenti aggiungo al chunck indicato m_vpLoop.push_back( pCrv) ;
else { // altrimenti aggiungo al chunck indicato
int nLoopCnt = GetLoopCount( nChunk) ; else {
if ( nLoopCnt == 0) int nLoopCnt = GetLoopCount( nChunk) ;
return false ; if ( nLoopCnt == 0)
int nOffset = m_vExtInd[nChunk] + nLoopCnt ; return false ;
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ; int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i) m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
++ m_vExtInd[i] ; for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
++ m_vExtInd[i] ;
}
}
catch (...) {
return false ;
} }
return true ; return true ;
@@ -1384,15 +1374,6 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) { for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ; const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
// intersezione // intersezione
#if SAVECLASSCRV
//debug
vector<IGeoObj*> vGeo ;
vGeo.push_back( Crv.Clone()) ;
vGeo.push_back( pLoop->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\crv_and_loop.nge") ;
#endif
IntersCurveCurve ccInt( Crv, *pLoop) ; IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione // classificazione
CRVCVECTOR ccPart ; CRVCVECTOR ccPart ;
@@ -1556,7 +1537,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda // classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ; IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
int nClass = ccInt.GetRegionCurveClassification() ; int nClass = ccInt.GetRegionCurveClassification() ;
switch ( nClass) { switch ( nClass){
default : // CCREGC_NULL default : // CCREGC_NULL
return REGC_NULL ; return REGC_NULL ;
case CCREGC_IN1 : case CCREGC_IN1 :
@@ -1569,141 +1550,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
return REGC_OUT ; return REGC_OUT ;
case CCREGC_INTERS : case CCREGC_INTERS :
return REGC_INTERS ; return REGC_INTERS ;
} }
}
//----------------------------------------------------------------------------
bool
SurfFlatRegion::CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const
{
bInterference = false ;
// verifico lo stato e il numero di chunk
if ( m_nStatus != OK || m_vpLoop.empty() || nChunk >= GetChunkCount())
return false ;
// recupero rappresentazione base dell'altra regione
const SurfFlatRegion& Reg2 = *GetBasicSurfFlatRegion( &Other) ;
// verifico lo stato e il numero di chunk dell'altra regione
if ( Reg2.m_nStatus != OK || Reg2.m_vpLoop.empty() || nOthChunk >= Reg2.GetChunkCount())
return false ;
// verifico che le due regioni giacciano in piani paralleli
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
return false ;
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
int nClass = GetChunkSimpleClassification( nChunk, Other, nOthChunk) ;
if ( nClass == REGC_NULL)
return false ;
// se le regioni non hanno isole, allora ho già identificato se i Chunks fanno interferenza
int nLoopCnt = GetLoopCount( nChunk) ;
int nOtherLoopCnt = Other.GetLoopCount( nOthChunk) ;
if ( nLoopCnt == 1 && nOtherLoopCnt == 1) {
bInterference = ( nClass != REGC_OUT) ;
return true ;
}
// --- a prescindere dalle isole presenti nei 2 Chunks in esame :
// se i due loop esterni si intersecano tra loro o sono gli stessi, allora fanno per forza interferenza
if ( nClass == REGC_INTERS || nClass == CCREGC_SAME) {
bInterference = true ;
return true ;
}
// se invece sono esterni tra loro, allora non c'è interferenza
else if ( nClass == REGC_OUT)
return true ;
// --- Analisi del loop interni :
// se la curva esterna corrente è interna alla curva esterna dell'altro chunk
else if ( nClass == REGC_IN1) {
// se l'altro chunk non ha isole, c'è interferenza (a prescinere da numero di loop interni del primo chunk)
if ( nOtherLoopCnt == 1) {
bInterference = true ;
return true ;
}
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
// per ogni loop interno (isole)
for ( int i = 1 ; i < nOtherLoopCnt ; ++ i) {
const ICurve* pCrv2Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( m_frF, Reg2.m_frF))
pCrv2Loc = Reg2.GetMyLoop( nOthChunk, i) ;
else {
pCopyCrv.Set( Reg2.GetMyLoop( nOthChunk, i)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( Reg2.m_frF, m_frF) ;
pCrv2Loc = pCopyCrv ;
}
// classifico il loop esterno del chunk della prima regione rispetto all'interno corrente del chunk della seconda
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
int nInternalClass = ccInt.GetRegionCurveClassification() ;
// se le curve non sono classificabili, errore
if ( nInternalClass == REGC_NULL)
return false ;
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
else if ( nInternalClass == REGC_IN1)
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
else if ( nInternalClass == REGC_OUT)
return true ;
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
bInterference = true ;
return true ;
}
// negli altri casi ho un orientamento errato dei loop o delle regioni
else
return false ;
}
}
// se la curva esterna dell'altro chunk è interna alla curva esterna corrente
else if ( nClass == REGC_IN2) {
// se l'altro chunk non ha isole, c'è interferenza
if ( nLoopCnt == 1) {
bInterference = true ;
return true ;
}
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv2Loc = Reg2.GetMyLoop( nChunk, 0) ;
// per ogni loop interno (isole)
for ( int i = 1 ; i < nLoopCnt ; ++ i) {
const ICurve* pCrv1Loc = nullptr ;
PtrOwner<ICurve> pCopyCrv ;
if ( AreSameFrame( Reg2.m_frF, m_frF))
pCrv1Loc = GetMyLoop( nOthChunk, i) ;
else {
pCopyCrv.Set( GetMyLoop( nOthChunk, i)->Clone()) ;
if ( IsNull( pCopyCrv))
return false ;
pCopyCrv->LocToLoc( m_frF, Reg2.m_frF) ;
pCrv1Loc = pCopyCrv ;
}
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
IntersCurveCurve ccInt( *pCrv2Loc, *pCrv1Loc) ;
int nInternalClass = ccInt.GetRegionCurveClassification() ;
// se le curve non sono classificabili, errore
if ( nInternalClass == REGC_NULL)
return false ;
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
else if ( nInternalClass == REGC_IN1)
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
else if ( nInternalClass == REGC_OUT)
return true ;
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
bInterference = true ;
return true ;
}
// negli altri casi ho un orientamento errato dei loop o delle regioni
else
return false ;
}
}
// in questo la curva di bordo è interna ad ogni isola ma interna anche al loop esterno, quindi esiste interferenza
bInterference = true ;
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
-2
View File
@@ -107,7 +107,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
bool GetChunkArea( int nChunk, double& dArea) const override ; bool GetChunkArea( int nChunk, double& dArea) const override ;
bool GetChunkPerimeter( int nChunk, double& dLen) const override ; bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
bool CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const override ; // compare alls
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ; bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
int GetLoopCount( int nChunk) const override ; int GetLoopCount( int nChunk) const override ;
int GetLoopCurveCount( int nChunk, int nLoop) const override ; int GetLoopCurveCount( int nChunk, int nLoop) const override ;
@@ -140,7 +139,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ; SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
friend class MyCAvSimpleSurfFrMove ; friend class MyCAvSimpleSurfFrMove ;
friend class MyCAvSurfFrMove ;
private : private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
-13
View File
@@ -20,12 +20,6 @@
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#define SAVELOOPS 0
#if SAVELOOPS
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -178,13 +172,6 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
pSfr.Set( new( nothrow) SurfFlatRegion) ; pSfr.Set( new( nothrow) SurfFlatRegion) ;
else else
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ; pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
#if SAVELOOPS
for (int i = 0 ; i < ssize( vpLoop) ; ++i)
vGeo.push_back( vpLoop[i]) ;
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\NewLoops.nge") ;
#endif
if ( IsNull( pSfr)) { if ( IsNull( pSfr)) {
MyTestAndDelete( vpCurve) ; MyTestAndDelete( vpCurve) ;
MyTestAndDelete( vpLoop) ; MyTestAndDelete( vpLoop) ;
+13 -66
View File
@@ -1188,10 +1188,8 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ; pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr)) if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ; pSfr.Set( pSfrTria) ;
else { else
if ( ! pSfr->Add( *pSfrTria)) pSfr->Add( *pSfrTria) ;
return false ;
}
} }
} }
// passo al successivo // passo al successivo
@@ -1203,18 +1201,14 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
return false ; return false ;
// Effettuo contro-offset // Effettuo contro-offset
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND)) pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
return false ;
// Recupero i contorni della regione // Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ; PolyLine PL ;
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) { if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.clear() ; vPL.emplace_back( PL) ;
return false ;
}
vPL.emplace_back( PL) ;
} }
} }
@@ -1265,10 +1259,8 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ; pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr)) if ( IsNull( pSfr))
pSfr.Set( pSfrTria) ; pSfr.Set( pSfrTria) ;
else { else
if ( ! pSfr->Add( *pSfrTria)) pSfr->Add( *pSfrTria) ;
return false ;
}
} }
} }
} }
@@ -1282,18 +1274,14 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
return true ; return true ;
// Effettuo contro-offset // Effettuo contro-offset
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND)) pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
return false ;
// Recupero i contorni della regione // Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ; PolyLine PL ;
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) { if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.clear() ; vPL.emplace_back( PL) ;
return false ;
}
vPL.emplace_back( PL) ;
} }
} }
@@ -3822,19 +3810,12 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ; BBox3d b3Box ;
PtrOwner<ISurfTriMesh> pStmShell ; PtrOwner<ISurfTriMesh> pStmShell ;
} ; } ;
// vettore di shell con vettori dei propri triangoli (per accelerare nei casi degeneri)
INTMATRIX mShellTria( m_nShells) ;
for ( int i = 0 ; i < ssize( m_vTria) ; ++ i) {
if ( m_vTria[i].nShell < m_nShells)
mShellTria[m_vTria[i].nShell].push_back( i) ;
}
// classificazione delle shell
vector<SHELLINFO> vOuterShells ; vector<SHELLINFO> vOuterShells ;
vector<SHELLINFO> vInnerShells ; vector<SHELLINFO> vInnerShells ;
INTVECTOR vOpenShells ; INTVECTOR vOpenShells ;
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) { for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
// se la shell è chiusa // se la shell è chiusa
if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) { if ( IsShellClosed( nSh)) {
// creo una superficie clonata dalla shell // creo una superficie clonata dalla shell
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ; PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
if ( IsNull( pStmShell) || ! pStmShell->IsValid()) if ( IsNull( pStmShell) || ! pStmShell->IsValid())
@@ -3846,9 +3827,7 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
BBox3d b3Box ; BBox3d b3Box ;
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ; pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
// la inserisco nel vettore opportuno // la inserisco nel vettore opportuno
if ( abs( dVol) < 1 * 1 * EPS_SMALL) if ( dVol > 0)
vOpenShells.push_back( nSh) ;
else if ( dVol > 0)
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ; vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
else else
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ; vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
@@ -4000,7 +3979,6 @@ SurfTriMesh::IsShellClosed( int nShell) const
return false ; return false ;
// ciclo sui triangoli della shell // ciclo sui triangoli della shell
bool bClosed = true ; bool bClosed = true ;
int nTriaCnt = 0 ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// se triangolo non cancellato e della shell // se triangolo non cancellato e della shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) { if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
@@ -4011,12 +3989,10 @@ SurfTriMesh::IsShellClosed( int nShell) const
bClosed = false ; bClosed = false ;
break ; break ;
} }
else
++ nTriaCnt ;
} }
} }
// restituisco il risultato // restituisco il risultato
return ( bClosed && nTriaCnt >= 4) ; return bClosed ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -4439,35 +4415,6 @@ SurfTriMesh::ClonePart( int nPart) const
return Release( pSurfTM) ; return Release( pSurfTM) ;
} }
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const
{
// l'indice della faccia deve essere nei limiti
if ( nFacet < 0 || nFacet >= int( m_vFacet.size()))
return false ;
// mi assicuro che siano calcolate il numero di parti e di shell
int nParts = GetPartCount() ;
int nTria = m_vFacet[nFacet] ;
nShell = m_vTria[nTria].nShell ;
// scopro in quale part è la shell
int nPartTemp = 0 ;
nPart = - 1 ;
while ( nPartTemp < nParts && nPart == - 1) {
for ( int i : m_vPart[nPartTemp].vShell) {
if ( i == nShell) {
nPart = nPartTemp ;
break ;
}
}
++nPartTemp ;
}
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfTriMesh::ResetTFlags( void) SurfTriMesh::ResetTFlags( void)
-1
View File
@@ -347,7 +347,6 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetPartVolume( int nPart, double& dVolume) const override ; bool GetPartVolume( int nPart, double& dVolume) const override ;
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ; bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
SurfTriMesh* ClonePart( int nPart) const override ; SurfTriMesh* ClonePart( int nPart) const override ;
bool GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const override ;
bool SetTFlag( int nId, int nTFlag) override ; bool SetTFlag( int nId, int nTFlag) override ;
bool GetTFlag( int nId, int& nFlag) const override ; bool GetTFlag( int nId, int& nFlag) const override ;
int GetMaxTFlag( void) const override int GetMaxTFlag( void) const override
+10 -10
View File
@@ -36,25 +36,25 @@ class Tool
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ; bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
bool SetToolNum( int nToolNum) bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; } { m_nCurrentNum = nToolNum ; return true ; }
int GetType( void) const int GetType() const
{ return m_nType ; } { return m_nType ; }
int GetToolNum( void) const int GetToolNum() const
{ return m_nCurrentNum ; } { return m_nCurrentNum ; }
double GetHeigth( void) const double GetHeigth() const
{ return m_dHeight ; } { return m_dHeight ; }
double GetTipHeigth( void) const double GetTipHeigth() const
{ return m_dTipHeight ; } { return m_dTipHeight ; }
double GetRadius( void) const double GetRadius() const
{ return m_dRadius ; } { return m_dRadius ; }
double GetTipRadius( void) const double GetTipRadius() const
{ return m_dTipRadius ; } { return m_dTipRadius ; }
double GetCornRadius( void) const double GetCornRadius() const
{ return m_dRCorner ; } { return m_dRCorner ; }
double GetRefRadius( void) const double GetRefRadius() const
{ return m_dRefRadius ; } { return m_dRefRadius ; }
double GetMrtChsWidth( void) const double GetMrtChsWidth() const
{ return m_dMrtChsWidth ; } { return m_dMrtChsWidth ; }
double GetMrtChsThickness( void) const double GetMrtChsThickness() const
{ return m_dMrtChsThickness ; } { return m_dMrtChsThickness ; }
const CurveComposite& GetOutline( void) const const CurveComposite& GetOutline( void) const
{ return ( m_Outline) ; } { return ( m_Outline) ; }
+25 -109
View File
@@ -177,7 +177,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
int nLoop = 0 ; int nLoop = 0 ;
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk // recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ; PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
double dLinTol = 0.005 ; // questo è riferito allo spazio parametrico double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
double dAngTolDeg = 5 ; double dAngTolDeg = 5 ;
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ; PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
@@ -185,8 +185,6 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
// i chunk della falt region sono ancora flat region composte da 1 chunk // i chunk della falt region sono ancora flat region composte da 1 chunk
// rimuovo i difetti dei loop prima di salvarli // rimuovo i difetti dei loop prima di salvarli
PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ; PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ;
if ( IsNull( pLoop))
return false ;
pLoop->MergeCurves( dLinTol, dAngTolDeg) ; pLoop->MergeCurves( dLinTol, dAngTolDeg) ;
pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ; pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ;
@@ -352,6 +350,10 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
} }
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1 // se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
if ( m_mTree.size() == 3 && ! m_mTree.at(-1).IsSplitVert()) { if ( m_mTree.size() == 3 && ! m_mTree.at(-1).IsSplitVert()) {
m_mTree[0].m_nLeft = -1 ;
m_mTree[0].m_nRight = -1 ;
m_mTree[1].m_nLeft = -1 ;
m_mTree[1].m_nRight = -1 ;
m_mTree[0].SetSplitDirVert( true) ; m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ; Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ; m_mTree[1].SetSplitDirVert( true) ;
@@ -459,8 +461,8 @@ Tree::Split( int nId, double dSplitValue)
dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ; dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ;
Point3d ptP00, ptP01, ptP10, ptP11 ; Point3d ptP00, ptP01, ptP10, ptP11 ;
if ( bGoodSplitVert) { if( bGoodSplitVert) {
if ( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) { if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
@@ -472,13 +474,12 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
} }
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) && if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || ( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitVert = false ; bGoodSplitVert = false ;
} }
if ( bGoodSplitHoriz) { if( bGoodSplitHoriz) {
if ( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) { if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ;
@@ -490,9 +491,8 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
} }
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) && if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || ( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitHoriz = false ; bGoodSplitHoriz = false ;
} }
@@ -662,18 +662,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
} }
} }
// calcolo se la parte di superficie nella cella è piatta
PolyLine PL ;
PL.AddUPoint( 0, ptP00) ;
PL.AddUPoint( 1, ptP10) ;
PL.AddUPoint( 2, ptP11) ;
PL.AddUPoint( 3, ptP01) ;
PL.AddUPoint( 4, ptCen) ;
Plane3d plPlane ;
bool bIsFlat = PL.IsFlat( plPlane, dLinTol) ;
// su isoparametriche in U e V // su isoparametriche in U e V
if ( dSagU < dLinTol && dSagV < dLinTol && ! bIsFlat) { if ( dSagU < dLinTol && dSagV < dLinTol) {
// step di verifica in U e in V // step di verifica in U e in V
int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ; int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ;
int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ; int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ;
@@ -734,73 +724,6 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
//{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ; //{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ;
// LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())} // LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())}
} }
else if ( dSagU < dLinTol && dSagV < dLinTol && bIsFlat) {
// se la cella è piatta devo verificare che i bordi siano dei tratti retti, altrimenti potrei commettere un errore di approssimazione
// bordo inferiore e superiore
double dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clU ;
if ( i == 0)
clU.Set( ptP00, ptP10) ;
else if ( i == 1)
clU.Set( ptP01, ptP11) ;
double dV = 0 ;
if ( i == 0)
dV = pcToSplit->GetBottomLeft().y ;
else if ( i == 1)
dV = pcToSplit->GetTopRight().y ;
int nStepU = 4 ;
for ( int j = 1 ; j < nStepU ; ++ j) {
// parametro U
double dCoeffU = double( j) / nStepU ;
double dU = ( 1 - dCoeffU) * pcToSplit->GetBottomLeft().x + dCoeffU * pcToSplit->GetTopRight().x ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clU) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagU = dMaxDist ;
// bordo sinistro e destro
dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clV ;
if ( i == 0)
clV.Set( ptP00, ptP01) ;
else if ( i == 1)
clV.Set( ptP10, ptP11) ;
double dU = 0 ;
if ( i == 0)
dU = pcToSplit->GetBottomLeft().x ;
else if ( i == 1)
dU = pcToSplit->GetTopRight().x ;
int nStepV = 4 ;
for ( int j = 1 ; j < nStepV ; ++ j) {
// parametro in V
double dCoeffV = double( j) / nStepV ;
double dV = ( 1 - dCoeffV) * pcToSplit->GetBottomLeft().y + dCoeffV * pcToSplit->GetTopRight().y ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clV) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagV = dMaxDist ;
}
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
// misura approssimativa della curvatura in una direzione // misura approssimativa della curvatura in una direzione
@@ -811,8 +734,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
bVert = false ; bVert = false ;
else else
bVert = ( dSagV <= dSagU) ; bVert = ( dSagV <= dSagU) ;
bool bFirstTry = true ; pcToSplit->SetSplitDirVert( bVert) ;
retry :
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
double dSideMinVal = 0 ; double dSideMinVal = 0 ;
double dLengMinVal = 0 ; double dLengMinVal = 0 ;
@@ -854,11 +776,6 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
} }
else if ( dSagV > dLinTol || dSagU > dLinTol) { else if ( dSagV > dLinTol || dSagU > dLinTol) {
bSplit = bDimOk ; bSplit = bDimOk ;
if ( ! bSplit && bFirstTry) {
bFirstTry = false ;
bVert = ! bVert ;
goto retry ;
}
//if ( bSplit) //if ( bSplit)
// LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV") // LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV")
} }
@@ -1538,7 +1455,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
++ nPolyInd ; ++ nPolyInd ;
continue ; continue ;
} }
else if ( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
continue ; continue ;
else { else {
// vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
@@ -2063,7 +1980,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
nCells.push_back( nCell) ; nCells.push_back( nCell) ;
nEdge = -2 ; nEdge = -2 ;
} }
if ( ssize( nCells) == 1) if( ssize( nCells) == 1)
return nCells ; return nCells ;
Vector3d vtDir ; Vector3d vtDir ;
@@ -2092,14 +2009,14 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 ) if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 )
ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ;
// altrimenti ruoto a destra // altrimenti ruoto a destra
else if (( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) || else if( ( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) { ( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ; Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
} }
// altrimenti ruoto a sinistra // altrimenti ruoto a sinistra
else /*if (( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) || else /*if( ( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ { ( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ; Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
} }
@@ -2221,7 +2138,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
bool bLoopInside = true ; bool bLoopInside = true ;
Point3d ptCurr ; Point3d ptCurr ;
int nIdPolygon = - 1; int nIdPolygon = - 1;
if ( ! pCell->m_vnPolyId.empty()) if( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ; nIdPolygon = pCell->m_vnPolyId[0] ;
else else
return false ; return false ;
@@ -2261,9 +2178,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
} }
// se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito // se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito
// se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto // se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto
if ( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) { if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
++ nInfiniteLoopCount ; ++ nInfiniteLoopCount ;
if ( nInfiniteLoopCount == 4) { if( nInfiniteLoopCount == 4) {
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell") LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
return false ; return false ;
} }
@@ -2272,7 +2189,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// aggiorno il puntatore alla cella // aggiorno il puntatore alla cella
pCell = &m_mTree[nId] ; pCell = &m_mTree[nId] ;
// recupero l'indice del poligono base associato alla cella // recupero l'indice del poligono base associato alla cella
if ( ! pCell->m_vnPolyId.empty()) if( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ; nIdPolygon = pCell->m_vnPolyId[0] ;
else else
return false ; return false ;
@@ -4108,8 +4025,7 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
Point3d ptTl ( ptBL.x, ptTR.y) ; Point3d ptTl ( ptBL.x, ptTR.y) ;
Point3d ptBr ( ptTR.x, ptBL.y) ; Point3d ptBr ( ptTR.x, ptBL.y) ;
if ( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || if( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
return false ; return false ;
else if ( AreSamePointXYApprox( ptToAssign, ptTR)) else if ( AreSamePointXYApprox( ptToAssign, ptTR))
nEdge = 7 ; nEdge = 7 ;
+16 -25
View File
@@ -23,8 +23,7 @@
#include <utility> #include <utility>
struct PairHashInt64 { struct PairHashInt64 {
size_t size_t operator()(const std::pair<int64_t, int64_t>& key) const {
operator()( const std::pair<int64_t, int64_t>& key) const {
size_t h1 = std::hash<int64_t>{}(key.first) ; size_t h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ; size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes return h1 ^ (h2 << 1); // Combine hashes
@@ -34,20 +33,14 @@ struct PairHashInt64 {
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct Inters { struct Inters {
int nIn ; int nIn ;
int nOut ;
PNTVECTOR vpt ; PNTVECTOR vpt ;
int nOut ;
bool bCCW ; bool bCCW ;
int nChunk ; int nChunk ;
bool bSortedbyStart ; bool bSortedbyStart ;
// riordino le intersezioni per lato in senso antiorario dal top
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario bool operator < ( Inters& b)
// -1 se la curva è sempre dentro la cella
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool
operator < ( Inters& b)
{ {
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici // trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
@@ -82,8 +75,7 @@ struct Inters {
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ; ( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
} }
static bool static bool FirstEncounter( Inters& a, Inters& b)
FirstEncounter( Inters& a, Inters& b)
{ {
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima. // riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso // ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
@@ -143,18 +135,18 @@ struct Inters {
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ; ( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
} }
bool bool operator == ( Inters& b)
operator == ( Inters& b)
{ {
return AreSamePointExact( vpt[0], b.vpt[0]) ; return AreSamePointExact( vpt[0], b.vpt[0]) ;
} }
bool operator != ( Inters& b)
bool
operator != ( Inters& b)
{ {
return ! AreSamePointExact( vpt[0], b.vpt[0]) ; return ! AreSamePointExact( vpt[0], b.vpt[0]) ;
} }
} ; } ;
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
class Cell class Cell
@@ -168,12 +160,11 @@ class Cell
// | | // | |
// |_________________| // |_________________|
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE) // Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
public:
public : enum Collapsed { TO_VERIFY = -1, // da verificare
enum Collapsed { TO_VERIFY = -1, // da verificare NO_COLLAPSE = 0, // non ho coppie di lati collassati
NO_COLLAPSE = 0, // non ho coppie di lati collassati VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
public : public :
~Cell( void) {} ~Cell( void) {}
+932 -2648
View File
File diff suppressed because it is too large Load Diff
+49 -253
View File
@@ -29,21 +29,8 @@
#include <thread> #include <thread>
#include <future> #include <future>
#define DEBUG_REMOVE_FINS 0
#if DEBUG_REMOVE_FINS
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
std::vector<IGeoObj*> VT ;
std::vector<Color> VC ;
#endif
using namespace std ; using namespace std ;
#if !defined(_WIN64)
int VolZmap::m_nDexelNbr = 0 ;
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ; GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
@@ -68,13 +55,6 @@ VolZmap::VolZmap(void)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
VolZmap::~VolZmap( void) VolZmap::~VolZmap( void)
{ {
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
#if !defined(_WIN64)
int nDexelNbr = 0 ;
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
nDexelNbr += m_nDim[i] ;
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
#endif
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -95,13 +75,6 @@ VolZmap::Clear( void)
m_nNumBlock = 0 ; m_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ; m_nConnectedCompoCount = 0 ;
m_MapFrame.Reset() ; m_MapFrame.Reset() ;
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
#if !defined(_WIN64)
int nDexelNbr = 0 ;
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
nDexelNbr += m_nDim[i] ;
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
#endif
for ( int i = 0 ; i < N_MAPS ; ++ i) { for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ; m_nNx[i] = 0 ;
m_nNy[i] = 0 ; m_nNy[i] = 0 ;
@@ -1721,15 +1694,16 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
// Creo lo ZMap per i riferimenti degli intervalli sulle griglie // creo lo ZMap per i riferimenti degli intervalli sulle griglie
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ; PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid()) if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
return false ; return false ;
// Creo uno ZMap per gli intervalli da aggiungere o da rimuovere // creo uno ZMap per gli intervalli da aggiungere o da rimuovere
PtrOwner<VolZmap> pZMapExtra( CreateBasicVolZmap()) ; PtrOwner<VolZmap> pZMapExtra( CreateBasicVolZmap()) ;
if ( IsNull( pZMapExtra) || if ( IsNull( pZMapExtra) ||
! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0], ! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1],
m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dStep, IsTriDexel())) m_dStep, IsTriDexel()))
return false ; return false ;
@@ -1745,7 +1719,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie // Ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti nella Copia // Ciclo sul numero di dexel presenti nella Copia
for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) { for ( int nDex = 0 ; nDex < int( pZMapCopy->m_Values[nGrid].size()) ; ++ nDex) {
// Se il dexel corrente non ha sotto-intervalli passo al successivo // Se il dexel corrente non ha sotto-intervalli passo al successivo
if ( pZMapCopy->m_Values[nGrid][nDex].empty()) if ( pZMapCopy->m_Values[nGrid][nDex].empty())
continue ; continue ;
@@ -1753,9 +1727,9 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
int nI = nDex % m_nNx[nGrid] ; int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ;
// Recupero il numero di intervalli presenti nel Dexel corrente // Recupero il numero di intervalli presenti nel Dexel corrente
int nIntervals = ssize( pZMapCopy->m_Values[nGrid][nDex]) ; int nIntervals = int( pZMapCopy->m_Values[nGrid][nDex].size()) ;
// Scorro gli intervalli presenti // Scorro gli intervalli presenti
for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// Recupero l'intervallo corrente // Recupero l'intervallo corrente
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ; Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
@@ -1765,54 +1739,57 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler, AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) { if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente) // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente)
// ( lascio invariato lo ZMapCopy) // ( lascio invariato lo ZMapCopy)
nIntervals = ssize( m_Values[nGrid][nDex]) ; nIntervals = int( m_Values[nGrid][nDex].size()) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, Interval.dMin, pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax,
dToler, true, nToolNum, V_INVALID, V_INVALID) ; Interval.dMin, dToler, true,
nToolNum, V_INVALID, V_INVALID) ;
} }
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ] // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) // Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler, AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) { if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo) // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo)
// ( lascio invariato lo ZMapCopy) // ( lascio invariato lo ZMapCopy)
nIntervals = ssize( m_Values[nGrid][nDex]) ; nIntervals = int( m_Values[nGrid][nDex].size()) ;
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.dMax, pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, Interval.dMax,
dToler, true, nToolNum, V_INVALID, V_INVALID) ; pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, dToler, true,
nToolNum, V_INVALID, V_INVALID) ;
} }
} }
// --- Se richiesta prima restrizione // --- Se richiesta prima restrizione
else { else {
// Se la lunghezza dell'intervallo non è almeno il doppio della tolleranza // *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ]
double dLen = Interval.dMax - Interval.dMin ; // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
if ( dLen < 2. * ( dToler + EPS_SMALL)) { SubtractIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
// L'intervallo sparisce completamente Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, // Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni
Interval.vtMinN, Interval.vtMaxN, nToolNum, true) ; if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
// Rimuovo le parti di spillone nelle altre dimensioni // Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy)
if ( IsTriDexel()) { nIntervals = int( m_Values[nGrid][nDex].size()) ;
-- nIntervals ; pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, Interval.dMin,
Interval.dMin, Interval.dMax, Interval.dMax, dToler, true,
dToler, true, Tool::UNDEF, V_INVALID, V_INVALID) ; Tool::UNDEF, V_INVALID, V_INVALID) ;
}
} }
// Se sufficientemente lungo, allora // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
else { // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
// *** Estremo inferiore -> Intervallo : [ dMin, dMin + dToler ] SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMin + dToler, // Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax ] // Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy)
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) nIntervals = int( m_Values[nGrid][nDex].size()) ;
SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + EPS_SMALL, pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; Interval.dMin,
Interval.dMax, dToler, true,
Tool::UNDEF, V_INVALID, V_INVALID) ;
} }
} }
} }
@@ -1822,12 +1799,12 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy) // Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti // Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) { for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla // Se l'intervallo è vuoto, non faccio nulla
if ( m_Values[nGrid][nDex].empty()) if ( m_Values[nGrid][nDex].empty())
continue ; continue ;
// Per ogni intervallo ricavato fino ad ora, restringo della tolleranza // Per ogni intervallo ricavato fino ad ora, restringo della tolleranza
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
if ( bIsExtensionFirst) { if ( bIsExtensionFirst) {
m_Values[nGrid][nDex][nInfo].dMin += dToler ; m_Values[nGrid][nDex][nInfo].dMin += dToler ;
@@ -1839,7 +1816,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
m_Values[nGrid][nDex][nInfo].dMax += dToler ; m_Values[nGrid][nDex][nInfo].dMax += dToler ;
} }
// Definisco il colore // Definisco il colore
for ( int nOrigInfo = 0 ; nOrigInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nOrigInfo) { for ( int nOrigInfo = 0 ; nOrigInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nOrigInfo) {
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMin - m_Values[nGrid][nDex][nInfo].dMin < EPS_SMALL) if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMin - m_Values[nGrid][nDex][nInfo].dMin < EPS_SMALL)
m_Values[nGrid][nDex][nInfo].nToolMin = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMin ; m_Values[nGrid][nDex][nInfo].nToolMin = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMin ;
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL) if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL)
@@ -1853,7 +1830,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
// Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy) // Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy)
for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) { for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti // Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( pZMapExtra->m_Values[nGrid]) ; ++ nDex) { for ( int nDex = 0 ; nDex < int( pZMapExtra->m_Values[nGrid].size()) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla // Se l'intervallo è vuoto, non faccio nulla
if ( pZMapExtra->m_Values[nGrid][nDex].empty()) if ( pZMapExtra->m_Values[nGrid][nDex].empty())
continue ; continue ;
@@ -1861,19 +1838,19 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
int nI = nDex % m_nNx[nGrid] ; int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ;
// Per ogni intervallo ricavato fino ad ora... // Per ogni intervallo ricavato fino ad ora...
for ( int nInfo = 0 ; nInfo < ssize( pZMapExtra->m_Values[nGrid][nDex]) ; ++ nInfo) { for ( int nInfo = 0 ; nInfo < int( pZMapExtra->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ; double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ;
double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ; double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ;
Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ; Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ;
Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ; Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ;
// --- Se richiesta prima estensione // --- Se richiesta prima estensione
if ( bIsExtensionFirst) { if ( bIsExtensionFirst) {
// Aggiungo i contributi // ... aggiungo i contributi
AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
} }
// --- Se richiesta prima restrizione // --- Se richiesta prima restrizione
else { else {
// Sottraggo i contributi // ... sottraggo i contributi
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
} }
} }
@@ -1891,187 +1868,6 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
VolZmap::RemoveFins( const Vector3d& vtDir, double dThick)
{
// Verifico la Validità dello ZMap
if ( ! IsValid())
return false ;
// Per sicurezza normalizzo la direzione
Vector3d vtMyDir = vtDir ;
if ( ! vtMyDir.Normalize())
return false ;
double dMyThick = max( 10. * EPS_SMALL, dThick) ;
// Creo lo ZMap per i riferimenti degli intervalli sulle griglie
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
return false ;
// Creo uno ZMap per gli intervalli da aggiungere e successivamente da rimuovere
VolZmap ZMapExtra ;
if ( ! ZMapExtra.CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
m_dStep, IsTriDexel()))
return false ;
const double FIN_ANG_DEG_TOL = 55. ; // Approssimazione per eccesso dell'angolo massimo possibile tra una direzione generica
// e un versore della terna globale ( arccos( 1 / sqrt( 3) ~ 54.375)
const double COS_FIN_ANG_DEG_TOL = cos( FIN_ANG_DEG_TOL * DEGTORAD) ;
const int NUM_TOOL = 1000 ; // Identificativo Utensile per riconoscere le parti rimosse
// NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente
// Ciclo sulle griglie
DBLVECTOR vdThicks ;
if ( IsTriDexel())
vdThicks = { dThick, dThick, dThick} ;
else
vdThicks = { dThick} ;
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
// Verifico se l'angolo tra la direzione degli spilloni della griglia corrente è sotto alla tolleranza rispetto alla direzione
double dCosDir = ( nGrid == 0 ? vtMyDir.z :
( nGrid == 1 ? vtMyDir.x :
vtMyDir.y)) ;
if ( abs( dCosDir) < COS_FIN_ANG_DEG_TOL + EPS_ANG_SMALL)
continue ;
// Aggiorno l'effettivo valore dello spessore da considerare
double dCurrThick = dMyThick / abs( dCosDir) ; // (sicuramente esiste, essendo 55deg il limite)
vdThicks[nGrid] = dCurrThick ;
// Ciclo sul numero di dexel presenti nella Copia
for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) {
// Se il dexel corrente non ha sotto-intervalli passo al successivo
if ( pZMapCopy->m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro gli intervalli presenti
for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) {
// Recupero l'intervallo corrente
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
// Se entrambi gli estremi dell'intervallo non sono stati toccati dall'utensile, allora passo al successivo
bool bAnalyze = ( ( Interval.nToolMin == 1 && Interval.nToolMax == 1) ||
( Interval.dMax > m_dMaxZ[nGrid] - EPS_SMALL || Interval.dMin < m_dMinZ[nGrid] + EPS_SMALL)) ;
if ( ! bAnalyze)
continue ;
// Se la lunghezza dell'intervallo è superiore allo spessore richiesto, non faccio nulla
double dLen = Interval.dMax - Interval.dMin ;
if ( dLen > dCurrThick + EPS_ZERO)
continue ;
// Se ZMap composto da una sola griglia, elimino il contributo lungo la direzione corrente
if ( ! IsTriDexel()) {
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
- Interval.vtMinN, - Interval.vtMaxN, NUM_TOOL, true) ;
}
// Se Tridexel, aggiungo il contributo del cubetto corrente allo ZMap Extra
else
ZMapExtra.AddStripInterval( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, NUM_TOOL) ;
}
}
}
// Se non ho aggiunto alcun elemento allo ZMap Extra, non devo fare nulla
if ( ! ZMapExtra.IsValid())
return true ;
#if DEBUG_REMOVE_FINS
SaveGeoObj( ZMapExtra.Clone(), "C:\\Temp\\VolZMapSubt0.nge") ;
#endif
// Ciclo sulle griglie dello ZMap Extra
for ( int nGrid = 0 ; nGrid < ZMapExtra.m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( ZMapExtra.m_Values[nGrid]) ; ++ nDex) {
// Se l'intervallo è vuoto, non faccio nulla
if ( ZMapExtra.m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro i gli Intervalli dello Spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( ZMapExtra.m_Values[nGrid][nDex]) ; ++ nInfo) {
double dMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMin ;
double dMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMax ;
Vector3d vtNMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMinN ;
Vector3d vtNMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMaxN ;
// sottraggo tali contributi
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, - vtNMin, - vtNMax, NUM_TOOL, true) ;
}
}
}
if ( ! IsValid())
return true ;
#if DEBUG_REMOVE_FINS
SaveGeoObj( this->Clone(), "C:\\Temp\\VolZMapSubt1.nge") ;
#endif
// Sistemo le Normali sullo ZMap ricavato
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'Intervallo è vuoto non faccio nulla
if ( m_Values[nGrid][nDex].empty())
continue ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Scorro gli intervalli dello spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
// Se intervallo con estremo minimo derivante dalla sottrazione con ZMapExtra, medio le normali
int nToolMin = m_Values[nGrid][nDex][nInfo].nToolMin ;
if ( nToolMin == NUM_TOOL) {
// Recupero il valore minimo, se sul bordo dello ZMap corrente non faccio nulla
double dMin = m_Values[nGrid][nDex][nInfo].dMin ;
if ( dMin > m_dMinZ[nGrid] + EPS_SMALL) {
Vector3d vtMinN = V_NULL ;
double dZMin = INFINITO ;
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMin, vtMyDir, dThick, true, 1, vtMinN, dZMin)) {
vtMinN = - ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
dZMin = dMin ;
}
m_Values[nGrid][nDex][nInfo].vtMinN = vtMinN ;
m_Values[nGrid][nDex][nInfo].dMin = dZMin ;
}
}
// Se intervallo con estremo massimo derivante dalla sottrazione con ZMapExtra, medio le normali
int nToolMax = m_Values[nGrid][nDex][nInfo].nToolMax ;
if ( nToolMax == NUM_TOOL) {
// Recupero il valore massimo, se sul bordo dello ZMap corrente non faccio nulla
double dMax = m_Values[nGrid][nDex][nInfo].dMax ;
if ( dMax < m_dMaxZ[nGrid] - EPS_SMALL) {
Vector3d vtMaxN = V_NULL ;
double dZMax = INFINITO ;
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMax, vtMyDir, dThick, false, 1, vtMaxN, dZMax)) {
vtMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
dZMax = dMax ;
}
m_Values[nGrid][nDex][nInfo].vtMaxN = vtMaxN ;
m_Values[nGrid][nDex][nInfo].dMax = dZMax ;
}
}
}
}
}
// Riassegno il Tool dell'utensile alle nuove parti
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// Ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
// Se l'Intervallo è vuoto non faccio nulla
if ( m_Values[nGrid][nDex].empty())
continue ;
// Scorro gli intervalli dello spillone corrente
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
if ( m_Values[nGrid][nDex][nInfo].nToolMin == NUM_TOOL)
m_Values[nGrid][nDex][nInfo].nToolMin = 1 ;
if ( m_Values[nGrid][nDex][nInfo].nToolMax == NUM_TOOL)
m_Values[nGrid][nDex][nInfo].nToolMax = 1 ;
}
}
}
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
+11 -23
View File
@@ -21,8 +21,9 @@
#include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkSurfTriMesh.h"
#include <unordered_map> #include <unordered_map>
#include <stack> #include <stack>
#include <tuple> #include <mutex>
#include <atomic> #include <atomic>
#include <tuple>
typedef std::pair<Point3d, Vector3d> PNTVEC3D ; typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
@@ -81,10 +82,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
public : // IVolZmap public : // IVolZmap
bool CopyFrom( const IGeoObj* pGObjSrc) override ; bool CopyFrom( const IGeoObj* pGObjSrc) override ;
bool Clear( void) override ; bool Clear( void) override ;
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ; bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ; bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ; bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ; bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0) override ;
int GetBlockCount( void) const override ; int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ; int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ; bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -151,7 +152,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool AddSurfTm( const ISurfTriMesh* pStm) override ; bool AddSurfTm( const ISurfTriMesh* pStm) override ;
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ; bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ; bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ;
bool RemoveFins( const Vector3d& vtDir, double dThick) override ;
bool Offset( double dOffs, int nType) override ; bool Offset( double dOffs, int nType) override ;
public : // IGeoObjRW public : // IGeoObjRW
@@ -227,15 +227,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
typedef std::unordered_map<int, Voxel> VoxelContainer ; typedef std::unordered_map<int, Voxel> VoxelContainer ;
// Unordered map per la coerenza topologica // Unordered map per la coerenza topologica
typedef std::unordered_map<int, bool> InterVoxMatter ; typedef std::unordered_map<int, bool> InterVoxMatter ;
#if !defined(_WIN64)
// Numero massimo approssimativo di Dexel per versione 32-bit per evitare Crash con memoria
#if defined(_DEBUG)
static const int MAX_DEXEL_32_BIT = 3000000 + 1 ;
#else
static const int MAX_DEXEL_32_BIT = 5000000 + 1 ;
#endif
static int m_nDexelNbr ; // numero corrente di Dexel presenti
#endif
private : private :
bool CopyFrom( const VolZmap& clSrc) ; bool CopyFrom( const VolZmap& clSrc) ;
@@ -272,7 +263,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax, bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin, double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
const Vector3d& vtToolMax) ; const Vector3d& vtToolMax) ;
bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) ;
bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax, bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
Vector3d& vtMin, Vector3d& vtMax) ; Vector3d& vtMin, Vector3d& vtMax) ;
// Spostamenti utensile // Spostamenti utensile
@@ -393,6 +383,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
double& dU1, double& dU2) const ; double& dU1, double& dU2) const ;
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ; bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ; bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen, const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp, bool bTapLow, bool bTapUp,
@@ -494,11 +487,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
// Funzioni per Offset di Zmap // Funzioni per Offset di Zmap
bool OffsetFillet( double dOffs) ; bool OffsetFillet( double dOffs) ;
bool OffsetSharped( double dOffs, int nType) ; bool OffsetSharped( double dOffs, int nType) ;
// Funzione analisi punti/Normali per Alette
bool GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) ;
bool ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
Vector3d& vtN, double& dNewZ) ;
private : private :
enum Move5Axis { enum Move5Axis {
@@ -569,9 +557,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::vector<InterVoxMatter> m_SliceXY ; mutable std::vector<InterVoxMatter> m_SliceXY ;
mutable std::vector<InterVoxMatter> m_SliceXZ ; mutable std::vector<InterVoxMatter> m_SliceXZ ;
mutable std::vector<InterVoxMatter> m_SliceYZ ; mutable std::vector<InterVoxMatter> m_SliceYZ ;
mutable std::atomic_flag m_SliceFlag ; mutable std::mutex m_SliceMutex ;
bool m_bIsBox ; std::atomic<bool> m_bIsBox ;
int m_nCurrTool ; int m_nCurrTool ;
std::vector<Tool> m_vTool ; std::vector<Tool> m_vTool ;
+121
View File
@@ -2071,6 +2071,127 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
return false ; return false ;
} }
//----------------------------------------------------------------------------
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti.
//----------------------------------------------------------------------------
bool
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
int nBasInt = 0 ;
if ( abs( vtV.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 1 ;
vtN1 = Z_AX ;
}
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 2 ;
vtN2 = - Z_AX ;
}
}
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
if ( nBasInt == 3) {
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Determino le intersezioni con la superficie laterale del cilindro
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
vtV.x * vtV.x + vtV.y * vtV.y} ;
DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
// Epsilon per piani di tappo
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
if ( nRoot == 2) {
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
-- nRoot ;
}
if ( nRoot >= 1) {
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
if ( nRoot == 2)
vdRoots[0] = vdRoots[1] ;
-- nRoot ;
}
}
// Due soluzioni: la retta interseca due volte la superficie laterale
if ( nRoot == 2) {
// Punti di intersezione con la superficie del cilindro
ptInt1 = ptP + vdRoots[0] * vtV ;
ptInt2 = ptP + vdRoots[1] * vtV ;
// Determino le normali
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
vtN1.Normalize() ;
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
vtN2.Normalize() ;
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Una soluzione : la retta interseca la superficie laterale e un piano
else if ( nRoot == 1) {
// Se piano superiore
if ( nBasInt == 2) {
// Punto di intersezione
ptInt1 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
vtN1.Normalize() ;
}
// altrimenti piano inferiore
else if ( nBasInt == 1) {
// Punto di intersezione
ptInt2 = ptP + vdRoots[0] * vtV ;
// Normale alla superficie del cilindro verso l'interno
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
vtN2.Normalize() ;
}
// altrimenti niente
else
return false ;
// Porto i punti e i versori nel riferimento globale
ptInt1.ToGlob( CylFrame) ;
vtN1.ToGlob( CylFrame) ;
ptInt2.ToGlob( CylFrame) ;
vtN2.ToGlob( CylFrame) ;
// Trovate intersezioni
return true ;
}
// Nessuna soluzione : nessuna intersezione
else
return false ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z. // Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
// La funzione restituisce true in caso di intersezione, false altrimenti. // La funzione restituisce true in caso di intersezione, false altrimenti.
+9 -74
View File
@@ -28,7 +28,7 @@ using namespace std ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError) VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
{ {
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL) if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
@@ -81,24 +81,12 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ; m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
// Creazione delle celle per ogni mappa // Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ; m_Values[i].resize( m_nDim[i]) ;
// Riempimento delle celle // Riempimento delle celle
for ( int i = 0 ; i < m_nMapNum ; ++ i) { for ( int i = 0 ; i < m_nMapNum ; ++ i)
for ( int j = 0 ; j < m_nDim[i] ; ++ j) { for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
// Aggiungo il tratto al dexel vuoto // Aggiungo il tratto al dexel vuoto
@@ -128,7 +116,6 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
break ; break ;
} }
} }
}
// Definizione delle limitazioni iniziali in Z per ogni mappa // Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ; m_dMinZ[0] = 0 ;
@@ -149,7 +136,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError) VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
{ {
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL) if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
@@ -200,18 +187,6 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ; m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
// Creazione delle celle per ogni mappa // Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i) for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ; m_Values[i].resize( m_nDim[i]) ;
@@ -235,7 +210,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError) VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
{ {
// Aggiorno la dimensione della mappa 1 o 3 // Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ; m_nMapNum = ( bTriDex ? 3 : 1) ;
@@ -275,35 +250,14 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
m_nNx[1] = m_nNy[0] ; m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ; m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ; m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ; m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ; m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ; m_nDim[2] = m_nNx[2] * m_nNy[2] ;
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_Values[1].resize( m_nDim[1]) ;
m_Values[2].resize( m_nDim[2]) ; m_Values[2].resize( m_nDim[2]) ;
} }
// Se dimensione singola
else { else {
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
#if !defined(_WIN64)
m_nDexelNbr += m_nDim[0] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_nNx[1] = 0 ; m_nNx[1] = 0 ;
m_nNy[1] = 0 ; m_nNy[1] = 0 ;
m_nDim[1] = 0 ; m_nDim[1] = 0 ;
@@ -834,7 +788,7 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError) VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
{ {
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
double dVol ; double dVol ;
@@ -884,33 +838,14 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
m_nNx[1] = m_nNy[0] ; m_nNx[1] = m_nNy[0] ;
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ; m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
m_nDim[1] = m_nNx[1] * m_nNy[1] ; m_nDim[1] = m_nNx[1] * m_nNy[1] ;
m_Values[1].resize( m_nDim[1]) ;
m_nNx[2] = m_nNy[1] ; m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ; m_nNy[2] = m_nNx[0] ;
m_nDim[2] = m_nNx[2] * m_nNy[2] ; m_nDim[2] = m_nNx[2] * m_nNy[2] ;
#if !defined(_WIN64)
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
m_nDexelNbr += m_nDim[i] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_Values[1].resize( m_nDim[1]) ;
m_Values[2].resize( m_nDim[2]) ; m_Values[2].resize( m_nDim[2]) ;
} }
// Se a dimensione singola
else { else {
#if !defined(_WIN64)
m_nDexelNbr += m_nDim[0] ;
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
Clear() ;
if ( nError != nullptr)
*nError = 1 ;
return false ;
}
#endif
m_nNx[1] = 0 ; m_nNx[1] = 0 ;
m_nNy[1] = 0 ; m_nNy[1] = 0 ;
m_nDim[1] = 0 ; m_nDim[1] = 0 ;
+12 -24
View File
@@ -1271,15 +1271,13 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ; auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceYZ[nSlBlockN].end()) { if ( it != m_SliceYZ[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs( nAdjVox3[nCount]) == 2) { else if ( abs( nAdjVox3[nCount]) == 2) {
@@ -1289,15 +1287,13 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ; auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXZ[nSlBlockN].end()) { if ( it != m_SliceXZ[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs( nAdjVox3[nCount]) == 3) { else if ( abs( nAdjVox3[nCount]) == 3) {
@@ -1307,15 +1303,13 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
bDefTopology = true ; bDefTopology = true ;
} }
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
auto it = m_SliceXY[nSlBlockN].find( nSliceN) ; auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
if ( it != m_SliceXY[nSlBlockN].end()) { if ( it != m_SliceXY[nSlBlockN].end()) {
bMatOnSlice = it->second ; bMatOnSlice = it->second ;
bDefTopology = true ; bDefTopology = true ;
} }
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
} }
@@ -1380,33 +1374,27 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceYZ.emplace( nSliceN, bMatOnSlice) ; SliceYZ.emplace( nSliceN, bMatOnSlice) ;
else { else {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ; m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs(nAdjVox3[nCount]) == 2) { else if ( abs(nAdjVox3[nCount]) == 2) {
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceXZ.emplace( nSliceN, bMatOnSlice) ; SliceXZ.emplace( nSliceN, bMatOnSlice) ;
else { else {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ; m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
else if ( abs(nAdjVox3[nCount]) == 3) { else if ( abs(nAdjVox3[nCount]) == 3) {
if ( nSlBlockN == nBlock) if ( nSlBlockN == nBlock)
SliceXY.emplace(nSliceN, bMatOnSlice) ; SliceXY.emplace(nSliceN, bMatOnSlice) ;
else { else {
while ( m_SliceFlag.test_and_set( memory_order_acquire)) m_SliceMutex.lock() ;
m_SliceFlag.wait( true, memory_order_relaxed) ;
m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ; m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
m_SliceFlag.clear( memory_order_release) ; m_SliceMutex.unlock() ;
m_SliceFlag.notify_one() ;
} }
} }
} }
+4 -6
View File
@@ -21,7 +21,6 @@
#include "CurveLine.h" #include "CurveLine.h"
#include "CurveArc.h" #include "CurveArc.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtNumUtils.h"
@@ -969,13 +968,12 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true, ptInt1, vtN1, ptInt2, vtN2)) {
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
if ( dOffs > 0.) if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ; AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ;
else else
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ; SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
} }
} }
} }
+104 -430
View File
@@ -21,7 +21,6 @@
#include "VolZmap.h" #include "VolZmap.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "IntersLineBox.h" #include "IntersLineBox.h"
#include "IntersLineCyl.h"
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkSurfBezier.h"
@@ -32,13 +31,6 @@
#include <future> #include <future>
#include <numeric> #include <numeric>
#define SAVETRIMMINGTOOL 0
#if SAVETRIMMINGTOOL
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ; using namespace std ;
// ------------------------- OPERAZIONI SU INTERVALLI -------------------------------------------------------------------------------------- // ------------------------- OPERAZIONI SU INTERVALLI --------------------------------------------------------------------------------------
@@ -846,183 +838,6 @@ VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin,
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum)
{
// Se non Tridex, esco
if ( ! IsTriDexel())
return true ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo che indici nI, nJ siano entro i limiti
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
return false ;
// Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia)
int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio +
( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
// Scorro i Voxel correnti
for ( int nVox = - 1 ; nVox < nVoxNum - 1 ; ++ nVox) {
// Considero solo i Voxel interni all'intervallo corrente
if ( ( nVox + 1) * m_dStep > dZMin && ( nVox - 1) * m_dStep < dZMax) {
// Recupero gli indici per la griglia successiva
int nMyGrid = ( nGrid + 1) % 3 ;
int nMyI = nJ ;
int nMyJ = nVox ;
int nMyK = nI ;
double dMyMinZ = nMyK * m_dStep ;
double dMyMaxZ = ( nMyK + 1) * m_dStep ;
Vector3d vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
nMyGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
Vector3d vtMyMinN = - vtMyMaxN ;
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
// Recupero gli indici della griglia precedente
nMyGrid = ( nGrid + 2) % 3 ;
nMyI = nVox ;
nMyJ = nI ;
nMyK = nJ ;
dMyMinZ = nMyK * m_dStep ;
dMyMaxZ = ( nMyK + 1) * m_dStep ;
vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
nMyGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
vtMyMinN = - vtMyMaxN ;
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
}
}
// Aggiungo l'intervallo corrente
Vector3d vtMyMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() :
nGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY()) ;
Vector3d vtMyMinN = - vtMyMaxN ;
AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMinN, vtMyMaxN, nToolNum, true) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc)
{
// Verifico che lo ZMap corrente sia valido
if ( ! IsValid())
return false ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo che indici nI, nJ siano entro i limiti
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
return false ;
// Calcolo il punto
ptLoc = m_MapFrame.Orig() ;
if ( nGrid == 0)
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersX() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersY() + dZ * m_MapFrame.VersZ()) ;
else if ( nGrid == 1)
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersY() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersZ() + dZ * m_MapFrame.VersX()) ;
else
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersZ() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersX() + dZ * m_MapFrame.VersY()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
Vector3d& vtN, double& dNewZ)
{
// Verifico che lo ZMap corrente sia valido
if ( ! IsValid())
return false ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Inizializzo il vettore da restituire
vtN = V_NULL ;
dNewZ = INFINITO ;
// Proietto la direzione lungo la mappa della griglia corrente
Vector3d vtDirProj = OrthoCompo( vtDir, ( nGrid == 0 ? m_MapFrame.VersZ() :
nGrid == 1 ? m_MapFrame.VersX() :
m_MapFrame.VersY())) ;
// Sposto il punto corrente nella direzione opposta a quella trovata
Point3d ptLoc ;
if ( ! GetLocalPoint( nGrid, nI, nJ, dZ, ptLoc))
return false ;
Point3d ptCenterLoc = ptLoc ;
ptCenterLoc.Translate( - vtDirProj * dThick) ;
// Recupero il Box nel punto
BBox3d BBoxLoc ; BBoxLoc.Add( ptCenterLoc) ;
double dExpandX = ( m_MapFrame.VersX() * X_AX) * dThick * ( vtDirProj * X_AX) ;
double dExpandY = ( m_MapFrame.VersY() * Y_AX) * dThick * ( vtDirProj * Y_AX) ;
double dExpandZ = ( m_MapFrame.VersZ() * Z_AX) * dThick * ( vtDirProj * Z_AX) ;
BBoxLoc.Expand( max( ( m_dStep + EPS_SMALL), dExpandX),
max( ( m_dStep + EPS_SMALL), dExpandY),
max( ( m_dStep + EPS_SMALL), dExpandZ)) ;
// Porto il Box nel Frame della Mappa corrente
BBox3d BBoxInGrid = GetToLoc( BBoxLoc, m_MapFrame) ;
// Recupero i suoi estremi
Point3d ptBoxLocMax = BBoxInGrid.GetMax() ;
Point3d ptBoxLocMin = BBoxInGrid.GetMin() ;
// Determino gli intervalli locali in X e Y locali alla Griglia correnti
double dMinXLoc = ( nGrid == 0 ? ptBoxLocMin.x : nGrid == 1 ? ptBoxLocMin.y : ptBoxLocMin.z) ;
double dMinYLoc = ( nGrid == 0 ? ptBoxLocMin.y : nGrid == 1 ? ptBoxLocMin.z : ptBoxLocMin.x) ;
double dMaxXLoc = ( nGrid == 0 ? ptBoxLocMax.x : nGrid == 1 ? ptBoxLocMax.y : ptBoxLocMax.z) ;
double dMaxYLoc = ( nGrid == 0 ? ptBoxLocMax.y : nGrid == 1 ? ptBoxLocMax.z : ptBoxLocMax.x) ;
// Recupero gli Spilloni coinvolti nel Box
int nStartI = max( 0, int( dMinXLoc / m_dStep)) ;
int nEndI = min( m_nNx[nGrid] - 1, int( dMaxXLoc / m_dStep)) ;
int nStartJ = max( 0, int( dMinYLoc / m_dStep)) ;
int nEndJ = min( m_nNy[nGrid] - 1, int( dMaxYLoc / m_dStep)) ;
double dSqMinDist = INFINITO ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
// Determino la posizione corrente dello Spillone
int nPos = j * m_nNx[nGrid] + i ;
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
// Scorro i suoi Intervalli
for ( int nInterval = 0 ; nInterval < ssize( vDexel) ; ++ nInterval) {
// Se l'Intervallo presenta un indice del Tool da evitare, passo al successivo
if ( ( bMinVsMax && vDexel[nInterval].nToolMin != nTool) ||
( ! bMinVsMax && vDexel[nInterval].nToolMax != nTool))
continue ;
// Recupero l'estremo da analizzare
double dZInterval = ( bMinVsMax ? vDexel[nInterval].dMin : vDexel[nInterval].dMax) ;
// Recupero il punto associato
Point3d ptInterval ;
if ( ! GetLocalPoint( nGrid, i, j, dZInterval, ptInterval))
return false ;
// Se il punto è dentro nel Box, aggiungo il contributo della normale presente
if ( BBoxLoc.Encloses( ptInterval)) {
double dCurrSqDist = ( SqDist( ptInterval, ptLoc)) ;
if ( dCurrSqDist < dSqMinDist) {
dSqMinDist = dCurrSqDist ;
vtN = ( bMinVsMax ? vDexel[nInterval].vtMinN : vDexel[nInterval].vtMaxN) ;
dNewZ = dZInterval ;
}
}
}
}
}
return ( ! vtN.IsSmall() && dZ < INFINITO - 1) ;
}
// ------------------------- BOUNDING BOX -------------------------------------------------------------------------------------- // ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -1754,6 +1569,10 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
else if ( n5AxisType == Move5Axis::ACROSS) else if ( n5AxisType == Move5Axis::ACROSS)
nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra
int nSurfInd = 0 ;
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
double dSide = 0 ;
// punti di riferimento sul tool // punti di riferimento sul tool
// tip del tool // tip del tool
Point3d ptP1T ; Point3d ptP1T ;
@@ -1766,17 +1585,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
Vector3d vtDirTip = ptP2T - ptP1T ; Vector3d vtDirTip = ptP2T - ptP1T ;
bool bTopIsPivot = vtDirTop.IsSmall() ; bool bTopIsPivot = vtDirTop.IsSmall() ;
bool bTipIsPivot = vtDirTip.IsSmall() ; bool bTipIsPivot = vtDirTip.IsSmall() ;
bool bSmallMovement = vtDirTop.Len() < 10 * EPS_SMALL && vtDirTip.Len() < 10 * EPS_SMALL ; bool bTopAndTipAreEquiverse = vtDirTop * vtDirTip > 0 ;
bool bInverse = ! (bTopIsPivot || bTipIsPivot) && vtDirTop * vtDirTip < 0 ;
if ( bInverse)
nTotSurf += 4 ;
if ( bSmallMovement)
nTotSurf += 2 ;
int nSurfInd = 0 ;
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
double dSide = 0 ;
// box dell'intero volume spazzato, nel riferimento object oriented // box dell'intero volume spazzato, nel riferimento object oriented
BBox3d bbVol ; BBox3d bbVol ;
@@ -1793,9 +1602,9 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
PNTVECTOR vPntTopStartBack(3) ; PNTVECTOR vPntTopStartBack(3) ;
PNTVECTOR vPntTopEndBack(3) ; PNTVECTOR vPntTopEndBack(3) ;
if ( nSub > 1) { if ( nSub > 1) {
if ( bTopIsPivot) if( bTopIsPivot)
vtDirTop = vtDirTip ; vtDirTop = vtDirTip ;
if ( bTipIsPivot) if( bTipIsPivot)
vtDirTip = vtDirTop ; vtDirTip = vtDirTop ;
// determino in che modo collegare il cilindro iniziale con quello finale // determino in che modo collegare il cilindro iniziale con quello finale
Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ; Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ;
@@ -1809,10 +1618,10 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
dSide = ( ptRefEnd - ptRefStart) * vtLs ; dSide = ( ptRefEnd - ptRefStart) * vtLs ;
// calcolo anche i vettori per le basi inferiori // calcolo anche i vettori per le basi inferiori
Vector3d vtTipBaseStart = bInverse ? ( vtLs ^ vtDirTip) : -( vtLs ^ vtDirTip) ; Vector3d vtTipBaseStart = -( vtLs ^ vtDirTip) ;
vtTipBaseStart.Normalize() ; vtTipBaseStart.Normalize() ;
vtTipBaseStart *= dMinRad ; vtTipBaseStart *= dMinRad ;
Vector3d vtTipBaseEnd = bInverse ? ( vtLe ^ vtDirTip) : -( vtLe ^ vtDirTip) ; Vector3d vtTipBaseEnd = -( vtLe ^ vtDirTip) ;
vtTipBaseEnd.Normalize() ; vtTipBaseEnd.Normalize() ;
vtTipBaseEnd *= dMinRad ; vtTipBaseEnd *= dMinRad ;
// aggiungo il primo punto per ognuno dei gruppi // aggiungo il primo punto per ognuno dei gruppi
@@ -1861,44 +1670,22 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
} }
vector<PNTVECTOR> vvPtCtrl ; vector<PNTVECTOR> vvPtCtrl ;
if ( ! bSmallMovement) { // superficie laterale sinistra
// superficie laterale sinistra CurveLine cLineLeftStart ; cLineLeftStart.Set( vPntTipStartFront.back(), vPntTopStartFront.back()) ;
CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ; PtrOwner<CurveBezier> cBezLeftStart( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftStart, nDegU, bRat))) ;
if ( ! cLineLeftBottom.IsValid()) CurveLine cLineLeftEnd ; cLineLeftEnd.Set( vPntTipEndFront.back(), vPntTopEndFront.back()) ;
return false ; PtrOwner<CurveBezier> cBezLeftEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftEnd, nDegU, bRat))) ;
if ( bInverse) vvPtCtrl.emplace_back( cBezLeftStart->GetAllControlPoints()) ;
cLineLeftBottom.Invert() ; PNTVECTOR vPntLeft = cBezLeftEnd->GetAllControlPoints() ;
PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
if ( IsNull( cBezLeftBottom)) // superficie laterale destra
return false ; CurveLine cLineRightStart ; cLineRightStart.Set( vPntTopStartFront.front(), vPntTipStartFront.front()) ;
CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ; PtrOwner<CurveBezier> cBezRightStart( GetBasicCurveBezier( LineToBezierCurve( &cLineRightStart, nDegU, bRat))) ;
if ( ! cLineLeftTop.IsValid()) CurveLine cLineRightEnd ; cLineRightEnd.Set( vPntTopEndFront.front(), vPntTipEndFront.front()) ;
return false ; PtrOwner<CurveBezier> cBezRightEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineRightEnd, nDegU, bRat))) ;
PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ; vvPtCtrl.emplace_back( cBezRightStart->GetAllControlPoints()) ;
if ( IsNull( cBezLeftTop)) PNTVECTOR vPntRight = cBezRightEnd->GetAllControlPoints() ;
return false ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
// superficie laterale destra
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
if ( ! cLineRightBottom.IsValid())
return false ;
if ( bInverse)
cLineRightBottom.Invert() ;
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
if ( IsNull( cBezRightBottom))
return false ;
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
if ( ! cLineRightTop.IsValid())
return false ;
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
if ( IsNull( cBezRightTop))
return false ;
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
}
if ( nSub == 1) { if ( nSub == 1) {
// superficie inferiore // superficie inferiore
vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ; vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ;
@@ -1962,83 +1749,43 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
if ( ! bTipIsPivot) { if ( ! bTipIsPivot) {
// inferiori // inferiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTipEnd01 = cBezTipStartF1->GetAllControlPoints() ; vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints());
if ( ! bInverse) PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints();
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end());
else vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints());
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ; PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints();
PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints() ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end());
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ;
PNTVECTOR vPntTipEnd02 = cBezTipStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
else
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
} }
else { else {
PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints() ; PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints();
if ( ! bInverse) vvPtCtrl.emplace_back(vPntTipEnd01.rbegin(), vPntTipEnd01.rend());
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ; PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints();
else vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend());
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ; PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints();
PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints() ; vvPtCtrl.emplace_back(vPntTipEnd02.rbegin(), vPntTipEnd02.rend());
if ( ! bInverse) PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints();
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend());
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
} }
} }
if ( ! bTopIsPivot) { if ( ! bTopIsPivot) {
// superiori // superiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTopEnd01 = cBezTopStartB1->GetAllControlPoints() ; vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ; PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints();
PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints() ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end());
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ; vvPtCtrl.emplace_back(cBezTopStartB2->GetAllControlPoints());
PNTVECTOR vPntTopEnd02 = cBezTopStartB2->GetAllControlPoints() ; PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints();
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end());
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
} }
else { else {
PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints() ; PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints();
if ( ! bInverse) vvPtCtrl.emplace_back(vPntTopEnd01.rbegin(), vPntTopEnd01.rend());
vvPtCtrl.emplace_back( vPntTopEnd01.rbegin(), vPntTopEnd01.rend()) ; PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints();
else vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend());
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ; PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints();
PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints() ; vvPtCtrl.emplace_back(vPntTopEnd02.rbegin(), vPntTopEnd02.rend());
if ( ! bInverse) PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints();
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend());
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTopEnd02.rbegin(), vPntTopEnd02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
} }
} }
@@ -2047,74 +1794,36 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
if ( ! bTipIsPivot) { if ( ! bTipIsPivot) {
// inferiori // inferiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints() ; PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints();
if ( ! bInverse) vvPtCtrl.emplace_back(vPntTip01.rbegin(), vPntTip01.rend());
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ; PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints();
else vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend());
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ; PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints();
PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints() ; vvPtCtrl.emplace_back(vPntTip02.rbegin(), vPntTip02.rend());
if ( ! bInverse) PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints();
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend());
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
} }
else { else {
PNTVECTOR vPntTip01 = cBezTipStartF1->GetAllControlPoints() ; vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints());
if ( ! bInverse) PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints();
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end());
else vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints());
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ; PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints();
PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints() ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end());
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ;
PNTVECTOR vPntTip02 = cBezTipStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
else
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
} }
} }
if ( ! bTopIsPivot) { if( ! bTopIsPivot) {
// superiori // superiori
if ( dSide > 0) { if ( dSide > 0) {
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints() ; PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints();
if ( ! bInverse) vvPtCtrl.emplace_back(vPntTop01.rbegin(), vPntTop01.rend());
vvPtCtrl.emplace_back( vPntTop01.rbegin(), vPntTop01.rend()) ; PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints();
else vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend());
vvPtCtrl.emplace_back( vPntTop01.begin(), vPntTop01.end()) ; PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints();
PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints() ; vvPtCtrl.emplace_back(vPntTop02.rbegin(), vPntTop02.rend());
if ( ! bInverse) PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints();
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend()) ; vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend());
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end()) ;
PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.emplace_back( vPntTop02.rbegin(), vPntTop02.rend()) ;
else
vvPtCtrl.emplace_back( vPntTop02.begin(), vPntTop02.end()) ;
PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints() ;
if ( ! bInverse)
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend()) ;
else
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end()) ;
} }
else { else {
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints()); vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
@@ -2130,43 +1839,23 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
// chiudo il volume con le superfici verticali e le basi dei tool // chiudo il volume con le superfici verticali e le basi dei tool
// chiudo il volume con le superici verticali end front 1 // chiudo il volume con le superici verticali end 1
vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ;
PNTVECTOR vPntEndF1 = cBezTopEndF1->GetAllControlPoints() ; PNTVECTOR vPntEnd1 = cBezTopEndF1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF1.begin(), vPntEndF1.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd1.begin(), vPntEnd1.end()) ;
// chiudo il volume con le superici verticali end front 2 // chiudo il volume con le superici verticali end 2
vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ;
PNTVECTOR vPntEndF2 = cBezTopEndF2->GetAllControlPoints() ; PNTVECTOR vPntEnd2 = cBezTopEndF2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF2.begin(), vPntEndF2.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd2.begin(), vPntEnd2.end()) ;
if ( bInverse || bSmallMovement) {
// chiudo il volume con le superici verticali end back 1
vvPtCtrl.emplace_back( cBezTipEndB1->GetAllControlPoints()) ;
PNTVECTOR vPntEndB1 = cBezTopEndB1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB1.begin(), vPntEndB1.end()) ;
// chiudo il volume con le superici verticali end back 2
vvPtCtrl.emplace_back( cBezTipEndB2->GetAllControlPoints()) ;
PNTVECTOR vPntEndB2 = cBezTopEndB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB2.begin(), vPntEndB2.end()) ;
}
// chiudo il volume con le superici verticali start back 1 // chiudo il volume con le superici verticali start 1
vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ;
PNTVECTOR vPntStartB1 = cBezTopStartB1->GetAllControlPoints() ; PNTVECTOR vPntStart1 = cBezTopStartB1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB1.begin(), vPntStartB1.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart1.begin(), vPntStart1.end()) ;
// chiudo il volume con le superfici verticali start back 2 // chiudo il volume con le superfici verticali start 2
vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ; vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ;
PNTVECTOR vPntStartB2 = cBezTopStartB2->GetAllControlPoints() ; PNTVECTOR vPntStart2 = cBezTopStartB2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB2.begin(), vPntStartB2.end()) ; vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart2.begin(), vPntStart2.end()) ;
if ( bInverse || bSmallMovement) {
// chiudo il volume con le superici verticali start front 1
vvPtCtrl.emplace_back( cBezTipStartF1->GetAllControlPoints()) ;
PNTVECTOR vPntStartF1 = cBezTopStartF1->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF1.begin(), vPntStartF1.end()) ;
// chiudo il volume con le superfici verticali start front 2
vvPtCtrl.emplace_back( cBezTipStartF2->GetAllControlPoints()) ;
PNTVECTOR vPntStartF2 = cBezTopStartF2->GetAllControlPoints() ;
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF2.begin(), vPntStartF2.end()) ;
}
// superfici di base dei tool // superfici di base dei tool
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) { if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) {
@@ -2237,7 +1926,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
} }
// inizializzo le superfici bilineari e i parametri per le intersezioni // inizializzo le superfici bilineari e i parametri per le intersezioni
for ( int z = 0 ; z < ssize( vvPtCtrl) ; ++z) { for ( int z = 0 ; z < int( vvPtCtrl.size()) ; ++z) {
vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ;
@@ -2248,11 +1937,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ;
vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ; vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ;
#if SAVETRIMMINGTOOL
if ( nGrid == 0)
vGeo.push_back( vSurfBez[nSurfInd].sBez.Clone()) ;
#endif
Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ; Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ;
Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ; Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ;
Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ; Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ;
@@ -2301,11 +1985,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
++ nSurfInd ; ++ nSurfInd ;
} }
#if SAVETRIMMINGTOOL
if ( nGrid == 0)
SaveGeoObj( vGeo, "D:\\Temp\\VirtualMilling\\5axisAdvanced\\marmo sottosquadra\\volume.nge") ;
#endif
// scorro tutti gli spilloni interessati // scorro tutti gli spilloni interessati
int j = 0 ; int j = 0 ;
int nLastForwardJ = -1 ; int nLastForwardJ = -1 ;
@@ -6250,8 +5929,7 @@ VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, co
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
} }
@@ -6296,9 +5974,8 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
// Cilindro // Cilindro
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -6477,8 +6154,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
// Cilindro iniziale // Cilindro iniziale
CylFrame.ChangeOrig( ptITip) ; CylFrame.ChangeOrig( ptITip) ;
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -6486,7 +6162,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC // del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
// il vettore che congiunge le due origini. // il vettore che congiunge le due origini.
CylFrame.ChangeOrig( ptITip + vtMove) ; CylFrame.ChangeOrig( ptITip + vtMove) ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) { if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
@@ -7073,8 +6749,7 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
// Cilindro inviluppo della sfera // Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
} }
} }
@@ -7222,15 +6897,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ;
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true, if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) { ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ; AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
} }
if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true, if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) { ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ; AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
} }
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0, if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
@@ -7626,9 +7301,8 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
// Cilindro inviluppo della sfera // Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ; Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ; Vector3d vtN1, vtN2 ;
double dU1, dU2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) { AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
} }
} }
} }
+4 -22
View File
@@ -828,19 +828,10 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
Point3d ptTemp ; Point3d ptTemp ;
Vector3d vtDir ; Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir)) if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
continue ; return false ;
vtDir.Normalize() ; vtDir.Normalize() ;
// verifico che il punto non sia già stato trovato vResult.emplace_back( pt, vtDir) ;
bool bAdd = true ;
for ( int j = 0 ; j < ssize( vResult) ; j ++) {
if ( AreSamePointApprox( vResult[j].first, pt)) {
bAdd = false ;
break ;
}
}
if ( bAdd)
vResult.emplace_back( pt, vtDir) ;
} }
} }
@@ -1023,17 +1014,8 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ; RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// aggiungo la curva alla lista degli offset // aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) { if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
// forzo chiusura
if ( ! pCrvOffs->IsClosed()) {
Point3d ptS ; pCrvOffs->GetStartPoint( ptS) ;
Point3d ptE ; pCrvOffs->GetEndPoint( ptE) ;
if ( SqDist( ptS, ptE) > 100. * SQ_EPS_SMALL)
return false ;
pCrvOffs->Close() ;
}
OffsList.push_back( Release( pCrvOffs)) ; OffsList.push_back( Release( pCrvOffs)) ;
}
} }
// libero la memoria di vroni dedicata agli offset // libero la memoria di vroni dedicata agli offset
@@ -1173,7 +1155,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool bool
Voronoi::Translate( const Vector3d& vtMove) Voronoi::Translate( const Vector3d & vtMove)
{ {
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;