Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6be67258d2 | |||
| 6c76943bf4 | |||
| 9306f5be9d | |||
| 944ce79776 | |||
| 313c735956 | |||
| 007ed1701c | |||
| 7385709bb4 | |||
| da4cd4c482 | |||
| dee744725c | |||
| 2aca943de4 | |||
| 25f6bae120 | |||
| c92d841011 | |||
| 398c8c430a | |||
| 79dc8f8fc2 | |||
| 1545bc07cd | |||
| 44edef378a | |||
| 679efc22e8 | |||
| 1076dc54dc | |||
| e091f253d0 | |||
| 3206961b88 | |||
| 48b2029d19 | |||
| a2ca0ac6f7 | |||
| 4155dd3e5a | |||
| 5a3b7e311c | |||
| 991586a880 | |||
| de4165889a | |||
| 42c5ffb014 | |||
| e394615f84 | |||
| 1008ba4229 | |||
| f4328430b9 | |||
| 1d6bc847da | |||
| d76beb09ee | |||
| 026436b914 | |||
| ebc5fd7ee7 | |||
| 82a211753e | |||
| a258e9cb31 | |||
| 157885f71a | |||
| f227a9cba7 | |||
| 39360eefd7 | |||
| 6b5fb15c9b | |||
| 4e698d4049 | |||
| e20bd7fd0c | |||
| 7e62acf351 | |||
| 421bc2eb3b | |||
| db98fa5d5a | |||
| 5f28258d16 | |||
| 8f06488b33 | |||
| ac7ba1b12c | |||
| 67131a1482 | |||
| a92cba8697 | |||
| 52cca7233e | |||
| b2beed0fe0 | |||
| 1f301b6100 | |||
| c74ca4932f | |||
| fafcd67a2c | |||
| 390cc3bd8b | |||
| b2ccda1b34 | |||
| 69916e7756 | |||
| 3a7b6f1343 | |||
| 71a054749c | |||
| 06d87d5c52 | |||
| 6d544f93f4 | |||
| 3c1a7ff1bb | |||
| 73bedf4f55 | |||
| bae8d4651d | |||
| f9127ce64d | |||
| 86338db67d | |||
| 2438d1d23a | |||
| f790736fd7 | |||
| 985b69ae33 | |||
| 6faf5ccde2 | |||
| 2e129d7b06 | |||
| 2b7070e408 | |||
| 571a24b419 | |||
| 5f132ae3d3 | |||
| fe5a09281e | |||
| b66522de33 | |||
| e87ef178c2 | |||
| 0987496caf | |||
| 5ad9c48285 | |||
| ec6eb3e645 | |||
| 64c3363426 | |||
| 2023ba3f7d | |||
| 27c1823a54 | |||
| f111827545 | |||
| 7cdc1ba5a3 | |||
| 1d68a1ee8e | |||
| b426ccc04d | |||
| 6f7b614c3a | |||
| f02f29c543 | |||
| 06cfe1bb96 | |||
| 736353bbac | |||
| f4b3312672 | |||
| 3178bb5f27 | |||
| 552ce70231 | |||
| c2a79b2665 | |||
| f72c949563 | |||
| bdcb00d1bd | |||
| 42fcb1847b | |||
| a7b36280f3 | |||
| cdef3931be | |||
| d3f2587cc2 | |||
| d343f474e4 | |||
| b7fee9696e | |||
| 4f48337f62 | |||
| 96907d5952 | |||
| 3c5d2571fe | |||
| 7005bf43a4 | |||
| 4726cf4d35 | |||
| b971eda771 | |||
| 3ded6fe87d | |||
| 5195c23dfb | |||
| 5f1255a625 |
+2
-2
@@ -151,11 +151,11 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
else {
|
||||
double dParA = vIccInfo[i].IciA[0].dU ;
|
||||
double dParB = vIccInfo[i].IciB[0].dU ;
|
||||
if ( abs( dParA - dEnd) < EPS_SMALL)
|
||||
if ( dParA > dParB)
|
||||
swap( dParA, dParB) ;
|
||||
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile
|
||||
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
double dArea1 = 0, dArea2 = 0 ;
|
||||
if ( ! IsNull( pCrv1))
|
||||
pCrv1->GetAreaXY( dArea1) ;
|
||||
|
||||
@@ -140,16 +140,20 @@ MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
}
|
||||
else if ( dNewLenXY < dPrevLenXY) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
|
||||
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
|
||||
const SCollInfo& GetSCollInfo()
|
||||
{ return m_SCollInfo ;}
|
||||
|
||||
private :
|
||||
protected :
|
||||
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
|
||||
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
|
||||
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
|
||||
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
const Point3d& ptCen, double& dAng) ;
|
||||
|
||||
private :
|
||||
protected :
|
||||
const SurfFlatRegion* m_pRegM ;
|
||||
const SurfFlatRegion* m_pRegF ;
|
||||
SCollInfo m_SCollInfo ;
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 ;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 ; }
|
||||
} ;
|
||||
@@ -1,12 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2024
|
||||
// EgalTech 2020-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 23.01.26 Versione : 3.1a3
|
||||
// Contenuto : Implementazione funzione verifica collisione tra
|
||||
// SurfTm e SurfTm.
|
||||
//
|
||||
// Modifiche : 13.11.20 LM Creazione modulo.
|
||||
// 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -45,10 +46,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
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)
|
||||
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))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -61,13 +62,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
continue ;
|
||||
BBox3d 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)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR 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.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -84,14 +85,14 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// 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 ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
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))
|
||||
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) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -111,10 +112,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
}
|
||||
}
|
||||
// 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))
|
||||
return false ;
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
Point3d ptPointA, ptPointB ;
|
||||
pSrfA->GetFirstVertex( ptPointA) ;
|
||||
pSrfB->GetFirstVertex( ptPointB) ;
|
||||
@@ -127,7 +128,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist, bool bTestEnclosion)
|
||||
{
|
||||
// Recupero le superfici base
|
||||
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
|
||||
@@ -140,10 +141,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
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)
|
||||
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))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -156,13 +157,13 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
continue ;
|
||||
BBox3d 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)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR 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.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -179,14 +180,14 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// 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 ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
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))
|
||||
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) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -205,6 +206,25 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
pSrfB->SetTempInt( nTB, 1) ;
|
||||
}
|
||||
}
|
||||
// Non c'è interferenza
|
||||
// Se non richiesto test di inclusione, 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 ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 ;
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -179,3 +181,6 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP
|
||||
}
|
||||
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) ;
|
||||
+270
-65
@@ -722,7 +722,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv )
|
||||
AssignFeedSpiralOpt( int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv )
|
||||
{
|
||||
// controllo della curva corrente
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0)
|
||||
@@ -732,24 +732,24 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC
|
||||
if ( ! PockParams.bCalcFeed)
|
||||
return AssignMaxFeed( pCrv, PockParams) ;
|
||||
|
||||
switch ( PockParams.nType) {
|
||||
case POCKET_SPIRALIN :
|
||||
if ( nOptType == 0) { // Spirale dall'Esterno
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
|
||||
if ( u == 0) // prima circonferenza
|
||||
pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ;
|
||||
else // semi cerchi in tangenza
|
||||
pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ;
|
||||
}
|
||||
if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_CONFORMAL_ZIGZAG ||
|
||||
PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
|
||||
if ( nOptType == 0) { // Spirale dall'Esterno
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
|
||||
if ( u == 0) // prima circonferenza
|
||||
pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ;
|
||||
else // semi cerchi in tangenza
|
||||
pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ;
|
||||
}
|
||||
else if ( nOptType == 1) { // Trapezoidi
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
|
||||
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
else if ( nOptType == 1) { // Trapezoidi
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
|
||||
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
|
||||
}
|
||||
}
|
||||
/* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre
|
||||
orientate nello stesso modo, solamente alla fine viene invertita la curva finale per la svuotatura... */
|
||||
case POCKET_SPIRALOUT :
|
||||
else {
|
||||
if ( nOptType == 0) { // Spiral verso l'esterno
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
|
||||
if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze
|
||||
@@ -762,9 +762,6 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
|
||||
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
|
||||
}
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -1061,9 +1058,9 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa
|
||||
bool bInside = true ;
|
||||
bool bOkOut = true ;
|
||||
if ( PockParams.SfrLimit.IsValid()) {
|
||||
bOkOut = ( IsPointInsideSurfFr( ptFall, &PockParams.SfrLimit, dMinDist, bInside) && ! bInside) ;
|
||||
bOkOut = ( IsPointInsideSurfFr( ptFall, &PockParams.SfrLimit, dMinDist - 10. * EPS_SMALL, bInside) && ! bInside) ;
|
||||
if ( bOkOut)
|
||||
bOkOut = ( IsPointInsideSurfFr( Media( ptFall, pt), &PockParams.SfrLimit, dMinDist, bInside) && ! bInside) ;
|
||||
bOkOut = ( IsPointInsideSurfFr( Media( ptFall, pt), &PockParams.SfrLimit, dMinDist - 10. * EPS_SMALL, bInside) && ! bInside) ;
|
||||
}
|
||||
if ( bOkOut)
|
||||
bOkOut = ( IsPointInsideSurfFr( ptFall, pSfr, dMinDist, bInside) && ! bInside) ;
|
||||
@@ -2638,6 +2635,100 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& PockParam,
|
||||
int nBase, int nSecondBase, bool& bForced)
|
||||
{
|
||||
bForced = false ;
|
||||
// se la curva non è valida, allora non può essere forzato
|
||||
if ( pCrvTrap == nullptr || ! pCrvTrap->IsValid())
|
||||
return false ;
|
||||
|
||||
// scorro la curva e ricavo le TempProps
|
||||
array<int, 4> vnProps ;
|
||||
int nClose = 0 ;
|
||||
for ( int i = 0 ; i < 4 ; ++ i) {
|
||||
if ( ! pCrvTrap->GetCurveTempProp( i, vnProps[i], 0))
|
||||
return false ;
|
||||
if ( vnProps[i] == TEMP_PROP_CLOSE_EDGE)
|
||||
++ nClose ;
|
||||
}
|
||||
|
||||
double dDiam = 2. * PockParam.dRad ;
|
||||
switch ( nClose) {
|
||||
// se trapezio tutto aperto, allora non è forzato
|
||||
case 0 :
|
||||
bForced = false ;
|
||||
break ;
|
||||
// se ho un lato chiuso, non è forzato
|
||||
case 1 :
|
||||
bForced = false ;
|
||||
break ;
|
||||
// se ho due lati chiusi
|
||||
case 2 : {
|
||||
if ( nBase < 0 || nBase > 4 || nSecondBase < 0 || nSecondBase > 4)
|
||||
return false ;
|
||||
// se entrambe le basi sono chiuse, è forzato
|
||||
if ( vnProps[nBase] == TEMP_PROP_CLOSE_EDGE && vnProps[nSecondBase] == TEMP_PROP_CLOSE_EDGE)
|
||||
bForced = true ;
|
||||
// se entrambe le basi sono aperte
|
||||
else if ( vnProps[nBase] == TEMP_PROP_OPEN_EDGE && vnProps[nSecondBase] == TEMP_PROP_OPEN_EDGE) {
|
||||
const ICurve* pCrvOpenBase = pCrvTrap->GetCurve( nBase) ;
|
||||
const ICurve* pCrvOpenSecondBase = pCrvTrap->GetCurve( nSecondBase) ;
|
||||
if ( pCrvOpenBase == nullptr || ! pCrvOpenBase->IsValid() ||
|
||||
pCrvOpenSecondBase == nullptr || ! pCrvOpenSecondBase->IsValid())
|
||||
return false ;
|
||||
double dLenOpenBase ; pCrvOpenBase->GetLength( dLenOpenBase) ;
|
||||
double dLenSecondOpenBase ; pCrvOpenSecondBase->GetLength( dLenSecondOpenBase) ;
|
||||
bForced = ( dLenOpenBase < dDiam + 10. * EPS_SMALL &&
|
||||
dLenSecondOpenBase < dDiam + 10. * EPS_SMALL) ;
|
||||
}
|
||||
// se alternate, non forzo
|
||||
else
|
||||
bForced = false ;
|
||||
}
|
||||
break ;
|
||||
// se ho tre lati chiusi
|
||||
case 3 : {
|
||||
// diventa forzato se il lato aperto non ha una componente perpendicolare grande rispetto al chiuso precedente e successivo
|
||||
double dLenOpen = 0. ;
|
||||
for ( int i = 0 ; i < 4 ; ++ i) {
|
||||
if ( vnProps[i] == TEMP_PROP_OPEN_EDGE) {
|
||||
const ICurve* pCrvOpen = pCrvTrap->GetCurve( i) ;
|
||||
if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid())
|
||||
return false ;
|
||||
// essendo nei casi a trapezio, ho solo segmenti
|
||||
pCrvOpen->GetLength( dLenOpen) ;
|
||||
Vector3d vtDir ; pCrvOpen->GetStartDir( vtDir) ;
|
||||
vtDir *= dLenOpen ;
|
||||
const ICurve* pCrvClosePrev = pCrvTrap->GetCurve( ( i == 0 ? 3 : i - 1)) ;
|
||||
if ( pCrvClosePrev == nullptr || ! pCrvClosePrev->IsValid())
|
||||
return false ;
|
||||
const ICurve* pCrvCloseAft = pCrvTrap->GetCurve( ( i == 3 ? 0 : i + 1)) ;
|
||||
if ( pCrvCloseAft == nullptr || ! pCrvCloseAft->IsValid())
|
||||
return false ;
|
||||
// essendo un trapezio queste due direzioni me le apsetto parallele tra loro
|
||||
Vector3d vtDirPrev ; pCrvClosePrev->GetEndDir( vtDirPrev) ;
|
||||
Vector3d vtDirAft ; pCrvCloseAft->GetStartDir( vtDirAft) ;
|
||||
dLenOpen = min( { OrthoCompo( vtDir, vtDirPrev).Len(), OrthoCompo( vtDir, vtDirAft).Len(), dLenOpen}) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
bForced = ( dLenOpen < dDiam + 10. * EPS_SMALL) ;
|
||||
}
|
||||
break ;
|
||||
// se tutto chiuso, è forzato
|
||||
case 4 :
|
||||
bForced = true ;
|
||||
break ;
|
||||
default :
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTrap,
|
||||
@@ -3040,8 +3131,12 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr
|
||||
return false ;
|
||||
|
||||
// se parametro MaxOptSize non compatibile => non è ottimizzato
|
||||
if ( PockParams.dMaxOptSize > EPS_SMALL && dPocketSize > PockParams.dMaxOptSize)
|
||||
pCrvTrap->Clear() ;
|
||||
bool bForced = false ;
|
||||
IsForcedStepTrapezoid( pCrvTrap, PockParams, nBase, nSecondBase, bForced) ;
|
||||
if ( ! bForced) {
|
||||
if ( PockParams.dMaxOptSize > EPS_SMALL && dPocketSize > PockParams.dMaxOptSize)
|
||||
pCrvTrap->Clear() ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -3444,18 +3539,18 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
|
||||
Vector3d vtX ; pCrvPocket->GetCurve( 1)->GetStartDir( vtX) ;
|
||||
Frame3d frDim ; frDim.Set( ptOrig, Z_AX, vtX) ; frDim.Invert() ;
|
||||
BBox3d b3Dim ; pCrvPocket->GetBBox( frDim, b3Dim, BBF_EXACT) ;
|
||||
dMaxLarg = ( vnProp[0] != 0 ? b3Dim.GetDimY() : dPocketSize) ;
|
||||
dMaxLarg = ( vnProp[0] != TEMP_PROP_CLOSE_EDGE ? b3Dim.GetDimY() : dPocketSize) ;
|
||||
}
|
||||
|
||||
// calcolo percorso di svuotatura
|
||||
// se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale
|
||||
if ( ( bRealTrap && dMaxLarg > PockParams.dRad * 2 + 10 * EPS_SMALL) &&
|
||||
if ( ( bRealTrap && dMaxLarg > dDiam + 10. * EPS_SMALL) &&
|
||||
( ( ( vnProp[0] != TEMP_PROP_CLOSE_EDGE && vnProp[2] != TEMP_PROP_CLOSE_EDGE) &&
|
||||
( vnProp[3] == TEMP_PROP_CLOSE_EDGE && vnProp[1] == TEMP_PROP_CLOSE_EDGE) &&
|
||||
( max( dLen0, dLen2) < 2 * dDiam + EPS_SMALL)) ||
|
||||
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)) ||
|
||||
( ( vnProp[1] != TEMP_PROP_CLOSE_EDGE && vnProp[3] != TEMP_PROP_CLOSE_EDGE) &&
|
||||
( vnProp[0] == TEMP_PROP_CLOSE_EDGE && vnProp[2] == TEMP_PROP_CLOSE_EDGE) &&
|
||||
( max( dLen1, dLen3) < 2 * dDiam + EPS_SMALL)))) {
|
||||
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)))) {
|
||||
if ( ! SpecialAdjustTrapezoidSpiralForAngles( pMCrv, ( vnProp[0] == TEMP_PROP_CLOSE_EDGE), pCrvPocket, PockParams, ptRef)) {
|
||||
pMCrv->Clear() ;
|
||||
return false ;
|
||||
@@ -3608,14 +3703,8 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
|
||||
|
||||
if ( pMCrv->GetCurveCount() == 0)
|
||||
return true ;
|
||||
|
||||
pMCrv->ToGlob( frTrap) ;
|
||||
|
||||
if ( PockParams.bInvert) {
|
||||
pMCrv->Invert() ;
|
||||
// inverto le proprietà in modo che nProp3 sia sempre legata al punto iniziale e nProp1 a quello finale
|
||||
swap( vnProp[1], vnProp[3]) ;
|
||||
}
|
||||
// segno i lati aperti come temp prop della curva
|
||||
int nOpenEdges = vnProp[0] + vnProp[1] * 2 + vnProp[2] * 4 + vnProp[3] * 8 ;
|
||||
pMCrv->SetTempProp( nOpenEdges, 0) ;
|
||||
@@ -3625,6 +3714,112 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam,
|
||||
const ISurfFlatRegion* pSfrChunk)
|
||||
{
|
||||
// recupero la TempProp
|
||||
int nTmpProp = pCrvRes->GetTempProp( 0) ;
|
||||
// se esiste almeno un aperto
|
||||
if ( nTmpProp > 0) {
|
||||
// se solo lato3 aperto
|
||||
bool bCheckHead = ( nTmpProp != 8 && nTmpProp != 2) ;
|
||||
if ( nTmpProp == 2)
|
||||
pCrvRes->Invert() ; // entro dall'unico aperto
|
||||
if ( bCheckHead) {
|
||||
// recupero gli estremi della curva corrente e la inverto in base alla Testa
|
||||
Point3d ptS ; pCrvRes->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrvRes->GetEndPoint( ptE) ;
|
||||
Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ;
|
||||
Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ;
|
||||
if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) ||
|
||||
( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z))
|
||||
pCrvRes->Invert() ;
|
||||
}
|
||||
}
|
||||
|
||||
// Assegno la Feed
|
||||
AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ;
|
||||
// Se curva da invertire, inverto
|
||||
if ( PockParam.bInvert)
|
||||
pCrvRes->Invert() ;
|
||||
|
||||
// se esiste almeno un aperto, provo ad estendere il percorso
|
||||
if ( nTmpProp > 0) {
|
||||
// Calcolo eventuale entrata da fuori
|
||||
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsStartExtended = false ;
|
||||
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam,
|
||||
ICurveComposite* pCrvRes)
|
||||
{
|
||||
// controllo dei parametri
|
||||
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
|
||||
return false ;
|
||||
pCrvRes->Clear() ;
|
||||
|
||||
// ricavo la curva di bordo del chunk corrente
|
||||
PtrOwner<ICurveComposite> pCrvBorder( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ;
|
||||
if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid())
|
||||
return false ;
|
||||
pCrvBorder->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ;
|
||||
pCrvBorder->SetExtrusion( pSfrChunk->GetNormVersor()) ;
|
||||
|
||||
/* TRAPEZI
|
||||
- E' richiesto che una dimensione del box della curva sia compatibile con il primo Offset, il
|
||||
quale sarebbe una singola curva aperta
|
||||
*/
|
||||
PtrOwner<ICurveComposite> pCrvTrap( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvTrap))
|
||||
return false ;
|
||||
Frame3d frTrap ;
|
||||
double dPocketSize ;
|
||||
int nBase, nSecondBase ;
|
||||
bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ;
|
||||
if ( bOkTrap && pCrvTrap->IsValid()) {
|
||||
// verifico se il trapezio ottenuto deve o meno rispettare il SideStep
|
||||
bool bForcedTrap = false ;
|
||||
IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ;
|
||||
if ( ! bForcedTrap)
|
||||
bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
|
||||
}
|
||||
if ( bOkTrap && pCrvTrap->IsValid()) {
|
||||
pCrvTrap->SetExtrusion( Z_AX) ;
|
||||
CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ;
|
||||
if ( bOkTrap) {
|
||||
// verifico che tale curva non interferisca con la regione limite
|
||||
if ( PockParam.SfrLimit.IsValid()) {
|
||||
double dOffsCheck = PockParam.dRad + PockParam.dRadialOffset - 50. * EPS_SMALL ; // restrittivo per sicurezza
|
||||
PtrOwner<ISurfFlatRegion> pSfrToolShape( GetSurfFlatRegionFromFatCurve( pCrvRes->Clone(), dOffsCheck, false, false)) ;
|
||||
bOkTrap = ( ! IsNull( pSfrToolShape) && pSfrToolShape->IsValid()) ;
|
||||
if ( bOkTrap) {
|
||||
bOkTrap = ( pSfrToolShape->Intersect( PockParam.SfrLimit) &&
|
||||
! pSfrToolShape->IsValid()) ;
|
||||
if ( ! bOkTrap)
|
||||
pCrvRes->Clear() ;
|
||||
}
|
||||
}
|
||||
if ( bOkTrap) {
|
||||
AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ;
|
||||
// imposto il flag di curva singola
|
||||
pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam,
|
||||
@@ -3673,7 +3868,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
|
||||
ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_OUT) ;
|
||||
// NB. una versione più complessa dovrebbe verificare se la sottrazione tra la
|
||||
// superficie dell'utensile e la regione limite non genera un'altra circonferenza...
|
||||
// In questo caso si la sottrazione potrebbe essere trattata come una circonferenza
|
||||
// In questo caso la sottrazione potrebbe essere trattata come una circonferenza
|
||||
// chiusa ed essere ancora svotata a spirale...
|
||||
}
|
||||
}
|
||||
@@ -3714,8 +3909,14 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
|
||||
Frame3d frTrap ;
|
||||
double dPocketSize ;
|
||||
int nBase, nSecondBase ;
|
||||
bool bOkTrap = ( GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) &&
|
||||
dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
|
||||
bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ;
|
||||
if ( bOkTrap && pCrvTrap->IsValid()) {
|
||||
// verifico se il trapezio ottenuto deve o meno rispettare il SideStep
|
||||
bool bForcedTrap = false ;
|
||||
IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ;
|
||||
if ( ! bForcedTrap)
|
||||
bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
|
||||
}
|
||||
if ( bOkTrap && pCrvTrap->IsValid()) {
|
||||
pCrvTrap->SetExtrusion( Z_AX) ;
|
||||
CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ;
|
||||
@@ -3733,20 +3934,9 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
|
||||
}
|
||||
}
|
||||
if ( bOkTrap) {
|
||||
// calcolo eventuali uscite e ingressi
|
||||
if ( pCrvRes->GetTempProp( 0) > 0) {
|
||||
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsStartExtended = false ;
|
||||
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
|
||||
return false ;
|
||||
pCrvRes->GetEndDir( vtRef) ;
|
||||
bool bIsEndExtended = false ;
|
||||
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, PockParam.dRad + PockParam.dOpenMinSafe, bIsEndExtended))
|
||||
return false ;
|
||||
if ( bIsEndExtended && ! bIsStartExtended)
|
||||
pCrvRes->Invert() ;
|
||||
}
|
||||
AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ;
|
||||
// imposto il flag di curva singola
|
||||
pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3789,23 +3979,31 @@ GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockPara
|
||||
PockParam.nType == POCKET_CONFORMAL_ZIGZAG || PockParam.nType == POCKET_CONFORMAL_ONEWAY) {
|
||||
// curva da resituire
|
||||
PtrOwner<ICurveComposite> pCrvOptSpiral( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvOptSpiral) ||
|
||||
! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral))
|
||||
if ( IsNull( pCrvOptSpiral) ||
|
||||
! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral))
|
||||
return false ;
|
||||
// se ho ricavato una curva ottimizzata
|
||||
if ( ! IsNull( pCrvOptSpiral) && pCrvOptSpiral->IsValid() && pCrvOptSpiral->GetCurveCount() > 0) {
|
||||
vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ;
|
||||
vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ;
|
||||
pSfr->EraseChunk( nCurrChunk) ;
|
||||
}
|
||||
else
|
||||
++ nCurrChunk ;
|
||||
}
|
||||
else if ( PockParam.nType == POCKET_ZIGZAG || PockParam.nType == POCKET_ONEWAY) {
|
||||
// curva da restituire
|
||||
PtrOwner<ICurveComposite> pCrvOptZigZag( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvOptZigZag) ||
|
||||
! GetZigZagOptimizedCurves( pSfrChunk, PockParam, pCrvOptZigZag))
|
||||
return false ;
|
||||
// se ho ricavato una curva ottimizzata
|
||||
if ( ! IsNull( pCrvOptZigZag) && pCrvOptZigZag->IsValid() && pCrvOptZigZag->GetCurveCount() > 0) {
|
||||
vCrvOptCurves.emplace_back( Release( pCrvOptZigZag)) ;
|
||||
pSfr->EraseChunk( nCurrChunk) ;
|
||||
}
|
||||
else
|
||||
++ nCurrChunk ;
|
||||
}
|
||||
// else if ( PockParam.nType == POCKET_ZIGZAG)
|
||||
// ;
|
||||
// else if ( PockParam.nType == POCKET_ONEWAY)
|
||||
// ;
|
||||
// else if ( PockParam.nType == POCKET_CONFORMAL_ONEWAY || PockParam.nType == POCKET_CONFORMAL_ZIGZAG)
|
||||
// ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -6044,6 +6242,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
// ricavo le regioni progressive
|
||||
double dOffsPrec = 0. ;
|
||||
int nCrvFirstOffs = 0 ;
|
||||
bool bLastNotValid = false ;
|
||||
while ( nIter < MAX_ITER) {
|
||||
// Offset della regione attuale
|
||||
PtrOwner<ISurfFlatRegion> pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ;
|
||||
@@ -6054,6 +6253,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ;
|
||||
if ( IsNull( pSfrOffsVR))
|
||||
return false ;
|
||||
bLastNotValid = true ;
|
||||
}
|
||||
|
||||
// se primo Offset
|
||||
@@ -6085,6 +6285,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
bool bInsert = true ;
|
||||
if ( ! CheckIfOffsetIsNecessary( pSrfAct, pCrvCompoBorder, dOffs, dOffsPrec, nIter, PockParams, bInsert))
|
||||
return false ;
|
||||
// per evitare di allacciare una curva di regione non svuotata alla prima curva di Offset
|
||||
// ( quindi avere un entrata nel pieno del grezzo) controllo di non eliminare il secondo Offset
|
||||
if ( ! bInsert && nChunks == 1 && bLastNotValid)
|
||||
bInsert = true ;
|
||||
if ( bInsert) {
|
||||
// imposto come secondo TempParam il Side di classificazione
|
||||
pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ;
|
||||
@@ -8901,14 +9105,14 @@ CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams&
|
||||
// il tipo può essere solo SpiralIn o SpiralOut
|
||||
if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT)
|
||||
return false ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrLimit( PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion()) ;
|
||||
// calcolo il percorso di svuotatura spiral
|
||||
return ( CalcPocketing( pSfr, PockParams.dRad, PockParams.dRadialOffset, PockParams.dSideStep,
|
||||
PockParams.dAngle, PockParams.dOpenMinSafe, nType, PockParams.bSmooth,
|
||||
PockParams.bCalcUnclearedRegs, PockParams.bInvert, PockParams.bAvoidOpt,
|
||||
PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart,
|
||||
PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion(),
|
||||
PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, PockParams.nLiType,
|
||||
vCrvCompoRes)) ;
|
||||
pSfrLimit, PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang,
|
||||
PockParams.nLiType, vCrvCompoRes)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -9203,9 +9407,10 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
|
||||
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
|
||||
bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs,
|
||||
double dMaxOptSize, double dLiTang, int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
|
||||
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt,
|
||||
bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec,
|
||||
const ISurfFlatRegion* pSfrLimit, bool bAllOffs, double dMaxOptSize, double dLiTang,
|
||||
int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
|
||||
{
|
||||
// controllo dei parametri
|
||||
if ( pSfr == nullptr || ! pSfr->IsValid() ||
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -168,7 +169,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
|
||||
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
|
||||
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
|
||||
// verifico se sono arrivato al punto di chiusura
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) {
|
||||
bStopped = true ;
|
||||
break ;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ static const NamedColor StdColor[] = {
|
||||
{ "FUCHSIA", FUCHSIA},
|
||||
{ "PURPLE", PURPLE},
|
||||
{ "ORANGE", ORANGE},
|
||||
{ "BROWN", BROWN}
|
||||
{ "BROWN", BROWN},
|
||||
{ "INVISIBLE", INVISIBLE}
|
||||
} ;
|
||||
static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ;
|
||||
|
||||
|
||||
+413
-52
@@ -13,6 +13,8 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "Bernstein.h"
|
||||
#include "CurveAux.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
@@ -23,12 +25,22 @@
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkCurveByInterp.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
#define SAVEAPPROX 0
|
||||
#define SAVECURVEPASSED 0
|
||||
#define SAVELINEARAPPROX 0
|
||||
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX
|
||||
static int nCrvPassed = 0 ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ;
|
||||
@@ -522,9 +534,9 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
|
||||
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
|
||||
pCrvBezier->Init( nDeg, true) ;
|
||||
pCrvBezier->FromLine( *pCrvLine) ;
|
||||
pCrvBezier->Init( nDeg, false) ;
|
||||
if ( ! pCrvBezier->FromLine( *pCrvLine))
|
||||
return nullptr ;
|
||||
if ( bMakeRatOrNot)
|
||||
pCrvBezier->MakeRational() ;
|
||||
return Release( pCrvBezier) ;
|
||||
@@ -577,6 +589,13 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot)
|
||||
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
|
||||
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc))
|
||||
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
|
||||
while ( pCrvBez->GetDegree() < nDeg)
|
||||
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
|
||||
@@ -1135,7 +1154,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
|
||||
return true ;
|
||||
}
|
||||
// trovo a quale span appartiene il parametro dU
|
||||
int nKnots = int( vKnots.size()) ;
|
||||
int nKnots = ssize( vKnots) ;
|
||||
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
|
||||
nSpan = nKnots - 1 - nDeg ;
|
||||
return true ;
|
||||
@@ -1161,7 +1180,7 @@ static bool
|
||||
CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
||||
{
|
||||
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
|
||||
if ( vBasis.size() != nDeg + 1)
|
||||
if ( ssize( vBasis) != nDeg + 1)
|
||||
return false ;
|
||||
|
||||
vBasis[0] = 1 ;
|
||||
@@ -1186,7 +1205,8 @@ CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTO
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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 ;
|
||||
|
||||
@@ -1215,6 +1235,8 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
bool bUseStartEndDir = vtStartDir.IsValid() && vtEndDir.IsValid() ;
|
||||
|
||||
DBLVECTOR vPntParam ;
|
||||
vPntParam.resize( nPoints) ;
|
||||
vPntParam[0] = 0 ;
|
||||
@@ -1223,13 +1245,15 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
|
||||
vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ;
|
||||
|
||||
DBLVECTOR vKnots ;
|
||||
vKnots.resize( nPoints + nDeg - 1) ;
|
||||
int nKnots = bUseStartEndDir ? nPoints + nDeg - 1 + 2 : nPoints + nDeg - 1 ;
|
||||
vKnots.resize( nKnots) ;
|
||||
for ( int i = 0 ; i < nDeg ; ++i) {
|
||||
vKnots[i] = 0 ;
|
||||
vKnots.end()[-i-1] = 1 ;
|
||||
}
|
||||
|
||||
for ( int i = nDeg ; i < nPoints - 1 ; ++i) {
|
||||
int nKnotsToEdit = bUseStartEndDir ? nPoints + 1 : nPoints - 1 ;
|
||||
for ( int i = nDeg ; i < nKnotsToEdit ; ++i) {
|
||||
double dKnot = 0 ;
|
||||
for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j)
|
||||
dKnot += vPntParam[j - nDeg] ;
|
||||
@@ -1237,13 +1261,14 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart,
|
||||
vKnots[i] = dKnot ;
|
||||
}
|
||||
|
||||
Eigen::MatrixXd mA( nPoints, nPoints) ;
|
||||
int nEq = bUseStartEndDir ? nPoints + 2 : nPoints ;
|
||||
Eigen::MatrixXd mA( nEq, nEq) ;
|
||||
mA.fill( 0) ;
|
||||
for ( int i = 0 ; i < nPoints ; ++i) {
|
||||
for ( int i = 0 ; i < nEq ; ++i) {
|
||||
if ( i == 0)
|
||||
mA.row(0).col(0) << 1 ;
|
||||
else if ( i == nPoints - 1)
|
||||
mA.row(i).col(nPoints - 1) << 1 ;
|
||||
else if ( i == nEq - 1)
|
||||
mA.row(i).col( nEq - 1) << 1 ;
|
||||
else {
|
||||
int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ;
|
||||
DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ;
|
||||
@@ -1294,7 +1319,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
|
||||
int nItCount = 0 ;
|
||||
while ( dErr > dLinTol && nItCount < 10) {
|
||||
pCrvInt->Clear() ;
|
||||
int nPoints = int( vPnt.size()) ;
|
||||
int nPoints = ssize( vPnt) ;
|
||||
int nDeg = 3 ;
|
||||
if ( nPoints < 2)
|
||||
return nullptr ;
|
||||
@@ -1310,7 +1335,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
|
||||
else if ( nPoints == 3) {
|
||||
// se ho solo tre punti uso un altro algoritmo
|
||||
CurveByInterp cbi ;
|
||||
for ( int i = 0 ; i < int( vPnt.size()) ; ++i)
|
||||
for ( int i = 0 ; i < ssize( vPnt) ; ++i)
|
||||
cbi.AddPoint( vPnt[i]) ;
|
||||
pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ;
|
||||
if ( ! IsNull( pCrvInt) && pCrvInt->IsValid())
|
||||
@@ -1342,10 +1367,16 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
|
||||
}
|
||||
}
|
||||
|
||||
if ( vLen.size() != 0) {
|
||||
if ( ! vLen.empty()) {
|
||||
if ( nEnd == 0)
|
||||
nEnd = nPoints - 1 ;
|
||||
pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot)) ;
|
||||
Vector3d vtStartDir = V_INVALID ;
|
||||
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) {
|
||||
@@ -1357,6 +1388,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
|
||||
nStart = nEnd ;
|
||||
}
|
||||
|
||||
//dErr = 0 ;
|
||||
CalcApproxError( pCrvOri, pCrvInt, dErr) ;
|
||||
if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL)
|
||||
dMaxLen /= 2 ;
|
||||
@@ -1371,42 +1403,318 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
|
||||
static bool
|
||||
ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
|
||||
{
|
||||
PolyLine plApprox ;
|
||||
double dAngTolFine = 2 ;
|
||||
pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ;
|
||||
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 ;
|
||||
|
||||
PNTVECTOR vPnt ;
|
||||
Point3d pt ; plApprox.GetFirstPoint( pt) ;
|
||||
do {
|
||||
vPnt.push_back( pt) ;
|
||||
} while ( plApprox.GetNextPoint( pt)) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// campiono punti lungo la curva e poi li interpolo
|
||||
//----------------------------------------------------------------------------
|
||||
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) ;
|
||||
|
||||
PtrOwner<ICurve> pCC( InterpolatePointSetWithBezier( vPnt, dTol, 100)) ;
|
||||
if ( ! IsNull( pCC) && pCC->IsValid())
|
||||
return Release( pCC) ;
|
||||
else
|
||||
return nullptr ;
|
||||
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*
|
||||
ApproxPointSetWithBezier( const ICurve* pCrv, double dTol)
|
||||
FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
|
||||
int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol, bool bLimitSplit = false)
|
||||
{
|
||||
// campiono punti lungo la curva e poi li interpolo
|
||||
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.) ;
|
||||
}
|
||||
}
|
||||
|
||||
PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ;
|
||||
return Release( pCC) ;
|
||||
// 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)
|
||||
{
|
||||
|
||||
#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 ;
|
||||
double dAngTolFine = 1 ;
|
||||
double dLinTolFine = 0.05 ;
|
||||
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 vPntOverSampling ;
|
||||
Point3d pt ; plApprox.GetFirstPoint( pt) ;
|
||||
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) ;
|
||||
} while ( plApprox.GetNextPoint( pt)) ;
|
||||
|
||||
// calcolo la curvatura nei vari punti per identificare zone a curvatura costante
|
||||
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) ;
|
||||
DBLVECTOR vParam( nPoints) ;
|
||||
int nFirst = 0 ;
|
||||
int nLast = ssize( vPnt) - 1 ;
|
||||
ParamByLen( vPnt, vParam, nFirst, nLast) ;
|
||||
|
||||
VCT3DVECTOR vPrevDer ;
|
||||
VCT3DVECTOR vNextDer ;
|
||||
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
|
||||
|
||||
int nOverSampling = ssize( vPntOverSampling) ;
|
||||
vParam.resize( nOverSampling) ;
|
||||
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
|
||||
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
|
||||
double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ;
|
||||
double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ;
|
||||
@@ -1488,7 +1796,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
{
|
||||
// se con nodi extra
|
||||
if ( cnData.bExtraKnotes) {
|
||||
int nKnotesNbr = int( cnData.vU.size()) ;
|
||||
int nKnotesNbr = ssize( cnData.vU) ;
|
||||
if ( nKnotesNbr < 4)
|
||||
return false ;
|
||||
cnData.bExtraKnotes = false ;
|
||||
@@ -1502,7 +1810,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
bool bAlreadyChecked = false ;
|
||||
// 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
|
||||
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
|
||||
if ( cnData.bPeriodic && ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1)) {
|
||||
bool bRepeated = true ;
|
||||
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
|
||||
if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) {
|
||||
@@ -1511,11 +1819,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
}
|
||||
}
|
||||
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
|
||||
DBLVECTOR vU = cnData.vU ;
|
||||
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
|
||||
if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) {
|
||||
if ( ssize( cnData.vU) > ssize( cnData.vCP) + 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
|
||||
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
|
||||
bFirstAddedAtEnd = true ;
|
||||
@@ -1527,11 +1835,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
|
||||
// controllo eventualmente anche i nodi extra
|
||||
// se ne ho due in più ne tolgo uno in cima e uno in fondo
|
||||
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
|
||||
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
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
|
||||
}
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) {
|
||||
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) {
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
||||
}
|
||||
}
|
||||
@@ -1558,7 +1866,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
// recupero il vettore dei nodi
|
||||
cnData.vU = vU ;
|
||||
// verifico se ho nodi extra
|
||||
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
|
||||
if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1 ) {
|
||||
// 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
|
||||
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
|
||||
@@ -1569,7 +1877,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
|
||||
}
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
|
||||
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg)
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
||||
}
|
||||
bAlreadyChecked = true ;
|
||||
@@ -1594,7 +1902,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
|
||||
bool bCollapsed = true ;
|
||||
Point3d ptFirst = cnData.vCP.front() ;
|
||||
for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
|
||||
for ( int i = 1 ; i < ssize( cnData.vCP) ; ++i) {
|
||||
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
|
||||
bCollapsed = false ;
|
||||
break ;
|
||||
@@ -1611,7 +1919,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
// 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
|
||||
int nCP = int( cnData.vCP.size()) ;
|
||||
int nCP = ssize( cnData.vCP) ;
|
||||
int nU = nCP + cnData.nDeg - 1 ;
|
||||
int nDeg = cnData.nDeg ;
|
||||
PNTVECTOR vBC ;
|
||||
@@ -1807,9 +2115,9 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
if ( cnData.bPeriodic || cnData.bExtraKnotes)
|
||||
return nullptr ;
|
||||
// numero dei nodi
|
||||
int nU = int( cnData.vCP.size()) + cnData.nDeg - 1 ;
|
||||
int nU = ssize( cnData.vCP) + cnData.nDeg - 1 ;
|
||||
// controllo relazione nodi - punti di controllo
|
||||
if ( nU != int( cnData.vU.size()))
|
||||
if ( nU != ssize( cnData.vU))
|
||||
return nullptr ;
|
||||
// numero degli intervalli
|
||||
int nInt = nU - 2 * cnData.nDeg + 1 ;
|
||||
@@ -2179,7 +2487,7 @@ CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, in
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
|
||||
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
|
||||
return false ;
|
||||
}
|
||||
@@ -2206,7 +2514,7 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
|
||||
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
|
||||
return false ;
|
||||
}
|
||||
@@ -2267,7 +2575,7 @@ bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, doubl
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
@@ -2297,7 +2605,7 @@ bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, do
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
@@ -2326,3 +2634,56 @@ ResetCurveVoronoi( const ICurve& crvC)
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -35,3 +35,4 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
|
||||
+3
-4
@@ -275,20 +275,19 @@ CurveBezier::FromLine( const ICurveLine& crLine)
|
||||
{
|
||||
if ( m_nStatus != OK || ! crLine.IsValid())
|
||||
return false ;
|
||||
double dWeight = 1 ;
|
||||
int nCount = 0 ;
|
||||
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
|
||||
SetControlPoint( nCount, ptStart, dWeight) ;
|
||||
SetControlPoint( nCount, ptStart) ;
|
||||
++nCount ;
|
||||
double dPart = 1. / m_nDeg ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
double dU = i * dPart ;
|
||||
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
|
||||
SetControlPoint( nCount, ptMid, dWeight) ;
|
||||
SetControlPoint( nCount, ptMid) ;
|
||||
++nCount ;
|
||||
}
|
||||
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
|
||||
SetControlPoint( nCount, ptEnd, dWeight) ;
|
||||
SetControlPoint( nCount, ptEnd) ;
|
||||
++nCount ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+2
-201
@@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void)
|
||||
bool
|
||||
CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// 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 ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByApprox::CalcBesselTangents( void)
|
||||
{
|
||||
// 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 ;
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+35
-236
@@ -50,12 +50,42 @@ CurveByInterp::AddPoint( const Point3d& ptP)
|
||||
ICurve*
|
||||
CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
{
|
||||
// calcolo le tangenti
|
||||
// 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)) ;
|
||||
//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 ( ! CalcBesselTangents())
|
||||
return nullptr ;
|
||||
}
|
||||
else if ( nType != CUBIC_BEZIERS_LONG) {
|
||||
else {
|
||||
if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER))
|
||||
return nullptr ;
|
||||
}
|
||||
@@ -103,16 +133,6 @@ CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -120,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
bool
|
||||
CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// 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 ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByInterp::CalcBesselTangents( void)
|
||||
{
|
||||
// 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 ;
|
||||
}
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
+15
-2
@@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
|
||||
vtDiff = ptQ - ptP ;
|
||||
// angolo tra vettore e tangente
|
||||
dTemp = vtDer1 * vtDiff ;
|
||||
bool bEquiverse = dTemp > 0 ;
|
||||
if ( abs( dTemp) > EPS_ZERO)
|
||||
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
|
||||
else
|
||||
@@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
|
||||
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
|
||||
dPrevPar = dPar ;
|
||||
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ;
|
||||
if ( abs( dTemp) > EPS_ZERO)
|
||||
dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ;
|
||||
|
||||
// se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale
|
||||
// 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
|
||||
if ( dPar < approxMin.dParMin) {
|
||||
if ( approxMin.bParMinSing && ! bClampedFromSing) {
|
||||
|
||||
+12
-1
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
|
||||
// distanza non calcolata
|
||||
m_dDist = - 1 ;
|
||||
|
||||
if ( &CrvBez == nullptr || ! CrvBez.IsValid())
|
||||
if ( ! CrvBez.IsValid())
|
||||
return ;
|
||||
|
||||
// determino tolleranza di approssimazione in base a ingombro curva
|
||||
@@ -42,6 +42,17 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
|
||||
if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
|
||||
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
|
||||
MDCVECTOR vApproxMin ;
|
||||
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
|
||||
|
||||
+5
-5
@@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide) const
|
||||
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const
|
||||
{
|
||||
if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size())
|
||||
return false ;
|
||||
|
||||
// se distanza nulla, il punto giace sulla curva
|
||||
if ( m_dDist <= EPS_SMALL) {
|
||||
if ( m_dDist <= dTol) {
|
||||
nSide = MDS_ON ;
|
||||
return true ;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
|
||||
// determino il lato di giacitura del punto
|
||||
double dSide = vtRef * ( m_ptP - ptQ) ;
|
||||
if ( abs( dSide) < EPS_SMALL)
|
||||
if ( abs( dSide) < dTol)
|
||||
nSide = MDS_ON ;
|
||||
else if ( dSide > 0)
|
||||
nSide = MDS_LEFT ;
|
||||
@@ -270,7 +270,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide) const
|
||||
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const
|
||||
{
|
||||
if ( m_dDist < 0 || m_Info.empty())
|
||||
return false ;
|
||||
@@ -286,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
|
||||
}
|
||||
}
|
||||
// mi sono ricondotto al caso precedente
|
||||
return GetSideAtMinDistPoint( nInd, vtN, nSide) ;
|
||||
return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+11
-10
@@ -23,10 +23,10 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
|
||||
: m_dDist( -1), m_bIsInside( false)
|
||||
: m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false)
|
||||
{
|
||||
// Bezier non valida
|
||||
if ( &pSrfBz == nullptr || ! pSrfBz.IsValid())
|
||||
if ( ! pSrfBz.IsValid())
|
||||
return ;
|
||||
// Calcolo la distanza
|
||||
Calculate( ptP, pSrfBz) ;
|
||||
@@ -37,9 +37,9 @@ void
|
||||
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
m_dDist = -1 ;
|
||||
|
||||
// Controllo se la superficie è chiusa
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = srfBz.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
@@ -49,17 +49,17 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
|
||||
|
||||
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) ;
|
||||
int nT ; dpst.GetMinDistTriaIndex( nT) ;
|
||||
//salvo il punto corrispondente nel parametrico
|
||||
// salvo il punto corrispondente nel parametrico
|
||||
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
|
||||
// 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) ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = Dist( ptP, m_ptMinDistPoint) ;
|
||||
// se il punto è sulla superficie
|
||||
// se il punto è sulla superficie
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_bIsInside = false ;
|
||||
return ;
|
||||
@@ -96,13 +96,14 @@ DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const
|
||||
DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
ptParamPoint = m_ptParam ;
|
||||
dU = m_ptParam.x ;
|
||||
dV = m_ptParam.y ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -116,4 +117,4 @@ DistPointSurfBz::GetNorm( Vector3d& vtN) const
|
||||
// Distanza valida
|
||||
vtN = m_vtN ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2018
|
||||
//----------------------------------------------------------------------------
|
||||
// File : EGkCAvSurfFrMove.h Data : 26.03.2026 Versione : 3.1c6
|
||||
// Contenuto : Dichiarazione classe per movimento di superfici flat region
|
||||
// nel loro piano evitando collisioni
|
||||
//
|
||||
// Modifiche : 26.03.26 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
|
||||
|
||||
//----------------------- Macro per import/export ----------------------------
|
||||
#undef EGK_EXPORT
|
||||
#if defined( I_AM_EGK) // da definirsi solo nella DLL
|
||||
#define EGK_EXPORT __declspec( dllexport)
|
||||
#else
|
||||
#define EGK_EXPORT __declspec( dllimport)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Costanti per info su tipo di Collisione tra regioni piane
|
||||
const int CI_NONE = 0 ; // non definito
|
||||
const int CI_PNT_PNT = 1 ; // tra punto di mobile e punto di fissa
|
||||
const int CI_PNT_LINE = 2 ; // tra punto di mobile e linea di fissa
|
||||
const int CI_LINE_PNT = 3 ; // tra linea di mobile e punto di fissa
|
||||
const int CI_LINE_LINE = 4 ; // tra linea di mobile e linea di fissa
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
struct CollInfo
|
||||
{
|
||||
int nType ; // tipo di collisione
|
||||
int nChunkM ; // indice del chunk della regione mobile
|
||||
int nCrvM ; // indice della curva nel loop esterno del chunk
|
||||
int nChunkF ; // indice del chunk della regione fissa
|
||||
int nCrvF ; // indice della curva nel loop esterno del chunk
|
||||
Point3d ptP1 ; // punto di contatto
|
||||
Point3d ptP2 ; // se contatto linea-linea, secondo punto di contatto
|
||||
Vector3d vtDirM ; // se contatto del mobile con linea, sua direzione
|
||||
Vector3d vtDirF ; // se contatto del fisso con linea, sua direzione
|
||||
// costruttori
|
||||
CollInfo() : nType( CI_NONE), nChunkM( -1), nCrvM( -1), nChunkF( -1), nCrvF( -1),
|
||||
ptP1(), ptP2(), vtDirM(), vtDirF() {}
|
||||
CollInfo( const CollInfo& Sou) : nType( Sou.nType), nChunkM( Sou.nChunkM), nCrvM( Sou.nCrvM),
|
||||
nChunkF( Sou.nChunkF), nCrvF( Sou.nCrvF), ptP1( Sou.ptP1),
|
||||
ptP2( Sou.ptP2), vtDirM( Sou.vtDirM), vtDirF( Sou.vtDirF) {}
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class CAvSurfFrMove
|
||||
{
|
||||
public :
|
||||
EGK_EXPORT CAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) ;
|
||||
|
||||
public :
|
||||
EGK_EXPORT bool Translate( const Vector3d& vtDir, double& dLen) ;
|
||||
EGK_EXPORT bool Rotate( const Point3d& ptCen, double& dAng) ;
|
||||
EGK_EXPORT const CollInfo& GetCollInfo()
|
||||
{ return m_CollInfo ; }
|
||||
|
||||
private :
|
||||
const ISurfFlatRegion* m_pRegM ;
|
||||
const ISurfFlatRegion* m_pRegF ;
|
||||
CollInfo m_CollInfo ;
|
||||
} ;
|
||||
Binary file not shown.
@@ -281,8 +281,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="BBox3d.cpp" />
|
||||
<ClCompile Include="BiArcs.cpp" />
|
||||
<ClCompile Include="CalcPocketing.cpp" />
|
||||
<ClCompile Include="CalcDerivate.cpp" />
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp" />
|
||||
@@ -352,6 +354,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h" />
|
||||
<ClInclude Include="CAvSurfFrMove.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
|
||||
@@ -567,6 +567,12 @@
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CalcDerivate.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1253,6 +1259,9 @@
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CAvSurfFrMove.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+451
-128
@@ -19,14 +19,15 @@
|
||||
#include "/EgtDev/Include/EGkAngle.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids2d.h"
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//--------------------------- Local functions --------------------------------
|
||||
static bool CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvAClosed, double dCrvASpan) ;
|
||||
bool bCrvAClosed, double dCrvASpan, bool bOrderedOnB = false) ;
|
||||
static bool CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvBClosed, double dCrvBSpan) ;
|
||||
bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB = false) ;
|
||||
static void MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crvCompo) ;
|
||||
static int GetCrvBDirAPrev( IntCrvCrvInfo& Icci) ;
|
||||
static int GetCrvBDirANext( IntCrvCrvInfo& Icci) ;
|
||||
@@ -197,7 +198,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// se coincidono U e ptInt tra A e B
|
||||
if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL &&
|
||||
AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) {
|
||||
// se non è alla fine di curva chiusa
|
||||
// se non è alla fine di curva chiusa
|
||||
if ( ! bCrvAClosed || abs( m_Info[j].IciA[0].dU - dCrvBSpan) > EPS_SMALL)
|
||||
// elimino la seconda
|
||||
EraseOtherInfo( i, j) ;
|
||||
@@ -261,10 +262,9 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM &&
|
||||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso DET-NULL -> NULL-DET per prima curva
|
||||
// caso DET-(NULL) -> (NULL)-DET per prima curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy != ICCT_NULL) {
|
||||
// per la prima curva tengo i determinati
|
||||
@@ -272,16 +272,22 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
// se overlap equiverso
|
||||
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
|
||||
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
|
||||
}
|
||||
// se overlap equiverso
|
||||
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
|
||||
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
|
||||
@@ -292,6 +298,13 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
}
|
||||
|
||||
// medio parametri e punti separatamente per le due curve
|
||||
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
|
||||
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
|
||||
@@ -306,7 +319,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
}
|
||||
// caso NULL-DET -> DET-NULL per prima curva (possibile su inizio/fine di curva chiusa)
|
||||
// caso (NULL)-DET -> DET-(NULL) per prima curva (possibile su inizio/fine di curva chiusa)
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
|
||||
m_Info[i].IciA[ki].nPrevTy != ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
// per la prima curva tengo i determinati
|
||||
@@ -314,28 +327,41 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
// se overlap equiverso
|
||||
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
|
||||
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
|
||||
}
|
||||
// se overlap equiverso
|
||||
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
// per la seconda curva ogni sottotipo è il duale di quello della prima
|
||||
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
|
||||
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
|
||||
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
}
|
||||
|
||||
// medio parametri e punti separatamente per le due curve
|
||||
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
|
||||
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
|
||||
@@ -356,8 +382,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-DET -> NULL-DET per prima curva con NULL-NULL -> NULL-NULL su seconda curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
|
||||
@@ -365,18 +390,23 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per corrente di prima curva
|
||||
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per precedente di prima curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
|
||||
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
|
||||
EraseOtherInfo( i, j) ;
|
||||
}
|
||||
@@ -395,22 +425,21 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
continue ;
|
||||
}
|
||||
// calcolo sottoindici
|
||||
int ki = 0 ; // del successivo si prende sempre il primo
|
||||
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
|
||||
int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
|
||||
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
|
||||
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
|
||||
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
|
||||
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) &&
|
||||
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) {
|
||||
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan, true) &&
|
||||
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan, true)) {
|
||||
// caso entrambi Overlap ma di tipo opposto e sullo stesso tratto
|
||||
if ( m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq &&
|
||||
abs( m_Info[i].IciB[0].dU - m_Info[j].IciB[0].dU) < EPS_PARAM &&
|
||||
abs( m_Info[i].IciB[1].dU - m_Info[j].IciB[1].dU) < EPS_PARAM) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso DET-NULL -> NULL-DET per seconda curva
|
||||
// caso DET-(NULL) -> (NULL)-DET per seconda curva
|
||||
else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy != ICCT_NULL) {
|
||||
// per la seconda curva tengo i determinati
|
||||
@@ -418,28 +447,40 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
// se overlap equiverso
|
||||
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
|
||||
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
|
||||
}
|
||||
// se overlap equiverso
|
||||
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
|
||||
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
}
|
||||
// medio parametri e punti separatamente per le due curve
|
||||
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
|
||||
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
|
||||
@@ -454,7 +495,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
}
|
||||
// caso NULL-DET -> DET-NULL per seconda curva (possibile su inizio/fine di curva chiusa)
|
||||
// caso (NULL)-DET -> DET-(NULL) per seconda curva (possibile su inizio/fine di curva chiusa)
|
||||
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
|
||||
m_Info[i].IciB[ki].nPrevTy != ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
// per la seconda curva tengo i determinati
|
||||
@@ -462,28 +503,40 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
// se overlap equiverso
|
||||
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
|
||||
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
|
||||
}
|
||||
// se overlap equiverso
|
||||
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
// per la prima curva ogni sottotipo è il duale di quello della seconda
|
||||
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
|
||||
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
|
||||
}
|
||||
// se altrimenti overlap controverso
|
||||
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
|
||||
}
|
||||
else {
|
||||
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
}
|
||||
// medio parametri e punti separatamente per le due curve
|
||||
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
|
||||
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
|
||||
@@ -504,8 +557,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-DET -> NULL-DET per seconda curva con NULL-NULL -> NULL-NULL su prima curva
|
||||
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
|
||||
@@ -513,22 +565,23 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
|
||||
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
// cancello entrambe
|
||||
EraseOtherInfo( i, j) ;
|
||||
EraseCurrentInfo( i, j) ;
|
||||
EraseBothInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per corrente di seconda curva
|
||||
else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
if ( m_Info[i].IciA[ki].dU > m_Info[j].IciA[kj].dU + EPS_PARAM)
|
||||
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
|
||||
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per precedente di seconda curva
|
||||
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciB[0].nPrevTy = m_Info[j].IciB[0].nPrevTy ;
|
||||
if ( m_Info[j].IciA[0].dU < m_Info[i].IciA[0].dU - EPS_PARAM)
|
||||
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
|
||||
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
|
||||
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
|
||||
EraseOtherInfo( i, j) ;
|
||||
}
|
||||
@@ -537,16 +590,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// ripristino ordinamento su prima curva
|
||||
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterA) ;
|
||||
|
||||
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva A e cerco di risolverle per continuità
|
||||
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva A e cerco di risolverle per continuità
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// se il tipo di accostamento per la curva A non è definito
|
||||
// se il tipo di accostamento per la curva A non è definito
|
||||
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
|
||||
if ( i > 0 || ( bCrvAClosed && ! bAutoInters)) {
|
||||
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
|
||||
m_Info[i].IciA[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciA[1].nNextTy : m_Info[j].IciA[0].nNextTy) ;
|
||||
}
|
||||
}
|
||||
// se il tipo di allontanamento per la curva A non è definito
|
||||
// se il tipo di allontanamento per la curva A non è definito
|
||||
int ki = ( m_Info[i].bOverlap ? 1 : 0) ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
if ( i < m_nNumInters - 1 || ( bCrvAClosed && ! bAutoInters)) {
|
||||
@@ -556,21 +609,23 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
}
|
||||
|
||||
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva B e cerco di risolverle per continuità
|
||||
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva B e cerco di risolverle per continuità
|
||||
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL) {
|
||||
if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
|
||||
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
|
||||
m_Info[i].IciB[ki].nPrevTy = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
|
||||
}
|
||||
}
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) {
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
ki = ( m_Info[i].bOverlap && m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
|
||||
m_Info[i].IciB[0].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
|
||||
m_Info[i].IciB[ki].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -581,7 +636,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// in assenza di overlap
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// se il tipo di accostamento per la curva A non è definito
|
||||
// se il tipo di accostamento per la curva A non è definito
|
||||
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
@@ -590,7 +645,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// aggiorno il tipo di accostamento della curva A alla curva B
|
||||
m_Info[i].IciA[0].nPrevTy = nType ;
|
||||
}
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
@@ -599,7 +654,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// aggiorno il tipo di accostamento della curva B alla curva A
|
||||
m_Info[i].IciB[0].nPrevTy = nType ;
|
||||
}
|
||||
// se il tipo di allontanamento per la curva A non è definito
|
||||
// se il tipo di allontanamento per la curva A non è definito
|
||||
if ( m_Info[i].IciA[0].nNextTy == ICCT_NULL) {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
@@ -608,7 +663,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
m_Info[i].IciA[0].nNextTy = nType ;
|
||||
}
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
@@ -620,66 +675,68 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
// in presenza di overlap
|
||||
else {
|
||||
// se il tipo di accostamento è non definito per la curva A
|
||||
// se il tipo di accostamento è non definito per la curva A
|
||||
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
|
||||
// se autointersezione con spike
|
||||
double dDeltaU = abs( m_Info[i].IciA[0].dU - m_Info[i].IciB[0].dU) ;
|
||||
if ( bAutoInters && ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM))) {
|
||||
// è punta di spike
|
||||
int nType = ICCT_SPK ;
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS,
|
||||
CCompoB, m_Info[i].IciB[0].dU, nType)) {
|
||||
// aggiorno il tipo di accostamento della curva A alla curva B
|
||||
m_Info[i].IciA[0].nPrevTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[0].nNextTy = nType ;
|
||||
}
|
||||
// caso standard
|
||||
else {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS,
|
||||
CCompoB, m_Info[i].IciB[0].dU, nType)) {
|
||||
// aggiorno il tipo di accostamento della curva A alla curva B
|
||||
m_Info[i].IciA[0].nPrevTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[0].nNextTy = nType ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se il tipo di allontanamento è non definito per la curva A
|
||||
// se il tipo di allontanamento è non definito per la curva A
|
||||
if ( m_Info[i].IciA[1].nNextTy == ICCT_NULL) {
|
||||
// se autointersezione con spike
|
||||
double dDeltaU = abs( m_Info[i].IciA[1].dU - m_Info[i].IciB[1].dU) ;
|
||||
if ( bAutoInters && ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM))) {
|
||||
// è punta di spike
|
||||
int nType = ICCT_SPK ;
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[1].dU, ICurve::FROM_PLUS,
|
||||
CCompoB, m_Info[i].IciB[1].dU, nType)) {
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
m_Info[i].IciA[1].nNextTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[1].nPrevTy = nType ;
|
||||
}
|
||||
// caso standard
|
||||
else {
|
||||
// devo studiare un intorno dell'intersezione
|
||||
int nType ;
|
||||
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[1].dU, ICurve::FROM_PLUS,
|
||||
CCompoB, m_Info[i].IciB[1].dU, nType)) {
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
m_Info[i].IciA[1].nNextTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[1].nPrevTy = nType ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAutoInters) {
|
||||
// controllo l'eventuale presenza di spike
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
|
||||
// se secondo tratto dello spike
|
||||
double dDeltaU = abs( m_Info[i].IciA[0].dU - m_Info[i].IciB[0].dU) ;
|
||||
if ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM)) {
|
||||
// è punta di spike
|
||||
int nType = ICCT_SPK ;
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
m_Info[i].IciA[0].nPrevTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[0].nNextTy = nType ;
|
||||
}
|
||||
// se primo tratto dello spike
|
||||
dDeltaU = abs( m_Info[i].IciA[1].dU - m_Info[i].IciB[1].dU) ;
|
||||
if ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM)) {
|
||||
// è punta di spike
|
||||
int nType = ICCT_SPK ;
|
||||
// aggiorno il tipo di allontanamento della curva A dalla curva B
|
||||
m_Info[i].IciA[1].nNextTy = nType ;
|
||||
// aggiorno anche il corrispondente tipo sulla curva B
|
||||
if ( m_Info[i].bCBOverEq)
|
||||
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
|
||||
else
|
||||
m_Info[i].IciB[1].nPrevTy = nType ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,10 +750,10 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// se prima curva aperta, salto alla prossima
|
||||
if ( ! CCompoA.IsClosed())
|
||||
continue ;
|
||||
// è chiusa quindi prendo l'ultima
|
||||
// è chiusa quindi prendo l'ultima
|
||||
j = m_nNumInters - 1 ;
|
||||
}
|
||||
// se i due indici coincidono, c'è una sola intersezione e posso uscire
|
||||
// se i due indici coincidono, c'è una sola intersezione e posso uscire
|
||||
if ( i == j)
|
||||
break ;
|
||||
// assegno sottoindici (considero solo intersezioni overlap)
|
||||
@@ -724,7 +781,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
}
|
||||
|
||||
// se è rimasta una sola intersezione con overlap anche ad entrambi gli estremi e le curve sono chiuse
|
||||
// se è rimasta una sola intersezione con overlap anche ad entrambi gli estremi e le curve sono chiuse
|
||||
if ( m_nNumInters == 1 && CCompoA.IsClosed() && CCompoB.IsClosed() &&
|
||||
m_Info[0].IciA[0].nPrevTy == ICCT_ON && m_Info[0].IciA[1].nNextTy == ICCT_ON &&
|
||||
GetCrvBDirANext( m_Info[0]) == ICCT_ON && GetCrvBDirAPrev( m_Info[0]) == ICCT_ON) {
|
||||
@@ -738,10 +795,243 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
m_Info[0].IciB[1].dU = ( m_Info[0].bCBOverEq ? dEnd : dStart) ;
|
||||
}
|
||||
|
||||
// verifico se una curva ha tutte le info e queste info sono coerenti
|
||||
if ( m_nNumInters > 1 && ! bAutoInters) {
|
||||
bool bCoherent = true ;
|
||||
INTVECTOR vIncoherenceWithPrev ;
|
||||
INTVECTOR vNewOverlap ;
|
||||
// salvo eventuali incoerenze col precedente
|
||||
for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
if ( (m_Info[j].IciA[kj].nNextTy == ICCT_NULL || m_Info[i].IciA[0].nPrevTy == ICCT_NULL || m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy) &&
|
||||
m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) {
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
bCoherent = false ;
|
||||
}
|
||||
}
|
||||
// incoerenze sulla curva A
|
||||
if ( ! bCoherent) {
|
||||
for ( int i : vIncoherenceWithPrev) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
int nType = 0 ;
|
||||
CalcSide( j, i, &CCompoA, &CCompoB, true, nType) ;
|
||||
if ( nType != ICCT_ON) {
|
||||
m_Info[i].IciA[0].nPrevTy = nType ;
|
||||
m_Info[j].IciA[kj].nNextTy = nType ;
|
||||
}
|
||||
else
|
||||
vNewOverlap.push_back( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// faccio il merge se ho trasformato delle intersezioni in overlap
|
||||
for ( int i : views::reverse( vNewOverlap))
|
||||
MergeNewOverlap( i, true) ;
|
||||
|
||||
vNewOverlap.clear() ;
|
||||
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
|
||||
bCoherent = true ;
|
||||
vIncoherenceWithPrev.clear() ;
|
||||
// salvo eventuali incoerenze col precedente
|
||||
for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[ki].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[ki].nPrevTy) &&
|
||||
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[ki].nPrevTy != ICCT_SPK) {
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
bCoherent = false ;
|
||||
}
|
||||
}
|
||||
// incoerenze sulla curva B
|
||||
if ( ! bCoherent) {
|
||||
for ( int i : vIncoherenceWithPrev) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
int nType = 0 ;
|
||||
CalcSide( j, i, &CCompoB, &CCompoA, false, nType) ;
|
||||
if ( nType != ICCT_ON) {
|
||||
m_Info[i].IciB[ki].nPrevTy = nType ;
|
||||
m_Info[j].IciB[kj].nNextTy = nType ;
|
||||
}
|
||||
else
|
||||
vNewOverlap.push_back( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// faccio il merge se ho trasformato delle intersezioni in overlap
|
||||
for ( int i : views::reverse( vNewOverlap))
|
||||
MergeNewOverlap( i, false) ;
|
||||
}
|
||||
else {
|
||||
// posso completare A guardando B e viceversa
|
||||
}
|
||||
|
||||
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterA) ;
|
||||
// verifiche su intersezioni in zone non-manifold
|
||||
OrderNonManifoldInters( m_Info, CCompoA, CCompoB) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType)
|
||||
{
|
||||
const IntCrvCrvInfo& Icci1 = m_Info[j] ;
|
||||
const IntCrvCrvInfo& Icci2 = m_Info[i] ;
|
||||
// calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori
|
||||
int kj = Icci1.bOverlap ? 1 : 0 ;
|
||||
double dU = 0 ;
|
||||
bool bPrevIsBefore = true ;
|
||||
if ( bCrvAOrB) {
|
||||
// se precedente minore del successivo faccio la media
|
||||
if ( Icci1.IciA[kj].dU < Icci2.IciA[0].dU)
|
||||
dU = ( Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ;
|
||||
// altrimenti guardo tra lo start e il successivo
|
||||
else {
|
||||
bPrevIsBefore = false ;
|
||||
dU = ( Icci2.IciA[0].dU + 0.) / 2 ;
|
||||
if ( dU < EPS_SMALL) {
|
||||
double dStart, dEnd ;
|
||||
pThisCrv->GetDomain( dStart, dEnd) ;
|
||||
double dUNew = dEnd - Icci1.IciA[kj].dU / 2 ;
|
||||
if ( dUNew > dU)
|
||||
dU = dUNew ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// se precedente minore del successivo faccio la media
|
||||
if ( Icci1.IciB[kj].dU < Icci2.IciB[0].dU)
|
||||
dU = ( Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ;
|
||||
// altrimenti guardi tra lo start e il successivo
|
||||
else {
|
||||
bPrevIsBefore = false ;
|
||||
dU = ( Icci2.IciB[0].dU + 0.) / 2 ;
|
||||
if ( dU < EPS_SMALL) {
|
||||
double dStart, dEnd ;
|
||||
pThisCrv->GetDomain( dStart, dEnd) ;
|
||||
double dUNew = dEnd - Icci1.IciB[kj].dU / 2 ;
|
||||
if ( dUNew > dU)
|
||||
dU = dUNew ;
|
||||
}
|
||||
}
|
||||
}
|
||||
Point3d ptTest ; pThisCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ;
|
||||
DistPointCurve dpc( ptTest, *pOtherCrv) ;
|
||||
dpc.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
|
||||
if ( nType == MDS_LEFT)
|
||||
nType = ICCT_IN ;
|
||||
else if ( nType == MDS_RIGHT)
|
||||
nType = ICCT_OUT ;
|
||||
// se lo trovo sulla curva controllo se posso definire un tratto overlap
|
||||
if ( nType == MDS_ON) {
|
||||
double dFactor = 1./3. ;
|
||||
DBLVECTOR vdU(2) ;
|
||||
bool bIsOn = false ;
|
||||
if ( bCrvAOrB) {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciA[0].dU + dFactor * Icci1.IciA[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[0].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciA[0].dU > 2 * EPS_SMALL){
|
||||
vdU[0] = ( Icci2.IciA[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciA[0].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
}
|
||||
else {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciB[0].dU + dFactor * Icci1.IciB[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[0].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciB[0].dU > 2 * EPS_SMALL) {
|
||||
vdU[0] = ( Icci2.IciB[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciB[0].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
}
|
||||
if ( ! bIsOn) {
|
||||
bIsOn = true ;
|
||||
for ( int k = 0 ; k < ssize(vdU) && bIsOn ; ++k) {
|
||||
Point3d ptTest2 ; pThisCrv->GetPointD1D2( vdU[k], ICurve::FROM_MINUS, ptTest2) ;
|
||||
DistPointCurve dpc2( ptTest2, *pOtherCrv) ;
|
||||
dpc2.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
|
||||
if ( nType != MDS_ON)
|
||||
bIsOn = false ;
|
||||
}
|
||||
}
|
||||
if ( bIsOn) {
|
||||
m_Info[i].bOverlap = true ;
|
||||
Vector3d vtDirThis, vtDirOther ;
|
||||
Point3d ptCommon ;
|
||||
double dUThis = 0 ;
|
||||
if ( bCrvAOrB)
|
||||
dUThis = m_Info[i].IciA[0].dU ;
|
||||
else
|
||||
dUThis = m_Info[i].IciB[0].dU ;
|
||||
pThisCrv->GetPointD1D2( dUThis, ICurve::Side::FROM_MINUS, ptCommon, &vtDirThis) ;
|
||||
double dUOther = 0 ; pOtherCrv->GetParamAtPoint( ptCommon, dUOther) ;
|
||||
pOtherCrv->GetPointD1D2( dUOther, ICurve::Side::FROM_MINUS, ptCommon, &vtDirOther) ;
|
||||
m_Info[i].bCBOverEq = vtDirThis * vtDirOther > 0 ;
|
||||
if ( m_Info[i].bCBOverEq) {
|
||||
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
}
|
||||
else {
|
||||
if ( bCrvAOrB) {
|
||||
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciB[0].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1].nNextTy = ICCT_ON ;
|
||||
}
|
||||
else {
|
||||
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciA[1] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciA[0].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[1].nNextTy = ICCT_ON ;
|
||||
}
|
||||
}
|
||||
nType = ICCT_ON ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCrvCompoCrvCompo::MergeNewOverlap( int i, bool bCrvAOrB)
|
||||
{
|
||||
// faccio il merge col precedente
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
if ( m_Info[j].bOverlap) {
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[0] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[0] ;
|
||||
}
|
||||
m_Info.erase( m_Info.begin() + j) ;
|
||||
-- j ;
|
||||
-- m_nNumInters ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const ICurve& CurveB, int nB,
|
||||
@@ -806,13 +1096,27 @@ bool
|
||||
IntersCrvCompoCrvCompo::EraseOtherInfo( int& nIndCurr, int& nIndOther)
|
||||
{
|
||||
m_Info.erase( m_Info.begin() + nIndOther) ;
|
||||
if ( nIndOther < nIndCurr)
|
||||
-- nIndCurr ;
|
||||
-- nIndCurr ;
|
||||
-- nIndOther ;
|
||||
-- m_nNumInters ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCrvCompoCrvCompo::EraseBothInfo( int& nIndCurr, int& nIndOther)
|
||||
{
|
||||
m_Info.erase( m_Info.begin() + nIndOther) ;
|
||||
-- nIndCurr ;
|
||||
-- nIndOther ;
|
||||
-- m_nNumInters ;
|
||||
m_Info.erase( m_Info.begin() + nIndCurr) ;
|
||||
if ( nIndCurr != -1)
|
||||
-- nIndCurr ;
|
||||
-- m_nNumInters ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Global functions
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -879,7 +1183,7 @@ SortGreaterB( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2)
|
||||
bool
|
||||
OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& CurveB)
|
||||
{
|
||||
// questi controlli sono validi solo se la curva B è chiusa
|
||||
// questi controlli sono validi solo se la curva B è chiusa
|
||||
if ( ! CurveB.IsClosed())
|
||||
return false ;
|
||||
|
||||
@@ -908,7 +1212,7 @@ OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& Cu
|
||||
// se prima curva aperta, salto alla prossima
|
||||
if ( ! CurveA.IsClosed())
|
||||
continue ;
|
||||
// è chiusa quindi prendo l'ultima
|
||||
// è chiusa quindi prendo l'ultima
|
||||
j = nNumInters - 1 ;
|
||||
}
|
||||
// se i due indici coincidono, salto
|
||||
@@ -960,11 +1264,20 @@ OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& Cu
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvAClosed, double dCrvASpan)
|
||||
bool bCrvAClosed, double dCrvASpan, bool bOrderedOnB)
|
||||
{
|
||||
int k = ( Icci1.bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
|
||||
if ( abs( Icci1.IciA[k].dU - Icci2.IciA[0].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvAClosed || abs( abs( Icci1.IciA[k].dU - Icci2.IciA[0].dU) - dCrvASpan) > 0.1 * SPAN_PARAM))
|
||||
int ki = 0 ;
|
||||
int kj = 0 ;
|
||||
if ( ! bOrderedOnB) {
|
||||
ki = 0 ;
|
||||
kj = Icci1.bOverlap ? 1 : 0 ;
|
||||
}
|
||||
else {
|
||||
ki = Icci2.bOverlap && ! Icci2.bCBOverEq ? 1 : 0 ;
|
||||
kj = Icci1.bOverlap && Icci1.bCBOverEq ? 1 : 0 ;
|
||||
}
|
||||
if ( abs( Icci1.IciA[kj].dU - Icci2.IciA[ki].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvAClosed || abs( abs( Icci1.IciA[kj].dU - Icci2.IciA[ki].dU) - dCrvASpan) > 0.1 * SPAN_PARAM))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
@@ -972,11 +1285,21 @@ CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvBClosed, double dCrvBSpan)
|
||||
bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB)
|
||||
{
|
||||
int k = ( Icci1.bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
|
||||
if ( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvBClosed || abs( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM))
|
||||
int ki = 0 ;
|
||||
int kj = 0 ;
|
||||
if ( ! bOrderedOnB) {
|
||||
ki = 0 ;
|
||||
kj = Icci1.bOverlap ? 1 : 0 ;
|
||||
}
|
||||
else {
|
||||
ki = Icci2.bOverlap && ! Icci2.bCBOverEq ? 1 : 0 ;
|
||||
kj = Icci1.bOverlap && Icci1.bCBOverEq ? 1 : 0 ;
|
||||
}
|
||||
|
||||
if ( abs( Icci1.IciB[kj].dU - Icci2.IciB[ki].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvBClosed || abs( abs( Icci1.IciB[kj].dU - Icci2.IciB[ki].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
@@ -998,7 +1321,7 @@ MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crv
|
||||
//Point3d ptMed ;
|
||||
//if ( ! crvCompo.GetPointD1D2( dUmed, ICurve::FROM_MINUS, ptMed))
|
||||
// return ;
|
||||
// verifico che non sia più lontano dei punti originali dal loro medio
|
||||
// verifico che non sia più lontano dei punti originali dal loro medio
|
||||
//if ( SqDist( Ici1.ptI, ptMed) > dSqDist / 4)
|
||||
// return ;
|
||||
// medio i parametri
|
||||
@@ -1012,13 +1335,13 @@ MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crv
|
||||
static int
|
||||
GetCrvBDirAPrev( IntCrvCrvInfo& Icci)
|
||||
{
|
||||
// non è overlap, è il prev del primo punto
|
||||
// non è overlap, è il prev del primo punto
|
||||
if ( ! Icci.bOverlap)
|
||||
return Icci.IciB[0].nPrevTy ;
|
||||
// è overlap equiverso, è il prev del primo punto
|
||||
// è overlap equiverso, è il prev del primo punto
|
||||
if ( Icci.bCBOverEq)
|
||||
return Icci.IciB[0].nPrevTy ;
|
||||
// è overlap controverso, è il next del primo punto
|
||||
// è overlap controverso, è il next del primo punto
|
||||
return Icci.IciB[0].nNextTy ;
|
||||
}
|
||||
|
||||
@@ -1028,13 +1351,13 @@ GetCrvBDirAPrev( IntCrvCrvInfo& Icci)
|
||||
static int
|
||||
GetCrvBDirANext( IntCrvCrvInfo& Icci)
|
||||
{
|
||||
// non è overlap, è il next del primo punto
|
||||
// non è overlap, è il next del primo punto
|
||||
if ( ! Icci.bOverlap)
|
||||
return Icci.IciB[0].nNextTy ;
|
||||
// è overlap equiverso, è il next del secondo punto
|
||||
// è overlap equiverso, è il next del secondo punto
|
||||
if ( Icci.bCBOverEq)
|
||||
return Icci.IciB[1].nNextTy ;
|
||||
// è overlap controverso, è il prev del secondo punto
|
||||
// è overlap controverso, è il prev del secondo punto
|
||||
return Icci.IciB[1].nPrevTy ;
|
||||
}
|
||||
|
||||
@@ -1078,7 +1401,7 @@ CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
|
||||
return false ;
|
||||
if ( dAngBpDeg < 0)
|
||||
dAngBpDeg += ANG_FULL ;
|
||||
// se l'angolo di DirA è compreso tra DirBn e DirBp (muovendosi in senso CCW) allora è IN, altrimenti OUT
|
||||
// se l'angolo di DirA è compreso tra DirBn e DirBp (muovendosi in senso CCW) allora è IN, altrimenti OUT
|
||||
if ( dAngADeg > 0 && dAngADeg < dAngBpDeg)
|
||||
nType = ICCT_IN ;
|
||||
else
|
||||
@@ -1151,12 +1474,12 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
|
||||
// li ordino in senso crescente
|
||||
if ( dAngB1pDeg > dAngB2pDeg)
|
||||
swap( dAngB1pDeg, dAngB2pDeg) ;
|
||||
// se non ci sono variazioni angolari significative, non posso decidere alcunché
|
||||
// se non ci sono variazioni angolari significative, non posso decidere alcunché
|
||||
const double MIN_DEV_ANG = 2 ;
|
||||
if ( abs( DiffAngle( dAngB1pDeg + ANG_STRAIGHT, 0)) < MIN_DEV_ANG &&
|
||||
abs( DiffAngle( dAngB2pDeg + ANG_STRAIGHT, dAngB2nDeg)) < MIN_DEV_ANG)
|
||||
return false ;
|
||||
// IN è tra 0 e dAngB1pDeg e tra dAngB2nDeg e dAngB2pDeg
|
||||
// IN è tra 0 e dAngB1pDeg e tra dAngB2nDeg e dAngB2pDeg
|
||||
if ( ( dAngADeg > 0 && dAngADeg < dAngB1pDeg) ||
|
||||
( dAngADeg > dAngB2nDeg && dAngADeg < dAngB2pDeg))
|
||||
nType = ICCT_IN ;
|
||||
|
||||
@@ -43,6 +43,9 @@ class IntersCrvCompoCrvCompo
|
||||
bool bAutoInters, bool bClosed, int nCurvesNbr) ;
|
||||
bool EraseCurrentInfo( 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 :
|
||||
bool m_bOverlaps ;
|
||||
|
||||
+45
-21
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
|
||||
// ciclo sulle curve per verificare se da approssimare
|
||||
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])) ||
|
||||
m_pCurve[i]->GetType() == CRV_BEZIER) {
|
||||
// approssimo con rette
|
||||
@@ -127,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
|
||||
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
|
||||
if ( pArc == nullptr)
|
||||
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()) ||
|
||||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
||||
}
|
||||
@@ -252,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
|
||||
bool
|
||||
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())
|
||||
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)
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
@@ -296,8 +296,8 @@ int
|
||||
IntersCurveCurve::GetInters3DCount( void)
|
||||
{
|
||||
int nCount = 0 ;
|
||||
for( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
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)
|
||||
++nCount ;
|
||||
}
|
||||
@@ -365,8 +365,8 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
|
||||
if ( nInd < 0 || nInd >= GetInters3DCount())
|
||||
return false ;
|
||||
int nCount = - 1 ;
|
||||
for( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
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)
|
||||
++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)
|
||||
++nCount ;
|
||||
}
|
||||
if( nCount == nInd) {
|
||||
if ( nCount == nInd) {
|
||||
aInfo = m_Info[nInd] ;
|
||||
return true ;
|
||||
}
|
||||
@@ -389,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
|
||||
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
|
||||
return false ;
|
||||
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
bool bFound = false ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
||||
// se è un'intersezione singola
|
||||
// se è un'intersezione singola
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// faccio la verifica sul punto
|
||||
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
|
||||
if ( m_nIntersCount >= 1)
|
||||
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
|
||||
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
|
||||
if ( m_nIntersCount >= 1)
|
||||
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
|
||||
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 ;
|
||||
if ( dU2 < dU1 && pCurve->IsClosed())
|
||||
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) {
|
||||
bToSkip = true ;
|
||||
break ;
|
||||
@@ -559,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
double dCurrPar = dStartPar ;
|
||||
double dCurrLen = 0 ;
|
||||
double dEndLen ; pCurve->GetLength( dEndLen) ;
|
||||
// se è chiusa, recupero come finisce
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! InfoCorr[nNumInters-1].bOverlap)
|
||||
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
|
||||
@@ -577,7 +577,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
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) ;
|
||||
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
@@ -599,7 +599,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
// altrimenti, salvo il tipo
|
||||
else
|
||||
nLastTy = InfoCorr[i].IciA[0].nNextTy ;
|
||||
// se è definito un tratto in sovrapposizione
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( InfoCorr[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
@@ -639,7 +639,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
double dStartParB, dEndParB ;
|
||||
if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
|
||||
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 ;
|
||||
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
|
||||
! pCurveB->GetLocalBBox( boxCrvB))
|
||||
@@ -682,13 +682,37 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
// dichiaro la classe della curva per default
|
||||
int nClass = CRVC_OUT ;
|
||||
// se c'è almeno una intersezione
|
||||
// se c'è almeno una intersezione
|
||||
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 ;
|
||||
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 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
|
||||
else {
|
||||
@@ -712,7 +736,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
|
||||
double dArea ;
|
||||
if ( ! pCurve->GetAreaXY( dArea))
|
||||
return false ;
|
||||
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +139,6 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur
|
||||
void
|
||||
IntersCurvePlane::OrderAndCompleteIntersections()
|
||||
{
|
||||
if ( m_Info.size() < 2)
|
||||
return ;
|
||||
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
|
||||
// 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 ;}) ;
|
||||
|
||||
+29
-57
@@ -14,7 +14,6 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -157,34 +156,34 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
|
||||
// flag per linee parallele
|
||||
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) ;
|
||||
|
||||
// analisi casi speciali di quasi parallelismo
|
||||
|
||||
// analisi casi speciali di quasi parallelismo
|
||||
// segmento sovrapposto all'altro
|
||||
double dDist1, dDist2 ;
|
||||
if( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
|
||||
if ( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
|
||||
dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ;
|
||||
dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ;
|
||||
if( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
|
||||
bParallel = true ;
|
||||
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) ;
|
||||
dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ;
|
||||
if( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY){
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY) {
|
||||
bParallel = true ;
|
||||
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
|
||||
}
|
||||
}
|
||||
// estremità sovrapposte di poco
|
||||
if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
|
||||
if (( nS1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nS1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nS2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nE2Side == 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
|
||||
if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
|
||||
bParallel = true ;
|
||||
bFarEnds = false ;
|
||||
}
|
||||
@@ -195,54 +194,27 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
// posizioni parametriche dell'intersezione sulle linee
|
||||
m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / 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
|
||||
if ( nS1Side == 0 || nE1Side == 0) {
|
||||
if( nS1Side == 0) {
|
||||
nPos1 = ICurve::PP_START ;
|
||||
m_Info.IciA[0].dU = 0 ;
|
||||
m_Info.IciB[0].dU = vtDir2 * ( ptS1 - ptS2) / Pow( vtDir2.Len(), 2) ;
|
||||
}
|
||||
else {
|
||||
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 ;
|
||||
}
|
||||
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
|
||||
int nPos2 = ICurve::PP_NULL ; // fuori
|
||||
if ( nS2Side == 0 || nE2Side == 0) {
|
||||
if( nS2Side == 0) {
|
||||
nPos2 = ICurve::PP_START ;
|
||||
m_Info.IciB[0].dU = 0 ;
|
||||
m_Info.IciA[0].dU = vtDir1 * (ptS2 - ptS1) / Pow( vtDir1.Len(), 2) ;
|
||||
}
|
||||
else {
|
||||
nPos2 = ICurve::PP_END ;
|
||||
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)
|
||||
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.IciB[0].dU = min( max( m_Info.IciB[0].dU, 0.), 1.) ;
|
||||
// calcolo i punti sulle due linee (possono differire in Z)
|
||||
|
||||
+357
-19
@@ -72,14 +72,28 @@ static void
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
vInfo.emplace_back( nType, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
}
|
||||
else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
double dU2 = ( ptIBz2 - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
|
||||
int nType2 = LSBT_NONE ;
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,9 +107,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
|
||||
{ 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) ; }) ;
|
||||
{ return ( a.dU < b.dU) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -181,19 +193,9 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) {
|
||||
int nFlag = LSBT_TOUCH ;
|
||||
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) ;
|
||||
}
|
||||
vInters.emplace_back( Info.nILSB, Info.dU) ;
|
||||
// se intersezione sovrapposta
|
||||
// da sviluppare
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
@@ -239,7 +241,343 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier
|
||||
// Intersezione di una linea con una superficie di Bezier di grado 3x1 monopatch
|
||||
//----------------------------------------------------------------------------
|
||||
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
|
||||
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
|
||||
|
||||
+1
-1
@@ -173,7 +173,7 @@ Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN,
|
||||
{
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptOn, vtN) ;
|
||||
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt) ;
|
||||
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt, dToler) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+22
-14
@@ -172,9 +172,9 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
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) ;
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
@@ -206,22 +206,30 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
|
||||
continue ;
|
||||
// calcolo il segmento di linea
|
||||
CurveLine clLine ;
|
||||
CurveLine clLine ;
|
||||
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
|
||||
return false ;
|
||||
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
|
||||
IntersCurveCurve intLL( clLine, ccLoop) ;
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
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) ;
|
||||
if ( intLL.GetIntersCount() == 0) {
|
||||
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
|
||||
ptM.z = 0 ;
|
||||
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
|
||||
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ;
|
||||
}
|
||||
else {
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+99
-52
@@ -19,6 +19,7 @@
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
@@ -92,6 +93,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
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.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
@@ -104,6 +107,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
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.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
@@ -118,6 +123,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
Pt5ax.ptP = ptInt ;
|
||||
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.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.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
@@ -233,23 +240,55 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
|
||||
static const SurfTriMesh*
|
||||
MyGetAuxSurf( const ISurf* pSrf)
|
||||
{
|
||||
// punto sulle supefici a minima distanza
|
||||
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
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulle superfici a minima distanza
|
||||
int nSurfMin = -1 ;
|
||||
int nTriaMin ;
|
||||
int nTriaMin = -1 ;
|
||||
double dUMin = -1, dVMin = -1 ;
|
||||
Point3d ptMin ;
|
||||
double dMinDist ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
double dMinDist = NAN ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
// punto sulla superficie a minima distanza
|
||||
DistPointSurfTm dPS( ptP, *vpStm[i]) ;
|
||||
double dDist ;
|
||||
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
|
||||
nSurfMin = i ;
|
||||
dPS.GetMinDistPoint( ptMin) ;
|
||||
dPS.GetMinDistTriaIndex ( nTriaMin) ;
|
||||
dMinDist = dDist ;
|
||||
int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ;
|
||||
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
|
||||
DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ;
|
||||
double dDist ;
|
||||
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
|
||||
nSurfMin = i ;
|
||||
dPS.GetMinDistPoint( ptMin) ;
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,19 +296,44 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar
|
||||
if ( nSurfMin >= 0) {
|
||||
// assegno il punto
|
||||
Point3d ptInt = ptMin ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptMin, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtN ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// calcolo gli altri dati
|
||||
int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ;
|
||||
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
|
||||
// recupero superficie trimesh
|
||||
const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! pSurfTm->GetTriangle( nTriaMin, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptMin, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
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
|
||||
return true ;
|
||||
}
|
||||
@@ -282,31 +346,6 @@ bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||
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
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
@@ -331,7 +370,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -403,6 +442,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = frRefLine.VersZ() ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
@@ -557,6 +598,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
@@ -696,6 +739,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
@@ -852,6 +897,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtN2 ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
|
||||
+2
-3
@@ -735,8 +735,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv,
|
||||
const INTVECTOR& vShown, const INTINTVECTOR& vNewOrEdited, double dLinTol)
|
||||
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
@@ -763,7 +762,7 @@ GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const IC
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv, vNewCrv, vShown, vNewOrEdited))
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
|
||||
+14
-7
@@ -76,11 +76,18 @@ FromString( const string& sVal, Frame3d& frFrame)
|
||||
bool
|
||||
FromString( const string& sVal, Color& cCol)
|
||||
{
|
||||
// devono essere 4 parametri : Red, Green, Blue, Alpha
|
||||
int vnVal[4] ;
|
||||
if ( ! FromString( sVal, vnVal))
|
||||
return false ;
|
||||
// assegno il colore
|
||||
cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
|
||||
return true ;
|
||||
// dovrebbero essere 4 parametri : Red, Green, Blue, Alpha
|
||||
int vnRGBA[4] ;
|
||||
if ( FromString( sVal, vnRGBA)) {
|
||||
cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ;
|
||||
return true ;
|
||||
}
|
||||
// riprovo con 3 parametri : Red, Green, Blue
|
||||
int vnRGB[3] ;
|
||||
if ( FromString( sVal, vnRGB)) {
|
||||
cCol.Set( vnRGB[0], vnRGB[1], vnRGB[2]) ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti errore
|
||||
return false ;
|
||||
}
|
||||
|
||||
+311
-69
@@ -24,6 +24,14 @@
|
||||
#include "/EgtDev/Include/EGkSurfAux.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.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 ;
|
||||
|
||||
@@ -530,6 +538,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
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
|
||||
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
|
||||
@@ -539,36 +566,33 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
bool bRescaledU = false ;
|
||||
bool bRescaledV = false ;
|
||||
int nSpanU = 1, nSpanV = 1 ;
|
||||
PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
|
||||
ICRVCOMPOPOVECTOR vUniformedCurves ;
|
||||
BOOLVECTOR vbUniform(2) ;
|
||||
fill( vbUniform.begin(), vbUniform.end(), true) ;
|
||||
DBLMATRIX mKnots(2) ;
|
||||
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vU ;
|
||||
DBLVECTOR& vU = mKnots[nDir] ;
|
||||
int nExtraKnots = 0 ;
|
||||
// controllo in U
|
||||
if ( nDir == 0) {
|
||||
if ( nDegU > 1) {
|
||||
nExtraKnots = nDegU - 1 ;
|
||||
}
|
||||
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
|
||||
for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) {
|
||||
double dKnot = vU0[i] * SBZ_TREG_COEFF ;
|
||||
// lo aggiungo solo se è diverso dal precedente
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
nSpanU = (int)vU.size() - 1 ;
|
||||
nSpanU = ssize( vU) - 1 ;
|
||||
}
|
||||
// controllo in V
|
||||
else if ( nDir == 1 ) {
|
||||
if ( nDegV > 1) {
|
||||
nExtraKnots = nDegV - 1 ;
|
||||
}
|
||||
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
|
||||
for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) {
|
||||
double dKnot = vV0[i] * SBZ_TREG_COEFF ;
|
||||
// lo aggiungo solo se è diverso dal precedente
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
nSpanV = (int)vU.size() - 1 ;
|
||||
nSpanV = ssize( vU) - 1 ;
|
||||
}
|
||||
|
||||
// controllo se il vettore dei nodi è uniforme
|
||||
@@ -581,76 +605,268 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
if ( b < (int)vU.size())
|
||||
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 ;
|
||||
pRescaledSfr.Set( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pRescaledSfr))
|
||||
return false ;
|
||||
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
|
||||
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
|
||||
if ( IsNull( pSfr_copy))
|
||||
return false ;
|
||||
// creo il vettore delle curve all'interno di una striscia
|
||||
ICRVCOMPOPOVECTOR vCrvStrip ;
|
||||
for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
|
||||
double dLenStrip = abs( vU[p+1] - vU[p]) ;
|
||||
if ( dLenStrip < EPS_SMALL)
|
||||
continue ;
|
||||
// creo la maschera per tagliare la superficie originale e ottenere una striscia
|
||||
PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
|
||||
PtrOwner<ICurveComposite> pTrimMask ;
|
||||
|
||||
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
|
||||
Vector3d vtTrim ;
|
||||
if ( nDir == 0) {
|
||||
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
|
||||
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
|
||||
Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ;
|
||||
pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ;
|
||||
}
|
||||
else{
|
||||
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
|
||||
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
|
||||
Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ;
|
||||
pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ;
|
||||
}
|
||||
pSfrTrim->Translate( vtTrim) ;
|
||||
|
||||
if ( ! pSfr_copy->Intersect( *pSfrTrim))
|
||||
return false ;
|
||||
// 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)
|
||||
|
||||
// aggiungo la nuova striscia solo se è valida
|
||||
if ( pSfr_copy->IsValid() ) {
|
||||
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 ;
|
||||
|
||||
if ( nDir == 0)
|
||||
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
else
|
||||
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
|
||||
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
|
||||
|
||||
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))
|
||||
dCoeffX = SBZ_TREG_COEFF / dLenStrip ;
|
||||
else
|
||||
dCoeffY = SBZ_TREG_COEFF / dLenStrip ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
|
||||
if( ! IsNull( vCrvStrip[i]))
|
||||
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
pRescaledSfr.Set( pSfr_copy) ;
|
||||
|
||||
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo (nDir == 0)
|
||||
// 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) {
|
||||
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
|
||||
if ( pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
if( ! vbUniform[1]) {
|
||||
vLoop.swap( vUniformedCurves) ;
|
||||
vUniformedCurves.clear() ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -658,12 +874,38 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
if ( ! vUniformedCurves.empty()) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
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
|
||||
|
||||
// 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)
|
||||
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
|
||||
|
||||
+531
-238
File diff suppressed because it is too large
Load Diff
+7
-7
@@ -116,9 +116,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
const SurfTriMesh* GetAuxSurfRefined( void) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 10 * EPS_SMALL, bool bUpdateEdges = false) const override ;
|
||||
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined = false) 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
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ;
|
||||
@@ -143,16 +143,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool IsPlanar( void) const override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) 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 CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
|
||||
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ;
|
||||
PNTVECTOR GetAllControlPoints( void) const override ;
|
||||
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const ICURVEPOVECTOR& vCrv, const ICURVEPOVECTOR& vNewCrv, const INTVECTOR& vShown ,const INTINTVECTOR& vNewOrEdited) ;
|
||||
bool RemoveCollapsedSpans() override ;
|
||||
bool SwapParameters() ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
|
||||
bool RemoveCollapsedSpans( void) override ;
|
||||
bool SwapParameters( void) ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+188
-35
@@ -28,6 +28,13 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.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 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -107,8 +114,20 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
||||
pMyCrv->SetThickness( 0) ;
|
||||
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
|
||||
ICURVEPLIST CrvLst ;
|
||||
|
||||
#if SAVEADJUSTCRV
|
||||
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
|
||||
#endif
|
||||
|
||||
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
||||
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
|
||||
int nExtAdded = 0 ;
|
||||
bool bOk = true ;
|
||||
@@ -169,14 +188,18 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
Vector3d vtExtr ;
|
||||
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
|
||||
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
|
||||
bool bOk = true ;
|
||||
CRVCVECTOR ccClass ;
|
||||
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]) ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
|
||||
@@ -216,14 +239,9 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
bool
|
||||
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
|
||||
{
|
||||
try {
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
}
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -304,10 +322,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
// 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))
|
||||
pMyCrv->Invert() ;
|
||||
// verifico non abbia auto-intersezioni
|
||||
SelfIntersCurve sInt( *pMyCrv) ;
|
||||
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
||||
return false ;
|
||||
|
||||
// ricerca del chunk in cui andrebbe inserito
|
||||
int nChunk = -1 ;
|
||||
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
|
||||
@@ -354,23 +369,18 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
bool
|
||||
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
|
||||
{
|
||||
try {
|
||||
// se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
// altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
//se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
//altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -1374,6 +1384,15 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
|
||||
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
// 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) ;
|
||||
// classificazione
|
||||
CRVCVECTOR ccPart ;
|
||||
@@ -1537,7 +1556,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
||||
int nClass = ccInt.GetRegionCurveClassification() ;
|
||||
switch ( nClass){
|
||||
switch ( nClass) {
|
||||
default : // CCREGC_NULL
|
||||
return REGC_NULL ;
|
||||
case CCREGC_IN1 :
|
||||
@@ -1550,7 +1569,141 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
return REGC_OUT ;
|
||||
case CCREGC_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 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -107,6 +107,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
bool GetChunkArea( int nChunk, double& dArea) const override ;
|
||||
bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
|
||||
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 ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
|
||||
@@ -139,6 +140,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
|
||||
|
||||
friend class MyCAvSimpleSurfFrMove ;
|
||||
friend class MyCAvSurfFrMove ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVELOOPS 0
|
||||
#if SAVELOOPS
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -172,6 +178,13 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
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)) {
|
||||
MyTestAndDelete( vpCurve) ;
|
||||
MyTestAndDelete( vpLoop) ;
|
||||
|
||||
@@ -4415,6 +4415,35 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
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
|
||||
SurfTriMesh::ResetTFlags( void)
|
||||
|
||||
@@ -347,6 +347,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetPartVolume( int nPart, double& dVolume) const override ;
|
||||
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) 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 GetTFlag( int nId, int& nFlag) const override ;
|
||||
int GetMaxTFlag( void) const override
|
||||
|
||||
@@ -36,25 +36,25 @@ class Tool
|
||||
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
|
||||
bool SetToolNum( int nToolNum)
|
||||
{ m_nCurrentNum = nToolNum ; return true ; }
|
||||
int GetType() const
|
||||
int GetType( void) const
|
||||
{ return m_nType ; }
|
||||
int GetToolNum() const
|
||||
int GetToolNum( void) const
|
||||
{ return m_nCurrentNum ; }
|
||||
double GetHeigth() const
|
||||
double GetHeigth( void) const
|
||||
{ return m_dHeight ; }
|
||||
double GetTipHeigth() const
|
||||
double GetTipHeigth( void) const
|
||||
{ return m_dTipHeight ; }
|
||||
double GetRadius() const
|
||||
double GetRadius( void) const
|
||||
{ return m_dRadius ; }
|
||||
double GetTipRadius() const
|
||||
double GetTipRadius( void) const
|
||||
{ return m_dTipRadius ; }
|
||||
double GetCornRadius() const
|
||||
double GetCornRadius( void) const
|
||||
{ return m_dRCorner ; }
|
||||
double GetRefRadius() const
|
||||
double GetRefRadius( void) const
|
||||
{ return m_dRefRadius ; }
|
||||
double GetMrtChsWidth() const
|
||||
double GetMrtChsWidth( void) const
|
||||
{ return m_dMrtChsWidth ; }
|
||||
double GetMrtChsThickness() const
|
||||
double GetMrtChsThickness( void) const
|
||||
{ return m_dMrtChsThickness ; }
|
||||
const CurveComposite& GetOutline( void) const
|
||||
{ return ( m_Outline) ; }
|
||||
|
||||
@@ -177,7 +177,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
|
||||
int nLoop = 0 ;
|
||||
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
|
||||
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
|
||||
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
|
||||
double dLinTol = 0.005 ; // questo è riferito allo spazio parametrico
|
||||
double dAngTolDeg = 5 ;
|
||||
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
|
||||
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
|
||||
@@ -185,6 +185,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
|
||||
// i chunk della falt region sono ancora flat region composte da 1 chunk
|
||||
// rimuovo i difetti dei loop prima di salvarli
|
||||
PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ;
|
||||
if ( IsNull( pLoop))
|
||||
return false ;
|
||||
pLoop->MergeCurves( dLinTol, dAngTolDeg) ;
|
||||
pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
|
||||
pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ;
|
||||
@@ -461,8 +463,8 @@ Tree::Split( int nId, double dSplitValue)
|
||||
dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ;
|
||||
Point3d ptP00, ptP01, ptP10, ptP11 ;
|
||||
|
||||
if( bGoodSplitVert) {
|
||||
if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
|
||||
if ( bGoodSplitVert) {
|
||||
if ( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
|
||||
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
|
||||
GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ;
|
||||
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
|
||||
@@ -474,12 +476,13 @@ Tree::Split( int nId, double dSplitValue)
|
||||
GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ;
|
||||
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
|
||||
}
|
||||
if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
|
||||
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
|
||||
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
|
||||
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
|
||||
dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
|
||||
bGoodSplitVert = false ;
|
||||
}
|
||||
if( bGoodSplitHoriz) {
|
||||
if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
|
||||
if ( bGoodSplitHoriz) {
|
||||
if ( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
|
||||
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
|
||||
GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ;
|
||||
GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ;
|
||||
@@ -491,8 +494,9 @@ Tree::Split( int nId, double dSplitValue)
|
||||
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
|
||||
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
|
||||
}
|
||||
if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
|
||||
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
|
||||
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
|
||||
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
|
||||
dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
|
||||
bGoodSplitHoriz = false ;
|
||||
}
|
||||
|
||||
@@ -662,8 +666,18 @@ 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
|
||||
if ( dSagU < dLinTol && dSagV < dLinTol) {
|
||||
if ( dSagU < dLinTol && dSagV < dLinTol && ! bIsFlat) {
|
||||
// step di verifica in U e in V
|
||||
int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ;
|
||||
int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ;
|
||||
@@ -724,6 +738,73 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
//{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ;
|
||||
// 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
|
||||
// misura approssimativa della curvatura in una direzione
|
||||
@@ -734,7 +815,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
bVert = false ;
|
||||
else
|
||||
bVert = ( dSagV <= dSagU) ;
|
||||
pcToSplit->SetSplitDirVert( bVert) ;
|
||||
bool bFirstTry = true ;
|
||||
retry :
|
||||
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
|
||||
double dSideMinVal = 0 ;
|
||||
double dLengMinVal = 0 ;
|
||||
@@ -776,6 +858,11 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
}
|
||||
else if ( dSagV > dLinTol || dSagU > dLinTol) {
|
||||
bSplit = bDimOk ;
|
||||
if ( ! bSplit && bFirstTry) {
|
||||
bFirstTry = false ;
|
||||
bVert = ! bVert ;
|
||||
goto retry ;
|
||||
}
|
||||
//if ( bSplit)
|
||||
// LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV")
|
||||
}
|
||||
@@ -1455,7 +1542,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
|
||||
++ nPolyInd ;
|
||||
continue ;
|
||||
}
|
||||
else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
|
||||
else if ( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
|
||||
continue ;
|
||||
else {
|
||||
// vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
|
||||
@@ -1980,7 +2067,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
nCells.push_back( nCell) ;
|
||||
nEdge = -2 ;
|
||||
}
|
||||
if( ssize( nCells) == 1)
|
||||
if ( ssize( nCells) == 1)
|
||||
return nCells ;
|
||||
|
||||
Vector3d vtDir ;
|
||||
@@ -2009,14 +2096,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 )
|
||||
ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ;
|
||||
// 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)) {
|
||||
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ;
|
||||
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
|
||||
}
|
||||
// altrimenti ruoto a sinistra
|
||||
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 */ {
|
||||
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 */ {
|
||||
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
|
||||
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
|
||||
}
|
||||
@@ -2138,7 +2225,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
bool bLoopInside = true ;
|
||||
Point3d ptCurr ;
|
||||
int nIdPolygon = - 1;
|
||||
if( ! pCell->m_vnPolyId.empty())
|
||||
if ( ! pCell->m_vnPolyId.empty())
|
||||
nIdPolygon = pCell->m_vnPolyId[0] ;
|
||||
else
|
||||
return false ;
|
||||
@@ -2178,9 +2265,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
}
|
||||
// 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
|
||||
if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
|
||||
if ( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
|
||||
++ nInfiniteLoopCount ;
|
||||
if( nInfiniteLoopCount == 4) {
|
||||
if ( nInfiniteLoopCount == 4) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
|
||||
return false ;
|
||||
}
|
||||
@@ -2189,7 +2276,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
// aggiorno il puntatore alla cella
|
||||
pCell = &m_mTree[nId] ;
|
||||
// recupero l'indice del poligono base associato alla cella
|
||||
if( ! pCell->m_vnPolyId.empty())
|
||||
if ( ! pCell->m_vnPolyId.empty())
|
||||
nIdPolygon = pCell->m_vnPolyId[0] ;
|
||||
else
|
||||
return false ;
|
||||
@@ -4025,7 +4112,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
|
||||
Point3d ptTl ( ptBL.x, ptTR.y) ;
|
||||
Point3d ptBr ( ptTR.x, ptBL.y) ;
|
||||
|
||||
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)
|
||||
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)
|
||||
return false ;
|
||||
else if ( AreSamePointXYApprox( ptToAssign, ptTR))
|
||||
nEdge = 7 ;
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <utility>
|
||||
|
||||
struct PairHashInt64 {
|
||||
size_t operator()(const std::pair<int64_t, int64_t>& key) const {
|
||||
size_t
|
||||
operator()( const std::pair<int64_t, int64_t>& key) const {
|
||||
size_t h1 = std::hash<int64_t>{}(key.first) ;
|
||||
size_t h2 = std::hash<int64_t>{}(key.second) ;
|
||||
return h1 ^ (h2 << 1); // Combine hashes
|
||||
@@ -33,14 +34,20 @@ struct PairHashInt64 {
|
||||
//----------------------------------------------------------------------------
|
||||
struct Inters {
|
||||
int nIn ;
|
||||
PNTVECTOR vpt ;
|
||||
int nOut ;
|
||||
PNTVECTOR vpt ;
|
||||
bool bCCW ;
|
||||
int nChunk ;
|
||||
bool bSortedbyStart ;
|
||||
// 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)
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
@@ -75,7 +82,8 @@ struct Inters {
|
||||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
|
||||
}
|
||||
|
||||
static bool FirstEncounter( Inters& a, Inters& b)
|
||||
static bool
|
||||
FirstEncounter( Inters& a, Inters& b)
|
||||
{
|
||||
// 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
|
||||
@@ -135,18 +143,18 @@ struct Inters {
|
||||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
|
||||
}
|
||||
|
||||
bool operator == ( Inters& b)
|
||||
bool
|
||||
operator == ( Inters& b)
|
||||
{
|
||||
return AreSamePointExact( vpt[0], b.vpt[0]) ;
|
||||
}
|
||||
bool operator != ( Inters& b)
|
||||
|
||||
bool
|
||||
operator != ( Inters& b)
|
||||
{
|
||||
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
|
||||
@@ -160,11 +168,12 @@ class Cell
|
||||
// | |
|
||||
// |_________________|
|
||||
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
|
||||
public:
|
||||
enum Collapsed { TO_VERIFY = -1, // da verificare
|
||||
NO_COLLAPSE = 0, // non ho coppie di lati collassati
|
||||
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
|
||||
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
|
||||
|
||||
public :
|
||||
enum Collapsed { TO_VERIFY = -1, // da verificare
|
||||
NO_COLLAPSE = 0, // non ho coppie di lati collassati
|
||||
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
|
||||
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
|
||||
|
||||
public :
|
||||
~Cell( void) {}
|
||||
@@ -336,4 +345,4 @@ class Tree
|
||||
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
||||
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
} ;
|
||||
} ;
|
||||
|
||||
+1999
-923
File diff suppressed because it is too large
Load Diff
+253
-49
@@ -29,8 +29,21 @@
|
||||
#include <thread>
|
||||
#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 ;
|
||||
|
||||
#if !defined(_WIN64)
|
||||
int VolZmap::m_nDexelNbr = 0 ;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
|
||||
|
||||
@@ -55,6 +68,13 @@ 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
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -75,6 +95,13 @@ VolZmap::Clear( void)
|
||||
m_nNumBlock = 0 ;
|
||||
m_nConnectedCompoCount = 0 ;
|
||||
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) {
|
||||
m_nNx[i] = 0 ;
|
||||
m_nNy[i] = 0 ;
|
||||
@@ -1694,16 +1721,15 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
if ( ! IsValid())
|
||||
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)) ;
|
||||
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
|
||||
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()) ;
|
||||
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()))
|
||||
return false ;
|
||||
|
||||
@@ -1719,7 +1745,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
// Ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti nella Copia
|
||||
for ( int nDex = 0 ; nDex < int( pZMapCopy->m_Values[nGrid].size()) ; ++ nDex) {
|
||||
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 ;
|
||||
@@ -1727,9 +1753,9 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// Recupero il numero di intervalli presenti nel Dexel corrente
|
||||
int nIntervals = int( pZMapCopy->m_Values[nGrid][nDex].size()) ;
|
||||
int nIntervals = ssize( pZMapCopy->m_Values[nGrid][nDex]) ;
|
||||
// Scorro gli intervalli presenti
|
||||
for ( int nInfo = 0 ; nInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
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 richiesta prima estensione
|
||||
@@ -1739,57 +1765,54 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
|
||||
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
|
||||
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
|
||||
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
|
||||
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
|
||||
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente)
|
||||
// ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
nIntervals = ssize( m_Values[nGrid][nDex]) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax,
|
||||
Interval.dMin, dToler, true,
|
||||
nToolNum, V_INVALID, V_INVALID) ;
|
||||
pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, Interval.dMin,
|
||||
dToler, true, nToolNum, V_INVALID, V_INVALID) ;
|
||||
}
|
||||
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
|
||||
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
|
||||
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
|
||||
// Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni
|
||||
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
|
||||
if ( IsTriDexel() && nIntervals != ssize( m_Values[nGrid][nDex])) {
|
||||
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo)
|
||||
// ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
nIntervals = ssize( m_Values[nGrid][nDex]) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
Interval.dMax,
|
||||
pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, dToler, true,
|
||||
nToolNum, V_INVALID, V_INVALID) ;
|
||||
Interval.dMax, pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin,
|
||||
dToler, true, nToolNum, V_INVALID, V_INVALID) ;
|
||||
}
|
||||
}
|
||||
// --- Se richiesta prima restrizione
|
||||
else {
|
||||
// *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ]
|
||||
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler,
|
||||
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
|
||||
// Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni
|
||||
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
|
||||
// Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
Interval.dMin,
|
||||
Interval.dMax, dToler, true,
|
||||
Tool::UNDEF, V_INVALID, V_INVALID) ;
|
||||
// Se la lunghezza dell'intervallo non è almeno il doppio della tolleranza
|
||||
double dLen = Interval.dMax - Interval.dMin ;
|
||||
if ( dLen < 2. * ( dToler + EPS_SMALL)) {
|
||||
// L'intervallo sparisce completamente
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
|
||||
Interval.vtMinN, Interval.vtMaxN, nToolNum, true) ;
|
||||
// Rimuovo le parti di spillone nelle altre dimensioni
|
||||
if ( IsTriDexel()) {
|
||||
-- nIntervals ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
Interval.dMin, Interval.dMax,
|
||||
dToler, true, Tool::UNDEF, V_INVALID, V_INVALID) ;
|
||||
}
|
||||
}
|
||||
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ]
|
||||
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler,
|
||||
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
|
||||
// Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni
|
||||
if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) {
|
||||
// Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
Interval.dMin,
|
||||
Interval.dMax, dToler, true,
|
||||
Tool::UNDEF, V_INVALID, V_INVALID) ;
|
||||
// Se sufficientemente lungo, allora
|
||||
else {
|
||||
// *** Estremo inferiore -> Intervallo : [ dMin, dMin + dToler ]
|
||||
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMin + dToler,
|
||||
Interval.vtMinN, Interval.vtMinN, nToolNum, true) ;
|
||||
// *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax ]
|
||||
// Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + EPS_SMALL,
|
||||
Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1799,12 +1822,12 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
// Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy)
|
||||
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
|
||||
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se l'intervallo è vuoto, non faccio nulla
|
||||
if ( m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Per ogni intervallo ricavato fino ad ora, restringo della tolleranza
|
||||
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
// --- Se richiesta prima estensione
|
||||
if ( bIsExtensionFirst) {
|
||||
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
|
||||
@@ -1816,7 +1839,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
m_Values[nGrid][nDex][nInfo].dMax += dToler ;
|
||||
}
|
||||
// Definisco il colore
|
||||
for ( int nOrigInfo = 0 ; nOrigInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nOrigInfo) {
|
||||
for ( int nOrigInfo = 0 ; nOrigInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nOrigInfo) {
|
||||
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 ;
|
||||
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL)
|
||||
@@ -1830,7 +1853,7 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
// Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy)
|
||||
for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < int( pZMapExtra->m_Values[nGrid].size()) ; ++ nDex) {
|
||||
for ( int nDex = 0 ; nDex < ssize( pZMapExtra->m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se l'intervallo è vuoto, non faccio nulla
|
||||
if ( pZMapExtra->m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
@@ -1838,19 +1861,19 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// Per ogni intervallo ricavato fino ad ora...
|
||||
for ( int nInfo = 0 ; nInfo < int( pZMapExtra->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
for ( int nInfo = 0 ; nInfo < ssize( pZMapExtra->m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ;
|
||||
double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ;
|
||||
Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ;
|
||||
Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ;
|
||||
// --- Se richiesta prima estensione
|
||||
if ( bIsExtensionFirst) {
|
||||
// ... aggiungo i contributi
|
||||
AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
|
||||
// Aggiungo i contributi
|
||||
AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
|
||||
}
|
||||
// --- Se richiesta prima restrizione
|
||||
else {
|
||||
// ... sottraggo i contributi
|
||||
// Sottraggo i contributi
|
||||
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
|
||||
}
|
||||
}
|
||||
@@ -1868,6 +1891,187 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
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
|
||||
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
|
||||
@@ -21,9 +21,8 @@
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <tuple>
|
||||
#include <atomic>
|
||||
|
||||
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
|
||||
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
|
||||
@@ -82,10 +81,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
public : // IVolZmap
|
||||
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
|
||||
bool Clear( void) 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) 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) override ;
|
||||
bool Create( 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, int* nError = nullptr) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
@@ -152,6 +151,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool SubtractSurfTm( const ISurfTriMesh* pStm) 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 ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
@@ -227,7 +227,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
typedef std::unordered_map<int, Voxel> VoxelContainer ;
|
||||
// Unordered map per la coerenza topologica
|
||||
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 :
|
||||
bool CopyFrom( const VolZmap& clSrc) ;
|
||||
bool ResetGraphics( void) ;
|
||||
@@ -263,6 +272,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
|
||||
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
|
||||
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,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
// Spostamenti utensile
|
||||
@@ -487,6 +497,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// Funzioni per Offset di Zmap
|
||||
bool OffsetFillet( double dOffs) ;
|
||||
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 :
|
||||
enum Move5Axis {
|
||||
@@ -557,9 +572,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable std::vector<InterVoxMatter> m_SliceXY ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceXZ ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceYZ ;
|
||||
mutable std::mutex m_SliceMutex ;
|
||||
mutable std::atomic_flag m_SliceFlag ;
|
||||
|
||||
std::atomic<bool> m_bIsBox ;
|
||||
bool m_bIsBox ;
|
||||
|
||||
int m_nCurrTool ;
|
||||
std::vector<Tool> m_vTool ;
|
||||
|
||||
+79
-14
@@ -27,8 +27,8 @@ using namespace std ;
|
||||
// ------------------------- CREAZIONE MAPPA --------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -51,7 +51,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[0] = max( int( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[0] = max( int( ( dDimY + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
|
||||
// Numero di componenti connesse
|
||||
// Numero di componenti connesse
|
||||
m_nConnectedCompoCount = 1 ;
|
||||
|
||||
// Se tridexel
|
||||
@@ -67,7 +67,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nNx[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
}
|
||||
|
||||
// Definisco il numero di blocchi lungo x,y e z
|
||||
@@ -81,12 +81,24 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ 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
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
|
||||
// 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) {
|
||||
|
||||
// Aggiungo il tratto al dexel vuoto
|
||||
@@ -98,7 +110,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
switch ( i) {
|
||||
case 0 :
|
||||
m_Values[i][j][0].vtMinN = - Z_AX ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].vtMaxN = Z_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
@@ -113,9 +125,10 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_Values[i][j][0].dMax = dDimY ;
|
||||
m_Values[i][j][0].vtMaxN = Y_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definizione delle limitazioni iniziali in Z per ogni mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
@@ -136,7 +149,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -187,6 +200,18 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ 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
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
@@ -210,7 +235,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Aggiorno la dimensione della mappa 1 o 3
|
||||
m_nMapNum = ( bTriDex ? 3 : 1) ;
|
||||
@@ -250,14 +275,35 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
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]) ;
|
||||
}
|
||||
|
||||
// Se dimensione singola
|
||||
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_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
@@ -788,7 +834,7 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError)
|
||||
{
|
||||
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
||||
double dVol ;
|
||||
@@ -838,14 +884,33 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
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]) ;
|
||||
}
|
||||
|
||||
// Se a dimensione singola
|
||||
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_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
|
||||
+24
-12
@@ -1271,13 +1271,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceYZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 2) {
|
||||
@@ -1287,13 +1289,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 3) {
|
||||
@@ -1303,13 +1307,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXY[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1374,27 +1380,33 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceYZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 2) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 3) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXY.emplace(nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+383
-84
@@ -31,6 +31,13 @@
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
|
||||
#define SAVETRIMMINGTOOL 0
|
||||
|
||||
#if SAVETRIMMINGTOOL
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
// ------------------------- OPERAZIONI SU INTERVALLI --------------------------------------------------------------------------------------
|
||||
@@ -838,6 +845,183 @@ VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin,
|
||||
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 --------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1569,10 +1753,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
else if ( n5AxisType == Move5Axis::ACROSS)
|
||||
nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra
|
||||
|
||||
int nSurfInd = 0 ;
|
||||
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
||||
double dSide = 0 ;
|
||||
|
||||
// punti di riferimento sul tool
|
||||
// tip del tool
|
||||
Point3d ptP1T ;
|
||||
@@ -1585,7 +1765,14 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
Vector3d vtDirTip = ptP2T - ptP1T ;
|
||||
bool bTopIsPivot = vtDirTop.IsSmall() ;
|
||||
bool bTipIsPivot = vtDirTip.IsSmall() ;
|
||||
bool bTopAndTipAreEquiverse = vtDirTop * vtDirTip > 0 ;
|
||||
bool bInverse = ! (bTopIsPivot || bTipIsPivot) && vtDirTop * vtDirTip < 0 ;
|
||||
|
||||
if ( bInverse)
|
||||
nTotSurf += 4 ;
|
||||
|
||||
int nSurfInd = 0 ;
|
||||
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
||||
double dSide = 0 ;
|
||||
|
||||
// box dell'intero volume spazzato, nel riferimento object oriented
|
||||
BBox3d bbVol ;
|
||||
@@ -1602,9 +1789,9 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
PNTVECTOR vPntTopStartBack(3) ;
|
||||
PNTVECTOR vPntTopEndBack(3) ;
|
||||
if ( nSub > 1) {
|
||||
if( bTopIsPivot)
|
||||
if ( bTopIsPivot)
|
||||
vtDirTop = vtDirTip ;
|
||||
if( bTipIsPivot)
|
||||
if ( bTipIsPivot)
|
||||
vtDirTip = vtDirTop ;
|
||||
// determino in che modo collegare il cilindro iniziale con quello finale
|
||||
Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ;
|
||||
@@ -1618,10 +1805,10 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
dSide = ( ptRefEnd - ptRefStart) * vtLs ;
|
||||
|
||||
// calcolo anche i vettori per le basi inferiori
|
||||
Vector3d vtTipBaseStart = -( vtLs ^ vtDirTip) ;
|
||||
Vector3d vtTipBaseStart = bInverse ? ( vtLs ^ vtDirTip) : -( vtLs ^ vtDirTip) ;
|
||||
vtTipBaseStart.Normalize() ;
|
||||
vtTipBaseStart *= dMinRad ;
|
||||
Vector3d vtTipBaseEnd = -( vtLe ^ vtDirTip) ;
|
||||
Vector3d vtTipBaseEnd = bInverse ? ( vtLe ^ vtDirTip) : -( vtLe ^ vtDirTip) ;
|
||||
vtTipBaseEnd.Normalize() ;
|
||||
vtTipBaseEnd *= dMinRad ;
|
||||
// aggiungo il primo punto per ognuno dei gruppi
|
||||
@@ -1671,20 +1858,24 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
|
||||
vector<PNTVECTOR> vvPtCtrl ;
|
||||
// superficie laterale sinistra
|
||||
CurveLine cLineLeftStart ; cLineLeftStart.Set( vPntTipStartFront.back(), vPntTopStartFront.back()) ;
|
||||
PtrOwner<CurveBezier> cBezLeftStart( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftStart, nDegU, bRat))) ;
|
||||
CurveLine cLineLeftEnd ; cLineLeftEnd.Set( vPntTipEndFront.back(), vPntTopEndFront.back()) ;
|
||||
PtrOwner<CurveBezier> cBezLeftEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftEnd, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezLeftStart->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntLeft = cBezLeftEnd->GetAllControlPoints() ;
|
||||
CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ;
|
||||
if ( bInverse)
|
||||
cLineLeftBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ;
|
||||
CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ;
|
||||
PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
|
||||
// superficie laterale destra
|
||||
CurveLine cLineRightStart ; cLineRightStart.Set( vPntTopStartFront.front(), vPntTipStartFront.front()) ;
|
||||
PtrOwner<CurveBezier> cBezRightStart( GetBasicCurveBezier( LineToBezierCurve( &cLineRightStart, nDegU, bRat))) ;
|
||||
CurveLine cLineRightEnd ; cLineRightEnd.Set( vPntTopEndFront.front(), vPntTipEndFront.front()) ;
|
||||
PtrOwner<CurveBezier> cBezRightEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineRightEnd, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezRightStart->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntRight = cBezRightEnd->GetAllControlPoints() ;
|
||||
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
|
||||
if ( bInverse)
|
||||
cLineRightBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
|
||||
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
|
||||
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
|
||||
if ( nSub == 1) {
|
||||
// superficie inferiore
|
||||
@@ -1749,43 +1940,83 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
if ( ! bTipIsPivot) {
|
||||
// inferiori
|
||||
if ( dSide > 0) {
|
||||
vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints());
|
||||
PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end());
|
||||
vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints());
|
||||
PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end());
|
||||
PNTVECTOR vPntTipEnd01 = cBezTipStartF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
|
||||
PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints() ;
|
||||
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 {
|
||||
PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTipEnd01.rbegin(), vPntTipEnd01.rend());
|
||||
PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend());
|
||||
PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTipEnd02.rbegin(), vPntTipEnd02.rend());
|
||||
PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend());
|
||||
PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
|
||||
PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.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) {
|
||||
// superiori
|
||||
if ( dSide > 0) {
|
||||
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
|
||||
PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end());
|
||||
vvPtCtrl.emplace_back(cBezTopStartB2->GetAllControlPoints());
|
||||
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end());
|
||||
PNTVECTOR vPntTopEnd01 = cBezTopStartB1->GetAllControlPoints() ;
|
||||
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
|
||||
PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
|
||||
PNTVECTOR vPntTopEnd02 = cBezTopStartB2->GetAllControlPoints() ;
|
||||
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
|
||||
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
|
||||
}
|
||||
else {
|
||||
PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTopEnd01.rbegin(), vPntTopEnd01.rend());
|
||||
PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend());
|
||||
PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTopEnd02.rbegin(), vPntTopEnd02.rend());
|
||||
PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend());
|
||||
PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTopEnd01.rbegin(), vPntTopEnd01.rend()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
|
||||
PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.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()) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1794,36 +2025,74 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
if ( ! bTipIsPivot) {
|
||||
// inferiori
|
||||
if ( dSide > 0) {
|
||||
PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTip01.rbegin(), vPntTip01.rend());
|
||||
PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend());
|
||||
PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTip02.rbegin(), vPntTip02.rend());
|
||||
PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend());
|
||||
PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
|
||||
PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.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 {
|
||||
vvPtCtrl.emplace_back(cBezTipStartF1->GetAllControlPoints());
|
||||
PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end());
|
||||
vvPtCtrl.emplace_back(cBezTipStartF2->GetAllControlPoints());
|
||||
PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end());
|
||||
PNTVECTOR vPntTip01 = cBezTipStartF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
|
||||
PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints() ;
|
||||
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
|
||||
if ( dSide > 0) {
|
||||
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTop01.rbegin(), vPntTop01.rend());
|
||||
PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend());
|
||||
PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints();
|
||||
vvPtCtrl.emplace_back(vPntTop02.rbegin(), vPntTop02.rend());
|
||||
PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints();
|
||||
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend());
|
||||
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.emplace_back( vPntTop01.rbegin(), vPntTop01.rend()) ;
|
||||
else
|
||||
vvPtCtrl.emplace_back( vPntTop01.begin(), vPntTop01.end()) ;
|
||||
PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints() ;
|
||||
if ( ! bInverse)
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.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 {
|
||||
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
|
||||
@@ -1839,23 +2108,43 @@ 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 superici verticali end 1
|
||||
// chiudo il volume con le superici verticali end front 1
|
||||
vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntEnd1 = cBezTopEndF1->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd1.begin(), vPntEnd1.end()) ;
|
||||
// chiudo il volume con le superici verticali end 2
|
||||
PNTVECTOR vPntEndF1 = cBezTopEndF1->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF1.begin(), vPntEndF1.end()) ;
|
||||
// chiudo il volume con le superici verticali end front 2
|
||||
vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntEnd2 = cBezTopEndF2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd2.begin(), vPntEnd2.end()) ;
|
||||
PNTVECTOR vPntEndF2 = cBezTopEndF2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF2.begin(), vPntEndF2.end()) ;
|
||||
if ( bInverse) {
|
||||
// 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 1
|
||||
// chiudo il volume con le superici verticali start back 1
|
||||
vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntStart1 = cBezTopStartB1->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart1.begin(), vPntStart1.end()) ;
|
||||
// chiudo il volume con le superfici verticali start 2
|
||||
PNTVECTOR vPntStartB1 = cBezTopStartB1->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB1.begin(), vPntStartB1.end()) ;
|
||||
// chiudo il volume con le superfici verticali start back 2
|
||||
vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntStart2 = cBezTopStartB2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart2.begin(), vPntStart2.end()) ;
|
||||
PNTVECTOR vPntStartB2 = cBezTopStartB2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB2.begin(), vPntStartB2.end()) ;
|
||||
if ( bInverse) {
|
||||
// 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
|
||||
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) {
|
||||
@@ -1937,6 +2226,11 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ;
|
||||
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 B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ;
|
||||
Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ;
|
||||
@@ -1985,6 +2279,11 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
++ nSurfInd ;
|
||||
}
|
||||
|
||||
#if SAVETRIMMINGTOOL
|
||||
if ( nGrid == 0)
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\VirtualMilling\\5axisAdvanced\\marmo sottosquadra\\volume.nge") ;
|
||||
#endif
|
||||
|
||||
// scorro tutti gli spilloni interessati
|
||||
int j = 0 ;
|
||||
int nLastForwardJ = -1 ;
|
||||
|
||||
+1
-1
@@ -1155,7 +1155,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::Translate( const Vector3d & vtMove)
|
||||
Voronoi::Translate( const Vector3d& vtMove)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
Reference in New Issue
Block a user