Compare commits

...

83 Commits

Author SHA1 Message Date
Riccardo Elitropi 6be67258d2 EgtGeomKernel (Nst_SurfFr) :
- Modifiche stilistiche e cambio di versione.
2026-03-31 14:27:01 +02:00
Riccardo Elitropi 6c76943bf4 Merge commit '9306f5be9d43c0978d7b8d4707ca31d6cd475674' into Nst_SurfFr 2026-03-31 12:39:24 +02:00
Daniele Bariletti 9306f5be9d EgtGeomKernel :
- correzioni alla gestione dei loop.
2026-03-31 09:13:21 +02:00
Riccardo Elitropi 944ce79776 Merge commit '007ed1701c76ba7e1e648e3afcc4cdc61046b2c5' into Nst_SurfFr 2026-03-30 18:19:25 +02:00
Riccardo Elitropi 313c735956 EgtGeomKernel (Nst_SurfFr) :
- migliorata e raffinata la classe CAvSurfFrMove.
2026-03-30 18:19:13 +02:00
Dario Sassi 007ed1701c EgtGeomKernel 3.1c6 :
- ricompilazione con cambio versione.
2026-03-30 17:56:23 +02:00
Riccardo Elitropi 7385709bb4 EgtGeomKernel :
- in CalcPocketing piccola modifica a casi forzati dei trapezi.
2026-03-30 16:52:46 +02:00
Riccardo Elitropi da4cd4c482 EgtGeomKernel (Nst_SurfFr) :
- primo commit per CAv tra Regioni Piane con loop interni e Interferenza tra Regioni Piane.
2026-03-27 18:39:41 +01:00
Daniele Bariletti dee744725c EgtGeomKernel :
- rimossi try/catch dalla classe SurfFlatRegion.
- rimosso ricalcolo delle autointersezioni in AddSimpleExtLoop e AddSimpleIntLoop.
2026-03-27 15:11:28 +01:00
Daniele Bariletti 2aca943de4 EgtGeomKernel :
- estrapolata funzione per l'intersezione tra superficie di bezier 3x1 con una linea.
2026-03-26 12:42:05 +01:00
Daniele Bariletti 25f6bae120 EgtGeomKernel :
- pulizia codice.
2026-03-25 15:53:21 +01:00
Daniele Bariletti c92d841011 EgtGeomKernel :
- piccola correzione.
2026-03-25 15:07:40 +01:00
Daniele Bariletti 398c8c430a Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-03-25 12:38:17 +01:00
Daniele Bariletti 79dc8f8fc2 EgtGeomKernel :
- correzione alla chainCurves.
2026-03-25 12:38:12 +01:00
Riccardo Elitropi 1545bc07cd EgtGeomKernel 3.1c5 :
- Aggiunto controllo dimensioni Zmap per versioni a 32Bit.
2026-03-24 15:58:51 +01:00
Riccardo Elitropi 44edef378a EgtGeomKernel :
- in VolZmap migliorata la funzione RemoveFins.
2026-03-23 19:15:35 +01:00
Daniele Bariletti 679efc22e8 EgtGeomKernel :
- correzione alla MakeUniform nella ricostruzione della parte di trim nella striscia corrente.
2026-03-23 17:22:45 +01:00
Daniele Bariletti 1076dc54dc Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-03-20 13:41:33 +01:00
Daniele Bariletti e091f253d0 EgtGeomKernel :
- nella IntersCurveCurve non vengono mai cancellate info delle intersezioni durante il merge.
2026-03-20 13:41:13 +01:00
Dario Sassi 3206961b88 EgtGeomKernel :
- ricompilazione per cambio nome a metodo di VolZmap da EraseFins a RemoveFins.
2026-03-19 19:30:04 +01:00
Riccardo Elitropi 48b2029d19 EgtGeomKernel :
- aggiunta funzione EraseFins per gli Zmap ( prima versione semplice).
2026-03-19 18:45:38 +01:00
Daniele Bariletti a2ca0ac6f7 EgtGeomKernel 3.1c4 :
- cambio versione.
2026-03-19 15:36:09 +01:00
Daniele Bariletti 4155dd3e5a Merge branch 'NewIntersCurveCurve' 2026-03-19 15:34:59 +01:00
Daniele Bariletti 5a3b7e311c Merge remote-tracking branch 'origin/master' into NewIntersCurveCurve 2026-03-19 14:48:18 +01:00
Daniele Bariletti 991586a880 EgtGeomKernel :
- piccola aggiunta.
2026-03-19 14:45:14 +01:00
Daniele Bariletti de4165889a EgtGeomKernel :
- IntersCurveCurve: eliminata le intersezioni puntuali rimanenti vicine a overlap; corretto scorrimento delle intersezioni durante il merge.
2026-03-19 12:57:11 +01:00
Daniele Bariletti 42c5ffb014 EgtGeomKernel :
- correzioni e migliorie a IntersCurveCurve.
2026-03-19 10:33:18 +01:00
Dario Sassi e394615f84 EgtGeomKernel :
- in Polygon3d::FromPlaneTrimmedWithBox piccola correzione su parametro di tolleranza ignorato.
2026-03-17 18:12:01 +01:00
Riccardo Elitropi 1008ba4229 EgtGeomKernel 3.1c3 :
- Migliorata e corretta funzione MakeUniform per VolZMap.
2026-03-17 13:10:18 +01:00
Daniele Bariletti f4328430b9 EgtGeomKernel :
- revert manuale di una modifica in IntersCurveCurve.
2026-03-17 09:22:06 +01:00
Daniele Bariletti 1d6bc847da EgtGeomKernel 3.1c2 :
- cambio versione.
2026-03-17 08:56:41 +01:00
Daniele Bariletti d76beb09ee EgtGeomKernel :
- correzione alla GetChainedCurves
- aggiunto parametro alla GetSide della DistPointCurve
- migliorie alla IntersCurveCurve.
2026-03-16 17:01:48 +01:00
Dario Sassi 026436b914 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2026-03-15 18:31:34 +01:00
Dario Sassi ebc5fd7ee7 EgtGeomKernel :
- aggiunto INVISIBLE tra i colori predefiniti.
2026-03-15 18:28:23 +01:00
Daniele Bariletti 82a211753e EgtGeomKernel :
- correzione al VM 5 assi con movimenti che fanno perno.
2026-03-12 16:41:19 +01:00
Daniele Bariletti a258e9cb31 EgtGeomKernel :
- piccola correzione alla richiesta del box di una bezier.
2026-03-10 13:24:40 +01:00
Daniele Bariletti 157885f71a EgtGeomKernel 3.1c1 :
- cambio versione.
2026-03-10 09:05:59 +01:00
Daniele Bariletti f227a9cba7 Merge branch 'NewMakeUniform' 2026-03-10 09:04:16 +01:00
Daniele Bariletti 39360eefd7 EgtGeomKernel :
- raffinamento finale della intersCompoCompo.
2026-03-06 17:25:50 +01:00
Daniele Bariletti 6b5fb15c9b EgtGeomKernel :
- piccola correzione alla IntersCurveCurve.
2026-03-06 12:37:26 +01:00
Daniele Bariletti 4e698d4049 EgtGeomKernel :
- spostato rilevamento spike nelle intersezioni tra curve.
- pulizia codice.
2026-03-05 17:33:55 +01:00
Daniele Bariletti e20bd7fd0c Merge branch 'master' into NewMakeUniform 2026-03-04 15:55:39 +01:00
Daniele Bariletti 7e62acf351 EgtGeomKernel :
- aggiunta funzione per richiedere Part e Shell cui appartiene una faccia.
2026-03-04 15:55:25 +01:00
Daniele Bariletti 421bc2eb3b EgtGeomKernel :
- correzione alla make uniform.
2026-03-04 15:24:33 +01:00
Daniele Bariletti db98fa5d5a Merge branch 'master' into NewMakeUniform 2026-03-03 17:10:06 +01:00
Daniele Bariletti 5f28258d16 EgtGeomKernel :
- migliorie e correzioni all'importazione delle bezier.
- tolto limite alle bezier per rivoluzione.
2026-03-03 17:09:30 +01:00
Daniele Bariletti 8f06488b33 EgtGeomKernel :
- miglioramento all'intersezione tra curve.
2026-02-27 16:52:55 +01:00
Riccardo Elitropi ac7ba1b12c EgtGeomKernel :
- in CalcPocketing piccola miglioria su tolleranza trapezi.
2026-02-25 16:56:30 +01:00
Dario Sassi 67131a1482 EgtGeomKernel :
- salvato file come UTF-8.
2026-02-25 15:17:56 +01:00
Daniele Bariletti a92cba8697 Merge branch 'master' into NewMakeUniform 2026-02-24 12:36:18 +01:00
Daniele Bariletti 52cca7233e EgtGeomKernel 3.1b3 :
- correzione alle intersezioni tra curve.
- cambio versione.
2026-02-24 12:36:05 +01:00
Dario Sassi b2beed0fe0 EgtGeomKernel :
- ora From string per Color accette sia RGBA che RGB.
2026-02-24 08:39:23 +01:00
Daniele Bariletti 1f301b6100 Merge branch 'master' into NewMakeUniform 2026-02-23 16:26:55 +01:00
Daniele Bariletti c74ca4932f Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-23 16:26:29 +01:00
Daniele Bariletti fafcd67a2c EgtGeomKernel :
- correzione alle ruled guided.
2026-02-23 16:26:23 +01:00
Riccardo Elitropi 390cc3bd8b EgtGeomKernel :
- in trimming migliorata la gestione delle curve di sincronizzazione mediante interpolazione.
2026-02-23 15:47:14 +01:00
Daniele Bariletti b2ccda1b34 Merge branch 'master' into NewMakeUniform 2026-02-23 10:59:22 +01:00
Daniele Bariletti 69916e7756 EgtGeomKernel :
- correzione alla ruled guided.
2026-02-23 10:57:15 +01:00
Daniele Bariletti 3a7b6f1343 EgtGeomKernel :
- aggiunto flag Refined alla funzione GetLeaves.
2026-02-23 09:44:39 +01:00
Daniele Bariletti 71a054749c EgtGeomKernel :
- miglioria alla bezier ruled guided.
2026-02-23 09:35:04 +01:00
Daniele Bariletti 06d87d5c52 Merge branch 'master' into NewMakeUniform 2026-02-23 09:27:55 +01:00
Daniele Bariletti 6d544f93f4 EgtGeomKernel :
- miglioramento dell'approssimazione con curve di bezier.
2026-02-23 09:11:28 +01:00
Riccardo Elitropi 3c1a7ff1bb EgtGeomKernel 3.1b2 :
- in Trimming aggiunta prima versione di interpolazione per le curve di sincronizzazione.
2026-02-20 16:47:42 +01:00
Daniele Bariletti 73bedf4f55 EgkGeomKernel :
- correzione all'intersezione tra curva e piano.
2026-02-19 15:39:43 +01:00
Daniele Bariletti bae8d4651d EgtGeomKernel :
- piccola correzione alla Surf Bez Ruled Guided.
2026-02-19 11:50:44 +01:00
Riccardo Elitropi f9127ce64d EgtGeomKernel 3.1b1 :
- cambio di versione.
2026-02-17 10:00:13 +01:00
Riccardo Elitropi 86338db67d EgtGeomKernel :
- in CalcPocketing piccola correzione.
2026-02-17 09:24:18 +01:00
Daniele Bariletti 2438d1d23a Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-12 16:25:34 +01:00
Daniele Bariletti f790736fd7 EgtGeomKernel :
- modificata conversione da linea a bezier.
2026-02-12 16:25:28 +01:00
Daniele Bariletti 985b69ae33 EgtGeomKernel :
- correzione alla triangolazione delle bezier.
- riduzione della dimensione minima dei triangoli nelle surf bezier.
2026-02-12 16:17:11 +01:00
Riccardo Elitropi 6faf5ccde2 EgtGeomKernel 3.1a8 :
- in CalcPocketing migliorati i casi a trapezio.
2026-02-12 15:46:42 +01:00
Daniele Bariletti 2e129d7b06 EgtGeomKernel :
- tolto un argomento alla funzione ApproxCurveWithBezier.
2026-02-11 16:50:50 +01:00
Daniele Bariletti 2b7070e408 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-11 15:27:04 +01:00
Daniele Bariletti 571a24b419 EgtGeomKernel :
- migliorata approssimazione con curve di bezier.
2026-02-11 15:26:57 +01:00
Dario Sassi 5f132ae3d3 EgtGeomKernel 3.1a7 :
- ricompilazione con cambio versione.
2026-02-11 12:20:15 +01:00
Riccardo Elitropi fe5a09281e EgtGeomKernel :
- rimozione memory leaks in CalcPocketing.
2026-02-11 11:31:08 +01:00
Riccardo Elitropi b66522de33 EgtGeomKernel 3.1a6 :
- in CalcPocketing migliorati i casi ottimizzati a Trapezio.
2026-02-10 17:03:46 +01:00
Daniele Bariletti e87ef178c2 EgtGeomKernel :
- correzione alla distanza punto- curva di bezier.
2026-02-10 15:42:03 +01:00
Dario Sassi 0987496caf EgtGeomKernel :
- piccoli aggiustamenti.
2026-02-09 12:48:38 +01:00
Riccardo Elitropi 5ad9c48285 EgtGeomKernel :
- in Trimming rimozione memory Leaks.
2026-02-09 11:21:06 +01:00
Dario Sassi ec6eb3e645 EgtGeomKernel :
- modifica a Trimming
- sistemazioni estetiche varie.
2026-02-09 08:24:16 +01:00
Daniele Bariletti 64c3363426 Merge branch 'NewApproxWithBezier' 2026-02-06 17:28:46 +01:00
Daniele Bariletti b426ccc04d EgtGeomKernel :
- modifica alla funzione MakeUniform: utilizzo solo di curve anziché di flat region.
2026-02-03 16:22:57 +01:00
43 changed files with 3926 additions and 1063 deletions
+2 -2
View File
@@ -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) ;
+4
View File
@@ -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) ;
+2 -2
View File
@@ -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 ;
+257
View File
@@ -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 ;
}
+29
View File
@@ -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 ; }
} ;
+264 -74
View File
@@ -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,29 +3934,9 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
}
}
if ( bOkTrap) {
// calcolo eventuali uscite e ingressi
if ( pCrvRes->GetTempProp( 0) > 0) {
// 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() ;
if ( PockParam.bInvert)
pCrvRes->Invert() ;
// 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 ;
}
else {
if ( PockParam.bInvert)
pCrvRes->Invert() ;
}
AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ;
// imposto il flag di curva singola
pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
}
}
}
@@ -3798,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 ;
@@ -8916,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)) ;
}
//----------------------------------------------------------------------------
@@ -9218,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() ||
+1 -1
View File
@@ -169,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 ;
}
+2 -1
View File
@@ -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]) ) ;
+146 -94
View File
@@ -37,6 +37,7 @@
#define SAVECURVEPASSED 0
#define SAVELINEARAPPROX 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX
static int nCrvPassed = 0 ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
@@ -533,9 +534,8 @@ 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) ;
if( ! pCrvBezier->FromLine( *pCrvLine))
pCrvBezier->Init( nDeg, false) ;
if ( ! pCrvBezier->FromLine( *pCrvLine))
return nullptr ;
if ( bMakeRatOrNot)
pCrvBezier->MakeRational() ;
@@ -589,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)) ;
@@ -1147,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 ;
@@ -1173,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 ;
@@ -1312,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 ;
@@ -1328,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())
@@ -1360,7 +1367,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
}
}
if ( vLen.size() != 0) {
if ( ! vLen.empty()) {
if ( nEnd == 0)
nEnd = nPoints - 1 ;
Vector3d vtStartDir = V_INVALID ;
@@ -1402,9 +1409,9 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
int nPoints = nLast - nFirst + 1 ;
if ( nPoints < 2)
return false ;
if( ssize(vParam) == 0)
if ( vParam.empty())
vParam.resize( nPoints) ;
if( vParam[nFirst] == 0 && vParam[nLast] == 1)
if ( vParam[nFirst] == 0 && vParam[nLast] == 1)
return true ;
vParam[nFirst] = 0 ;
for ( int i = nFirst + 1 ; i <= nLast ; ++i) {
@@ -1420,8 +1427,8 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
//----------------------------------------------------------------------------
ICurveBezier*
ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, const Vector3d& vtStartDir, const Vector3d& vtEndDir,
const DBLVECTOR& vParam)
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 ;
@@ -1435,7 +1442,7 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
pCrvBez->SetControlPoint( 0, pt0) ;
pCrvBez->SetControlPoint( 3, pt3) ;
Eigen::Vector2d mA ;
if( nPoints > 4) {
if ( nPoints > 4) {
// risoluzione sistema
Eigen::Matrix2d mC ; mC.setZero() ;
Eigen::Vector2d mX ; mX.setZero() ;
@@ -1461,16 +1468,14 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
}
// 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)
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 ;
}
double alpah1 = mA(0) ;
double alpha2 = mA(1) ;
Point3d pt1 = pt0 + vtStartDir * mA(0) ;
Point3d pt2 = pt3 + vtEndDir * mA(1) ;
pCrvBez->SetControlPoint( 1, pt1) ;
@@ -1480,14 +1485,15 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
//----------------------------------------------------------------------------
bool
CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr)
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) {
if ( dErrTemp > dErr) {
dErr = dErrTemp ;
nPointMaxErr = i ;
}
@@ -1498,19 +1504,21 @@ CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int
//----------------------------------------------------------------------------
ICurve*
FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, 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)
{
ParamByLen(vPnt, vParam, nFirst, nLast) ;
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
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
// questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione
double dCorr = 1 ;
do {
Vector3d vtDer1, vtDer2 ;
@@ -1525,32 +1533,50 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
}
}
// fit della curva
pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vNextDer[nFirst], vPrevDer[nLast], vParam)) ;
if( IsNull( pCrvBez) || ! pCrvBez->IsValid())
// 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\\first_approx.nge") ;
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 && dErr > dTol) {
// 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)
if ( ( nIter == 10 && dErr > dTol) || dErr > dErrPrec || dErrPrec - dErr < dErrPrec / 20)
bSplit = true ;
// 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) {
if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) ||
! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol)))
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 ;
}
@@ -1561,17 +1587,15 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
if ( pCrvFit->GetCurveCount() > 0)
return Release( pCrvFit) ;
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
return Release( pCrvBez) ;
else
return nullptr ;
}
static int nCrvPassed = 0 ;
//----------------------------------------------------------------------------
ICurve*
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
{
#if SAVECURVEPASSED
@@ -1591,47 +1615,48 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ;
#endif
CurveByInterp cbi ;
PNTVECTOR vPnt ;
PNTVECTOR vPntOverSampling ;
Point3d pt ; plApprox.GetFirstPoint( pt) ;
do {
if ( ssize(vPnt) != 0) {
vPnt.push_back( Media(vPnt.back(), pt,1./3.)) ;
vPnt.push_back( Media(vPnt.back(), pt,2./3.)) ;
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) ;
cbi.AddPoint( pt) ;
} while ( plApprox.GetNextPoint( pt)) ;
// calcolo la curvatura nei vari punti per identificare zone a curvatura costante
DBLVECTOR vCrvVal( ssize(vPnt)) ;
DBLVECTOR vRad ( ssize( vPnt)) ;
for( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) {
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()) ;
double dCurvature = dR > 0 ? 1. / dR : 0 ;
double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * ( vtA ^ vtB).Len()) ;
vRad[i] = dR ;
vCrvVal[i] = dCurvature ;
}
vCrvVal[0] = vCrvVal[1] ;
vCrvVal.back() = vCrvVal.end()[-2] ;
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 dCurvaturePrec = vCrvVal[0] ;
double dRadPrec = vRad[0] ;
int nStart = 0 ;
int nEnd = 1 ;
double dRatio = 1.5 ;
while ( nStart < ssize( vPnt) - 1) {
dCurvaturePrec = vCrvVal[nEnd] ;
while ( nEnd < ssize( vPnt) - 1 && abs( vCrvVal[nEnd] - dCurvaturePrec) < 0.1) {
dCurvaturePrec = vCrvVal[nEnd] ;
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, nEnd) ;
vConstCurv.emplace_back( nStart * 3, nEnd * 3) ;
nStart = nEnd ;
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
if( ssize(vConstCurv) == 0)
if ( vConstCurv.empty())
vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ;
int nPoints = ssize( vPnt) ;
@@ -1643,22 +1668,40 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
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) {
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) {
for ( INTINT iiSE : vConstCurv) {
nFirst = iiSE.first ;
nLast = iiSE.second ;
//definisco la bezier che vado a raffinare iterativamente
PtrOwner<ICurve> pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ;
if( IsNull( pCApprox) || ! pCApprox->IsValid())
return nullptr ;
if( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
// 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) ;
@@ -1668,7 +1711,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
bool
CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints)
{
if( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
if ( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
dErr = INFINITO ;
return false ;
}
@@ -1753,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 ;
@@ -1767,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]) ) {
@@ -1776,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 ;
@@ -1792,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()) ;
}
}
@@ -1823,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) {
@@ -1834,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 ;
@@ -1859,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 ;
@@ -1876,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 ;
@@ -2072,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 ;
@@ -2444,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 ;
}
@@ -2471,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 ;
}
@@ -2532,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 ;
}
@@ -2562,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 ;
}
@@ -2596,7 +2639,7 @@ ResetCurveVoronoi( const ICurve& crvC)
bool
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
{
if( ssize( vCrv) == 1)
if ( ssize( vCrv) == 1)
return true ;
ChainCurves chainCrv ;
// modifico direttamente le curve passate in input
@@ -2613,25 +2656,34 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
INTVECTOR vIds ;
Point3d ptStart = ORIG ;
while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) {
ICurveComposite* pFirstCrv = vCrv[abs(vIds[0]) - 1] ;
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) {
bool bInvert = false ;
if( nId < 0)
bInvert = false ;
if ( nId < 0)
bInvert = true ;
nId = abs( nId) - 1 ;
if( bInvert)
if ( nId == nFirst)
continue ;
if ( bInvert)
vCrv[nId]->Invert() ;
if( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
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) ;
while( c > -1) {
if( IsNull( vCrv[c]))
int c = ssize( vCrv) - 1 ;
while ( c > -1) {
if ( IsNull( vCrv[c]))
vCrv.erase( vCrv.begin() + c) ;
--c ;
}
return true ;
}
}
+3 -4
View File
@@ -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 ;
}
+15 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 ;
}
}
+69
View File
@@ -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 ;
} ;
BIN
View File
Binary file not shown.
+2
View File
@@ -284,6 +284,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<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" />
@@ -353,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" />
+6
View File
@@ -570,6 +570,9 @@
<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">
@@ -1256,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">
+449 -130
View File
@@ -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,22 +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[i].IciB[ki].dU > m_Info[j].IciB[kj].dU + EPS_PARAM)
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[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[j].IciB[kj].dU < m_Info[i].IciB[ki].dU - EPS_PARAM)
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) ;
}
@@ -399,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
@@ -422,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) ;
@@ -458,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
@@ -466,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) ;
@@ -508,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 &&
@@ -517,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) ;
}
@@ -541,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)) {
@@ -560,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) ;
}
}
}
@@ -585,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 ;
@@ -594,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 ;
@@ -603,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 ;
@@ -612,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 ;
@@ -624,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 ;
}
}
}
@@ -697,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)
@@ -728,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) {
@@ -742,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,
@@ -810,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
//----------------------------------------------------------------------------
@@ -883,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 ;
@@ -912,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
@@ -964,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 ;
}
@@ -976,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 ;
}
@@ -1002,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
@@ -1016,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 ;
}
@@ -1032,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 ;
}
@@ -1082,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
@@ -1155,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 ;
+3
View File
@@ -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 ;
+6 -6
View File
@@ -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 ;
}
@@ -736,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 ;
}
-2
View File
@@ -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 ;}) ;
+357 -19
View File
@@ -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
View File
@@ -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) ;
}
//----------------------------------------------------------------------------
+99 -52
View File
@@ -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
+14 -7
View File
@@ -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
View File
@@ -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) ;
+261 -136
View File
@@ -45,10 +45,12 @@
#include "/EgtDev/Extern/Eigen/Dense"
#define SAVEFAILEDTRIANGULATION 0
#define SAVEISO 0
#define SAVEREBUILTISO 0
#define SAVERULEDISO 0
#define SAVERULEDGUIDEDISO 0
#if SAVEFAILEDTRIANGULATION || SAVEISO || SAVERULEDISO || SAVERULEDGUIDEDISO
#define SAVEMATCHCURVES 0
#define SAVEFAILEDTREE 0
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES || SAVEFAILEDTREE
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
@@ -876,8 +878,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc)
m_bTrimmed = true ;
m_pTrimReg = sbSrc.m_pTrimReg->Clone() ;
}
#ifndef SAVEFAILEDTRIANGULATION
if( sbSrc.GetAuxSurf() != nullptr)
#if ! SAVEFAILEDTRIANGULATION && ! SAVEFAILEDTREE
if ( sbSrc.GetAuxSurf() != nullptr)
m_pSTM = sbSrc.GetAuxSurf()->Clone() ;
#endif
for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) {
@@ -1075,7 +1077,7 @@ SurfBezier::Load( NgeReader& ngeIn)
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize(vCrv) ; ++i)
for ( int i = 0 ; i < ssize(vCrv) ; ++i)
vGeo.push_back( vCrv[i]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\ruled\\rebuild\\isoCrv.nge") ;
#endif
@@ -1122,7 +1124,7 @@ bool
SurfBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
{
// basta approssimato
if ( ( nFlag & BBF_EXACT) == 0) {
if ( ( nFlag & BBF_EXACT) == 0 && ! m_bTrimmed) {
for ( int i = 0 ; i < GetDim() ; ++ i) {
Point3d ptTemp = m_vPtCtrl[i] ;
ptTemp.ToGlob( frRef) ;
@@ -1820,7 +1822,7 @@ SurfBezier::GetAuxSurf( void) const
}
}
// eseguo calcolo
m_pSTM = GetApproxSurf( s_dAuxSurfTol, 100 * EPS_SMALL, false) ;
m_pSTM = GetApproxSurf( s_dAuxSurfTol, 10 * EPS_SMALL, false) ;
++nSurf ;
if ( m_pSTM != nullptr)
m_pSTM->SetTempParam( s_dAuxSurfTol) ;
@@ -1855,13 +1857,13 @@ SurfBezier::GetAuxSurfRefined( void) const
}
}
// eseguo calcolo
m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 100 * EPS_SMALL, true) ;
m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 10 * EPS_SMALL, true) ;
if ( m_pSTMRefined != nullptr)
m_pSTMRefined->SetTempParam( s_dAuxSurfRefinedTol) ;
return m_pSTMRefined ;
}
#if SAVEFAILEDTRIANGULATION
#if SAVEFAILEDTRIANGULATION || SAVEFAILEDTREE
static int nErr = 0 ;
#endif
@@ -1898,8 +1900,12 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons
Point3d ptMin = get<0>( vTrees[i]) ;
Point3d ptMax = get<1>( vTrees[i]) ;
Tree.SetSurf( this, ptMin, ptMax) ;
if( ! Tree.BuildTree( dTol, dSideMin)) {
if ( ! Tree.BuildTree( dTol, dSideMin)) {
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface parametric space couldn't be split in cells") ;
#if SAVEFAILEDTREE
SaveGeoObj( Clone(),"D:\\Temp\\bezier\\not_triangulated\\" + ToString( nErr) + ".nge") ;
++nErr ;
#endif
return nullptr ;
}
if ( ! Tree.GetPolygons( vvPL, vvPL3d, m_mCCEdge, m_vCCLoop, bUpdateEdges))
@@ -2175,7 +2181,7 @@ SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangula
//----------------------------------------------------------------------------
bool
SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined) const
{
Tree Tree ;
if ( ! Tree.SetSurf( this))
@@ -2186,7 +2192,10 @@ SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
Point3d ptMin = get<0>( vTrees[i]) ;
Point3d ptMax = get<1>( vTrees[i]) ;
Tree.SetSurf( this, ptMin, ptMax) ;
Tree.BuildTree( s_dAuxSurfTol, 100 * EPS_SMALL) ;
if ( ! bRefined)
Tree.BuildTree( s_dAuxSurfTol, 10 * EPS_SMALL) ;
else
Tree.BuildTree( s_dAuxSurfRefinedTol, 10 * EPS_SMALL) ;
vector<Cell> vCells ;
Tree.GetLeaves( vCells) ;
for ( int k = 0 ; k < int( vCells.size()) ; ++ k) {
@@ -3029,10 +3038,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
dPtStm.GetMinDistTriaIndex( nTriaIndex) ;
// se ho trovato un nuovo triangolo, controllo che questo fosse nella lista dei triangoli equidistanti dal punto originale
// sennò ripeto il conto con meno scostamento
if( nTriaOld != nTriaIndex) {
if ( nTriaOld != nTriaIndex) {
auto iter = find( vnT.begin(), vnT.end(),nTriaIndex) ;
int nIdTria = distance( vnT.begin(), iter) ;
if( nIdTria > ssize( vnT) - 1) {
if ( nIdTria > ssize( vnT) - 1) {
ptI2 = ptI + ( ptIPrevOrNext - ptI) * 5 * EPS_SMALL ;
DistPointSurfTm dPtStm2( ptI2, *pSurfTm) ;
dPtStm2.GetMinDistTriaIndex( nTriaIndex) ;
@@ -4138,7 +4147,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr)
// se composita verifico che curve siano con lo stesso grado e uniformi come tipo
bool bRat = false ;
int nDegU = 3 ;
if( pCrv->GetType() != CRV_COMPO) {
if ( pCrv->GetType() != CRV_COMPO) {
CC.AddCurve( CurveToBezierCurve( pCrv, nDegU, bRat)) ;
}
else {
@@ -4151,7 +4160,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr)
}
}
if( CC.GetCurveCount() == 0 || ! CC.IsValid())
if ( CC.GetCurveCount() == 0 || ! CC.IsValid())
return false ;
// riempio la matrice dei punti di controllo
@@ -4222,46 +4231,73 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V
if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL)
dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ;
// se sto facendo una rivoluzione e la curva è piana, controllo che la curva non attraversi l'asse
if ( abs( dMove) < EPS_SMALL ) {
Plane3d plPlane ;
if ( pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) {
BBox3d b3Crv ;
pCurve->GetLocalBBox( b3Crv) ;
double dAxLen = b3Crv.MaxDistFromPoint( ptAx) ;
CurveLine crvAx ;
crvAx.Set( ptAx - dAxLen * vtAx, ptAx + dAxLen * vtAx) ;
IntersCurveCurve icc( *pCurve, crvAx) ;
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ;
for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) {
IntCrvCrvInfo iccInfo ;
icc.GetIntCrvCrvInfo( i, iccInfo) ;
// controllo che sia una vera intersezione in 3D, altrimenti passo alla successiva
if ( ! AreSamePointApprox( iccInfo.IciA[0].ptI, iccInfo.IciB[0].ptI))
continue ;
// se è il punto di inizio o di fine va bene e procedo
if ( AreSamePointApprox( ptStart, iccInfo.IciA[0].ptI) || AreSamePointApprox( ptEnd, iccInfo.IciA[0].ptI))
continue ;
// se la curva oltrepassa l'asse allora mi fermo, se tocca l'asse, ma resta dallo stesso lato, allora vado avanti
if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy)
return false ;
}
}
}
//// se sto facendo una rivoluzione e la curva è piana, controllo che la curva non attraversi l'asse
//CurveComposite ccNotTraversing ;
//if ( abs( dMove) < EPS_SMALL ) {
// Plane3d plPlane ;
// if ( pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) {
// BBox3d b3Crv ;
// pCurve->GetLocalBBox( b3Crv) ;
// double dAxLen = b3Crv.MaxDistFromPoint( ptAx) ;
// CurveLine crvAx ;
// crvAx.Set( ptAx - dAxLen * vtAx, ptAx + dAxLen * vtAx) ;
// IntersCurveCurve icc( *pCurve, crvAx) ;
// Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
// Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ;
// bool bOk = true ;
// double dSplit = 0 ;
// for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) {
// IntCrvCrvInfo iccInfo ;
// icc.GetIntCrvCrvInfo( i, iccInfo) ;
// // controllo che sia una vera intersezione in 3D, altrimenti passo alla successiva
// if ( ! AreSamePointApprox( iccInfo.IciA[0].ptI, iccInfo.IciB[0].ptI))
// continue ;
// // se è il punto di inizio o di fine va bene e procedo
// if ( AreSamePointApprox( ptStart, iccInfo.IciA[0].ptI) || AreSamePointApprox( ptEnd, iccInfo.IciA[0].ptI))
// continue ;
// // se la curva oltrepassa l'asse allora terrò solo la parte prima dell'asse, se tocca l'asse va bene
// if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy) {
// bOk = false ;
// dSplit = iccInfo.IciA[0].dU ;
// }
// }
// converto in bezier la curva iniziale
// // tengo solo la parte della curva fino all'intersezione con l'asse
// if ( ! bOk) {
// ccNotTraversing.AddCurve( pCurve->CopyParamRange( 0, dSplit)) ;
// }
// else
// ccNotTraversing.CopyFrom( pCurve) ;
// }
//}
//// converto in bezier la curva iniziale
// CurveComposite CrvU ;
//// se la curva è già una bezier singola la tengo, sennò la converto
// if ( ccNotTraversing.GetType() != CRV_BEZIER)
// CrvU.AddCurve( CurveToBezierCurve( &ccNotTraversing, 3, false)) ;
// else {
// if ( ! GetCurveBezier(&ccNotTraversing)->IsRational())
// CrvU.AddCurve( ccNotTraversing.Clone()) ;
// else {
// ICurveBezier* pCrvCopy = GetCurveBezier( ccNotTraversing.Clone()) ;
// if ( ! CrvU.AddCurve( EditBezierCurve( pCrvCopy, 3, false)))
// return false ;
// }
// }
// converto in bezier la curva iniziale
CurveComposite CrvU ;
// se la curva è già una bezier singola la tengo, sennò la converto
if ( pCurve->GetType() != CRV_BEZIER)
CrvU.AddCurve( CurveToBezierCurve( pCurve, 3, true)) ;
else {
if ( GetCurveBezier(pCurve)->IsRational())
if ( ! GetCurveBezier( pCurve)->IsRational())
CrvU.AddCurve( pCurve->Clone()) ;
else {
ICurveBezier* pCrvCopy = GetCurveBezier( pCurve->Clone()) ;
pCrvCopy->MakeRational() ;
CrvU.AddCurve( pCrvCopy) ;
if ( ! CrvU.AddCurve( EditBezierCurve( pCrvCopy, 3, true)))
return false ;
}
}
if ( ! CrvU.IsValid())
@@ -5071,7 +5107,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
if ( j == vMatch1.size())
bAdvance1 = false ;
// se trovo che ho uno spigolo allora procedo con la gestione spigoli
if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
// se ho uno spigolo su entrambe le curve forzo l'accoppiamento
bAdvance0 = true ;
bPerfectMatch = true ;
@@ -5080,7 +5116,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
ptJoint0 = vPnt1[j+1] ;
ptJoint1 = vPnt0[c+1] ;
}
else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
else if (( vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
bAdvance0 = false ;
bAdvance1 = false ;
}
@@ -5241,28 +5277,28 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// bAdvance0 = true ;
// bAdvance1 = true ;
// int nParam0, nParam1 ;
// while( bAdvance0) {
// while ( bAdvance0) {
// dParam0 = vMatch0[c_temp].second ;
// nParam0 = int( round( dParam0)) ;
// dParam1 = vMatch1[nParam0].second ;
// nParam1 = int( round( dParam1)) ;
// if( abs( nParam1 - c_temp) <= 2)
// if ( abs( nParam1 - c_temp) <= 2)
// bAdvance0 = false ;
// else
// ++ c_temp ;
// }
// while( bAdvance1) {
// while ( bAdvance1) {
// dParam1 = vMatch1[j_temp].second ;
// nParam1 = int( round( dParam1)) ;
// dParam0 = vMatch0[nParam1].second ;
// nParam0 = int( round( dParam0)) ;
// if( abs( nParam0 - j_temp) <= 2)
// if ( abs( nParam0 - j_temp) <= 2)
// bAdvance1 = false ;
// else
// ++ j_temp ;
// }
// // se non sono avanzato, allora mi basta accoppiare i due punti in questione
// if( c_temp == c || j_temp == j) {
// if ( c_temp == c || j_temp == j) {
// ++c ;
// ++j ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
@@ -5292,13 +5328,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// PtrOwner<ICurve> pCC1 ;
// int nPointsBetween0 = 0 ;
// int nPointsBetween1 = 0 ;
// if( bAdvance0 && bAdvance1) {
// if ( bAdvance0 && bAdvance1) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = c_temp - c ;
// nPointsBetween1 = j_temp - j ;
// }
// else if( bAdvance0){
// else if ( bAdvance0) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ;
// nPointsBetween0 = c_temp - c ;
@@ -5306,7 +5342,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// if ( bIntParam0)
// nPointsBetween1 -= 1 ;
// }
// else if( bAdvance1){
// else if ( bAdvance1) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = int( dParam1) - ( c + 1) ;
@@ -5337,7 +5373,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// int nJBefore = j ;
// //debug
// while ( bSplitToAdd) {
// if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
// if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
// LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ;
// return false ;
// }
@@ -5384,13 +5420,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ;
// }
// // aggiorno i dati dell'ultima aggiunta
// if( bAdvance0 && ! bAdvance1) {
// if ( bAdvance0 && ! bAdvance1) {
// ptLastPointMatch0 = vMatch0[c_temp].first ;
// dLastParamMatch0 = vMatch0[c_temp].second ;
// ptLastPointMatch1 = vPnt0[c_temp] ;
// dLastParamMatch0 = c_temp ;
// }
// else if( ! bAdvance0 && bAdvance1) {
// else if ( ! bAdvance0 && bAdvance1) {
// ptLastPointMatch0 = vPnt1[j_temp] ;
// dLastParamMatch0 = j_temp ;
// ptLastPointMatch1 = vMatch1[j_temp].first ;
@@ -5406,7 +5442,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// }
}
}
bAdvance = ! (c >= int(vMatch0.size()) - 1 && j >= int(vMatch1.size()) - 1) ;
bAdvance = ! ( c >= ssize( vMatch0) - 1 && j >= ssize( vMatch1) - 1) ;
}
// applico effettivamente gli split
@@ -5501,7 +5537,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
vector<IGeoObj*> vGeo ;
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
for( int i = 0 ; i < ssize( vCrv) ; ++i) {
for ( int i = 0 ; i < ssize( vCrv) ; ++i) {
vGeo.push_back( vCrv[i]->Clone()) ;
}
vector<Color> vCol( ssize( vCrv)) ;
@@ -5883,8 +5919,8 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
{
// vCrv è il vettore delle isocurve (nel parametro V) che si vogliono forzare per la creazione della rigata tra Curve0 e Curve1
//controllo che siano entrambe chiuse o entrambe aperte
if( pCurve0->IsClosed() ^ pCurve1->IsClosed())
// controllo che siano entrambe chiuse o entrambe aperte
if ( pCurve0->IsClosed() != pCurve1->IsClosed())
return false ;
bool bClosed = pCurve0->IsClosed() ;
@@ -5934,22 +5970,95 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
Point3d ptU1 = vCrv[i].second ;
double dParam0 ; CrvU0.GetParamAtPoint( ptU0, dParam0) ;
double dParam1 ; CrvU1.GetParamAtPoint( ptU1, dParam1) ;
if( bClosed && (dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) && (dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if( ! bFirstAdded) {
dParam0 = 0 ;
dParam1 = 0 ;
bFirstAdded = true ;
if ( bClosed) {
// curve di sync che sono esattamente sugli start/end di churve chiuse
if ( ( dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) &&
( dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if ( ! bFirstAdded) {
dParam0 = 0 ;
dParam1 = 0 ;
bFirstAdded = true ;
}
else {
dParam0 = nSpanU0 ;
dParam1 = nSpanU1 ;
}
}
else {
dParam0 = nSpanU0 ;
dParam1 = nSpanU1 ;
// curve si sync che hanno solo uno dei due punti su un punto di start/end, ma NON sono a cavallo dello start
else if ( ( dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL)) {
if ( ( nSpanU1 - dParam1) > dParam1)
dParam0 = 0 ;
else
dParam0 = nSpanU0 ;
}
else if (( dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if ( ( nSpanU0 - dParam0) > dParam0)
dParam1 = 0 ;
else
dParam1 = nSpanU1 ;
}
//else if ( abs(( nSpanU0 - dParam0) / nSpanU0 - ( nSpanU1 - dParam1) / nSpanU1) > 0.1) {
// // gestisco il cambio di start se ho una sync a cavallo di start e end
// // quella sync diventa il nuovo start
//}
}
vIso.emplace_back( i, dParam0, dParam1) ;
}
sort( vIso.begin(), vIso.end()) ;
// sposto lo start sulla prima curva di sync che trovo
if ( bClosed) {
double dNewStart0 = vIso[0].dParam0 ;
double dNewStart1 = vIso[0].dParam1 ;
CrvU0.ChangeStartPoint( dNewStart0) ;
CrvU1.ChangeStartPoint( dNewStart1) ;
vIso[0].dParam0 = 0 ;
vIso[0].dParam1 = 0 ;
double dCeil0 = ceil( dNewStart0) ;
double dFloor0 = floor( dNewStart0) ;
double dCeil1 = ceil( dNewStart1) ;
double dFloor1 = floor( dNewStart1) ;
vPnt0.pop_back() ;
rotate( vPnt0.begin(), vPnt0.begin() + int( dCeil0), vPnt0.end()) ;
vPnt1.pop_back() ;
rotate( vPnt1.begin(), vPnt1.begin() + int( dCeil1), vPnt1.end()) ;
if ( abs( dNewStart0 - round( dNewStart0)) > EPS_SMALL) {
Point3d ptNewStart ; CrvU0.GetStartPoint( ptNewStart) ;
vPnt0.insert( vPnt0.begin(), ptNewStart) ;
++nSpanU0 ;
}
if ( abs( dNewStart1 - round( dNewStart1)) > EPS_SMALL) {
Point3d ptNewStart ; CrvU1.GetStartPoint( ptNewStart) ;
vPnt1.insert( vPnt1.begin(), ptNewStart) ;
++nSpanU1 ;
}
for ( int i = 1 ; i < ssize( vIso) ; ++i) {
if ( vIso[i].dParam0 >= dCeil0)
vIso[i].dParam0 -= dFloor0 ;
else if ( vIso[i].dParam0 <= dFloor0)
vIso[i].dParam0 += nSpanU0 - dCeil0 ;
else
CrvU0.GetParamAtPoint( vCrv[vIso[i].nCrv].first, vIso[i].dParam0) ;
if ( vIso[i].dParam1 >= dCeil1)
vIso[i].dParam1 -= dFloor1 ;
else if ( vIso[i].dParam1 <= dFloor1)
vIso[i].dParam1 += nSpanU1 - dCeil1 ;
else
CrvU1.GetParamAtPoint( vCrv[vIso[i].nCrv].second, vIso[i].dParam1) ;
}
}
else {
vIso.emplace_back( -1, 0, 0) ;
rotate( vIso.begin(), vIso.begin() + ssize(vIso) - 1, vIso.end()) ;
}
// se manca aggiungo la coppia finale
if ( vIso.back().dParam0 != nSpanU0 || vIso.back().dParam1 != nSpanU1)
vIso.emplace_back( -1, nSpanU0, nSpanU1) ;
// scorro vIso per verificare che non ci siano curve che si intersecano
int c = 0 ;
dLastParam0 = vIso[c].dParam0 ;
@@ -5965,12 +6074,25 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
dLastParam0 = 0 ;
dLastParam1 = 0 ;
if( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0)
if ( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0)
vPairs.emplace_back( 0, 0) ;
for ( int i = 0 ; i < ssize( vIso) ; ++i) {
const BIPOINT& pCrv = vCrv[vIso[i].nCrv] ;
Point3d ptU0 = pCrv.first ;
Point3d ptU1 = pCrv.second ;
Point3d ptU0, ptU1 ;
if ( vIso[i].nCrv != -1) {
const BIPOINT& pCrv = vCrv[vIso[i].nCrv] ;
ptU0 = pCrv.first ;
ptU1 = pCrv.second ;
}
else {
if ( vIso[i].dParam0 == 0 && vIso[i].dParam1 == 0) {
CrvU0.GetStartPoint( ptU0) ;
CrvU1.GetStartPoint( ptU1) ;
}
else {
CrvU0.GetEndPoint( ptU0) ;
CrvU1.GetEndPoint( ptU1) ;
}
}
double& dParam0 = vIso[i].dParam0 ;
double& dParam1 = vIso[i].dParam1 ;
// se sono vicino ad un'intero allora considero il parametro intero ( uno split già esistente)
@@ -6037,7 +6159,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
return false ;
}
// se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split
if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) {
if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_SMALL && vdParamPos0[c0] < 1) {
++c0 ;
++c1 ;
++nLastParam0 ;
@@ -6052,6 +6174,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSplit1 = vdSplit1.size() ;
}
else if ( dPar = round( dPar) ; dPar > nLastParam1){
++ c1 ;
++ nLastParam1 ;
}
++nLastParam0 ;
@@ -6066,6 +6189,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSplit0 = vdSplit0.size() ;
}
else if ( dPar = round( dPar) ; dPar > nLastParam0){
++ c0 ;
++ nLastParam0 ;
}
++nLastParam1 ;
@@ -6125,11 +6249,12 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSpanU0 = CrvU0.GetCurveCount() ;
nSpanU1 = CrvU1.GetCurveCount() ;
// aggiungo l'ultima coppia
vPairs.emplace_back( nSpanU0, nSpanU1) ;
// aggiungo l'ultima coppia se necessario
if ( vPairs.back().first != nSpanU0 || vPairs.back().second != nSpanU1)
vPairs.emplace_back( nSpanU0, nSpanU1) ;
// trovo il numero di span che dovrà avere la superficie
int nSpanU = int(vPairs.size()) - 1 ;
int nSpanU = int( vPairs.size()) - 1 ;
int nSecondRowInd = nDegU * nSpanU + 1 ;
// inizializzo la superficie
@@ -6186,7 +6311,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
vector<IGeoObj*> vGeo ;
ICURVEPOVECTOR vCrvIso ;
GetAllPatchesIsocurves( false, vCrvIso) ;
for( int i = 0 ; i < ssize( vCrvIso) ; ++i) {
for ( int i = 0 ; i < ssize( vCrvIso) ; ++i) {
vGeo.push_back( vCrvIso[i]->Clone()) ;
}
vector<Color> vCol( ssize( vCrvIso)) ;
@@ -6208,36 +6333,36 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
//----------------------------------------------------------------------------
bool
SurfBezier::RemoveCollapsedSpans()
SurfBezier::RemoveCollapsedSpans( void)
{
double dTol = EPS_SMALL ;
//controllo se ho delle span collassate e le rimuovo
if( m_nSpanU > 1 || m_nSpanV > 1) {
if ( m_nSpanU > 1 || m_nSpanV > 1) {
CalcPoles() ;
if( ! m_vbPole[2]) {
if ( ! m_vbPole[2]) {
// scorro i punti della prima riga
INTVECTOR vnCollapsedSpan ;
for( int i = 0 ; i < m_nSpanU ; ++i) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
bool bSamePoint = true ;
Point3d ptFirst = m_vPtCtrl[m_nDegU * i] ;
// cerco se trovo tutti i punti in U coincidenti in una delle Span
for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol))
for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol))
bSamePoint = false ;
}
if( bSamePoint) {
if ( bSamePoint) {
// se trovo un'altra riga collassata do per scontato che tutta span sia collassata
ptFirst = m_vPtCtrl[GetInd( m_nDegU * i, 1)] ;
for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol))
for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol))
bSamePoint = false ;
}
if( bSamePoint)
if ( bSamePoint)
vnCollapsedSpan.push_back( i) ;
}
}
int nOldSpanU = m_nSpanU ;
if( ! vnCollapsedSpan.empty()) {
if ( ! vnCollapsedSpan.empty()) {
// cancello le span che risultano collassate
int nNewSpanU = m_nSpanU - ssize( vnCollapsedSpan) ;
int nNewDim = ( m_nDegU * nNewSpanU + 1) * ( m_nDegV * m_nSpanV + 1) ;
@@ -6245,21 +6370,21 @@ SurfBezier::RemoveCollapsedSpans()
DBLVECTOR vNewWeight( nNewDim) ;
int nCurrSkipInd = -1 ;
int nCurrSkip = -1 ;
for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
nCurrSkipInd = 0 ;
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
for( int i = 0 ; i < m_nSpanU ; ++i) {
if( i != nCurrSkip) {
for( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
if ( i != nCurrSkip) {
for ( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
vNewCtrlPnt[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
if( m_bRat) {
if ( m_bRat) {
vNewWeight[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
}
}
}
else {
++nCurrSkipInd ;
if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
nCurrSkip = -1 ;
else
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
@@ -6270,32 +6395,32 @@ SurfBezier::RemoveCollapsedSpans()
// vettori dei punti e numero di span
ISurfFlatRegion* pSFRTrim = nullptr ;
bool bTrimmed = m_bTrimmed ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTrim = GetTrimRegion() ;
m_pTrimReg = nullptr ;
}
Init( m_nDegU, m_nDegV, nNewSpanU, m_nSpanV, m_bRat) ;
m_vPtCtrl = vNewCtrlPnt ;
if( m_bRat)
if ( m_bRat)
m_vWeCtrl = vNewWeight ;
if( bTrimmed) {
if ( bTrimmed) {
// elimino le span di troppo dallo spazio parametrico
PtrOwner<ISurfFlatRegion> pNewTrim( pSFRTrim->Clone()) ;
for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
int nSpan = vnCollapsedSpan[i] ;
// tolgo tutta la parte a destra della colonna da togliere
PtrOwner<ISurfFlatRegion> pSFRCut ( GetSurfFlatRegionRectangle( ( nOldSpanU - nSpan) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ;
if( nSpan != 0) {
if ( nSpan != 0) {
pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ;
pNewTrim->Subtract( *pSFRCut) ;
}
if( pNewTrim->IsValid()) {
if ( pNewTrim->IsValid()) {
// ritaglio dal parametrico originale la parte a destra della colonna da eliminare e la incollo alla parte a sinistra
PtrOwner<ISurfFlatRegion> pRightPart( pSFRTrim->Clone()) ;
pSFRCut.Set( GetSurfFlatRegionRectangle( ( nSpan + 1) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ;
pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ;
if( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) {
if( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid())
if ( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) {
if ( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid())
break ;
}
}
@@ -6307,30 +6432,30 @@ SurfBezier::RemoveCollapsedSpans()
}
}
if( ! m_vbPole[1]) {
if ( ! m_vbPole[1]) {
// scorro i punti della prima colonna
INTVECTOR vnCollapsedSpan ;
for( int i = 0 ; i < m_nSpanV ; ++i) {
for ( int i = 0 ; i < m_nSpanV ; ++i) {
bool bSamePoint = true ;
Point3d ptFirst = m_vPtCtrl[GetInd( 0, i * m_nDegV)] ;
// cerco se trovo tutti i punti in U coincidenti in una delle Span
for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol))
for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol))
bSamePoint = false ;
}
if( bSamePoint) {
if ( bSamePoint) {
// se trovo un'altra colonna collassata do per scontato che tutta span sia collassata
ptFirst = m_vPtCtrl[GetInd( 1, i * m_nDegV)] ;
for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol))
for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol))
bSamePoint = false ;
}
if( bSamePoint)
if ( bSamePoint)
vnCollapsedSpan.push_back( i) ;
}
}
int nOldSpanV = m_nSpanV ;
if( ! vnCollapsedSpan.empty()) {
if ( ! vnCollapsedSpan.empty()) {
// cancello le span che risultano collassate
int nNewSpanV = m_nSpanV - ssize( vnCollapsedSpan) ;
int nNewDim = ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * nNewSpanV + 1) ;
@@ -6338,12 +6463,12 @@ SurfBezier::RemoveCollapsedSpans()
DBLVECTOR vNewWeight( nNewDim) ;
int nCurrSkipInd = 0 ;
int nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
if( nIndV / m_nDegV != nCurrSkip) {
for( int i = 0 ; i < m_nSpanU ; ++i) {
for( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
if ( nIndV / m_nDegV != nCurrSkip) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
for ( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
vNewCtrlPnt[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
if( m_bRat) {
if ( m_bRat) {
vNewWeight[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
}
}
@@ -6352,7 +6477,7 @@ SurfBezier::RemoveCollapsedSpans()
else {
nIndV += m_nDegV - 1 ;
++nCurrSkipInd ;
if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
nCurrSkip = -1 ;
else
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
@@ -6362,32 +6487,32 @@ SurfBezier::RemoveCollapsedSpans()
// vettori dei punti e numero di span
ISurfFlatRegion* pSFRTrim = nullptr ;
bool bTrimmed = m_bTrimmed ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTrim = GetTrimRegion() ;
m_pTrimReg = nullptr ;
}
Init( m_nDegU, m_nDegV, m_nSpanU, nNewSpanV, m_bRat) ;
m_vPtCtrl = vNewCtrlPnt ;
if( m_bRat)
if ( m_bRat)
m_vWeCtrl = vNewWeight ;
if( bTrimmed) {
if ( bTrimmed) {
// elimino le span di troppo dallo spazio parametrico
PtrOwner<ISurfFlatRegion> pNewTrim( pSFRTrim->Clone()) ;
for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
int nSpan = vnCollapsedSpan[i] ;
// tolgo tutta la parte a sopra la riga da togliere
PtrOwner<ISurfFlatRegion> pSFRCut ( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nOldSpanV - nSpan) * SBZ_TREG_COEFF)) ;
if( nSpan != 0) {
if ( nSpan != 0) {
pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ;
pNewTrim->Subtract( *pSFRCut) ;
}
if( pNewTrim->IsValid()) {
if ( pNewTrim->IsValid()) {
// ritaglio dal parametrico originale la parte sopra la riga da eliminare e la incollo alla parte sotto la riga
PtrOwner<ISurfFlatRegion> pUpperPart( pSFRTrim->Clone()) ;
pSFRCut.Set( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nSpan + 1) * SBZ_TREG_COEFF)) ;
pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ;
if( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) {
if( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid())
if ( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) {
if ( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid())
break ;
}
}
@@ -6405,7 +6530,7 @@ SurfBezier::RemoveCollapsedSpans()
//----------------------------------------------------------------------------
bool
SurfBezier::SwapParameters()
SurfBezier::SwapParameters( void)
{
// inverto il parametro U con il parametro V
// salvo i vecchi dati
@@ -6415,7 +6540,7 @@ SurfBezier::SwapParameters()
int nDegV = m_nDegU ;
bool bTrimmed = m_bTrimmed ;
PtrOwner<ISurfFlatRegion> pSFRTRim ;
if( m_bTrimmed) {
if ( m_bTrimmed) {
pSFRTRim.Set( GetTrimRegion()) ;
m_pTrimReg = nullptr ;
}
@@ -6423,16 +6548,16 @@ SurfBezier::SwapParameters()
// creo il vettore dei punti di controllo
PNTVECTOR vNewCtrlPt( GetDim()) ;
DBLVECTOR vNewWeight( GetDim()) ;
for( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) {
for( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) {
for ( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) {
for ( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) {
vNewCtrlPt[i * ( nDegU * nSpanU + 1) + j] = m_vPtCtrl[GetInd(i,j)] ;
if( m_bRat)
if ( m_bRat)
vNewWeight[i * ( nDegU * nSpanU + 1) + j] = m_vWeCtrl[GetInd(i,j)] ;
}
}
Init( nDegU, nDegV, nSpanU, nSpanV, m_bRat) ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTRim->Mirror( ORIG, Vector3d(1,-1)) ;
SetTrimRegion( *pSFRTRim) ;
}
@@ -6440,4 +6565,4 @@ SurfBezier::SwapParameters()
m_vWeCtrl = vNewWeight ;
return true ;
}
}
+5 -5
View File
@@ -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 ;
@@ -148,11 +148,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
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 BIPNTVECTOR& vCrv) ;
bool RemoveCollapsedSpans() override ;
bool SwapParameters() ;
bool RemoveCollapsedSpans( void) override ;
bool SwapParameters( void) ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+188 -35
View File
@@ -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 ;
}
//----------------------------------------------------------------------------
+2
View File
@@ -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} ;
+13
View File
@@ -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) ;
+29
View File
@@ -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)
+1
View File
@@ -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
+10 -10
View File
@@ -36,25 +36,25 @@ class Tool
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
bool 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) ; }
+109 -21
View File
@@ -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 ;
+26 -17
View File
@@ -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.
} ;
} ;
+475 -205
View File
File diff suppressed because it is too large Load Diff
+253 -49
View File
@@ -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 -5
View File
@@ -81,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 ;
@@ -151,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
@@ -226,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) ;
@@ -262,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
@@ -486,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 {
+79 -14
View File
@@ -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 ;
+383 -83
View File
@@ -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,6 +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 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 ;
@@ -1601,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) ;
@@ -1617,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
@@ -1670,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
@@ -1748,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()) ;
}
}
@@ -1793,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());
@@ -1838,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)) {
@@ -1936,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] ;
@@ -1984,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
View File
@@ -1155,7 +1155,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//---------------------------------------------------------------------------
bool
Voronoi::Translate( const Vector3d & vtMove)
Voronoi::Translate( const Vector3d& vtMove)
{
if ( ! IsValid())
return false ;