Compare commits
255 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2023ba3f7d | |||
| 27c1823a54 | |||
| f111827545 | |||
| 7cdc1ba5a3 | |||
| 1d68a1ee8e | |||
| 6f7b614c3a | |||
| f02f29c543 | |||
| 06cfe1bb96 | |||
| 736353bbac | |||
| f4b3312672 | |||
| 3178bb5f27 | |||
| 552ce70231 | |||
| c2a79b2665 | |||
| f72c949563 | |||
| bdcb00d1bd | |||
| 42fcb1847b | |||
| a7b36280f3 | |||
| cdef3931be | |||
| d3f2587cc2 | |||
| d343f474e4 | |||
| b7fee9696e | |||
| 4f48337f62 | |||
| 96907d5952 | |||
| 3c5d2571fe | |||
| 7005bf43a4 | |||
| 4726cf4d35 | |||
| b971eda771 | |||
| 3ded6fe87d | |||
| 5195c23dfb | |||
| 5f1255a625 | |||
| 82accd45c1 | |||
| e46768b14b | |||
| 32307efd78 | |||
| e84df69f6f | |||
| 669f38a731 | |||
| afef5597b2 | |||
| 4a0bd638fa | |||
| 4bfb38b9d5 | |||
| 0d62cd9bbd | |||
| 913d5f60ca | |||
| 3dddbdf5cd | |||
| 3245f7fe75 | |||
| f144cda136 | |||
| d374e133f0 | |||
| 0c435a646d | |||
| d0ac226753 | |||
| d92344f2bb | |||
| 51c584c6c4 | |||
| 176bbec8a7 | |||
| a508da8b18 | |||
| 91ca84f77a | |||
| d27fdb9904 | |||
| 3b816e2a45 | |||
| 11a46ca58c | |||
| 6e0aec3bec | |||
| 11dd35af44 | |||
| 17fe5f0c9c | |||
| c8e2d88bb7 | |||
| c6ac9fbcf8 | |||
| e636e75b76 | |||
| a01346577f | |||
| 61a5e53351 | |||
| 739c17b4b6 | |||
| 144ef16b0b | |||
| 58c635cb9d | |||
| a39b9a7651 | |||
| 75889983de | |||
| e4a14b629c | |||
| 3640a17632 | |||
| 2a3f809e4e | |||
| d7dd7b9f80 | |||
| cd48e2de3b | |||
| 8f43efe282 | |||
| 025bcbba1d | |||
| d0131deb40 | |||
| 1325f83291 | |||
| 961acdbc76 | |||
| 6789d74abc | |||
| 062c92377e | |||
| 383f4c7abd | |||
| 4cc6161918 | |||
| c0ebbee347 | |||
| e3b4f5bd2d | |||
| 5df3ab6d98 | |||
| 63fb9a638b | |||
| d62d6946c3 | |||
| 7f0237ced4 | |||
| 23621630d5 | |||
| b3abcf73c3 | |||
| 1219e9bd80 | |||
| dced59b9a1 | |||
| 3bf2972089 | |||
| 6dd3ea5cc2 | |||
| 592a92ebdb | |||
| 1321742afe | |||
| f1f93124a0 | |||
| c8e9d1e012 | |||
| 7b0cd0939b | |||
| 3b5ab5089b | |||
| b36d919d8f | |||
| e22a207f03 | |||
| 24dbef52c9 | |||
| 5498b1e25c | |||
| 86851bb67e | |||
| b99e12c56f | |||
| 129b1b919e | |||
| 711c250cfc | |||
| 0f05216474 | |||
| c57b7c95c1 | |||
| 62e041ed8c | |||
| 2983454ce2 | |||
| 6d5046cb6d | |||
| 91fcf43da9 | |||
| aef1a57e1c | |||
| 71316bac6a | |||
| f1c4f06461 | |||
| 412bbd2a8b | |||
| be64cedfc3 | |||
| 2a6b35d658 | |||
| f51c5c36d0 | |||
| 5599901185 | |||
| fb235bf985 | |||
| 717d7a3fe3 | |||
| c91f468dce | |||
| 1f36657efd | |||
| b70ad5c808 | |||
| da56ef91fd | |||
| 9bd7a152d7 | |||
| 5c287d49bb | |||
| 942f15b49d | |||
| 20b61cda42 | |||
| b1b1d6d434 | |||
| c7ad32ef30 | |||
| 6016db837e | |||
| 2051e0b5d9 | |||
| fddb3f5707 | |||
| 096dd84511 | |||
| e16a2078fc | |||
| e388ae34e3 | |||
| b64c747082 | |||
| 8afa3ae47d | |||
| 1eba68e95b | |||
| 047b339006 | |||
| acd7415835 | |||
| a48460ef76 | |||
| 8ab3896e3a | |||
| 2d481c8a71 | |||
| 7968a4e5ed | |||
| 39d295f412 | |||
| 0bf2cc2a77 | |||
| 433f486091 | |||
| fee6604d5e | |||
| c339fced5c | |||
| a87351778d | |||
| 42687457e0 | |||
| 4a541402da | |||
| ecef487746 | |||
| df483b5623 | |||
| e4d3f5f9a4 | |||
| 02e164dcdf | |||
| ead94e7915 | |||
| dfc3c29439 | |||
| ab538f4bf7 | |||
| 00b6f8583a | |||
| 4cf4a99107 | |||
| 137289e843 | |||
| e7b066e75e | |||
| cd0828f3e0 | |||
| 563697f840 | |||
| 61fc814528 | |||
| 7c90dbabea | |||
| 5ee0f3c373 | |||
| 098bdd0076 | |||
| 40b6da6b44 | |||
| b083dabc6b | |||
| 7fcc3ed42d | |||
| 4ed362f226 | |||
| 39d98f79fb | |||
| c79f7ba245 | |||
| 16354ff435 | |||
| f3a191dd62 | |||
| cb0a5092fb | |||
| 8730f55308 | |||
| 932e98d19c | |||
| 3a69dcfa79 | |||
| 5930674d4a | |||
| df6b20d97f | |||
| 4200af5296 | |||
| b0c9c5be2e | |||
| f2bb1deac4 | |||
| 94ec83aa60 | |||
| e183eec3ea | |||
| b179771ec9 | |||
| d7380a09c1 | |||
| afc316cd1d | |||
| b6f820258a | |||
| 116b605cb1 | |||
| 9f5ce42393 | |||
| 9716d93c15 | |||
| 3465179379 | |||
| c7aad8d917 | |||
| 8ddc1c70e1 | |||
| 5230261be8 | |||
| 8cc8d6eb03 | |||
| 7a95e4c5a3 | |||
| 1c0f182bbc | |||
| 736e20e599 | |||
| c71c8e8c12 | |||
| 9c7a29f939 | |||
| 40bb15e46b | |||
| fb957b61d2 | |||
| 4da9dcb062 | |||
| 60f9302c3f | |||
| 2553f15e7b | |||
| e8d31f2020 | |||
| 4c693ccd60 | |||
| c550fb1848 | |||
| e49bd5a2a0 | |||
| 81be6ce7b9 | |||
| 2d6bf3d9dc | |||
| b2244b7f43 | |||
| 53dcd9c863 | |||
| 75f70d2b30 | |||
| 36b1df1a27 | |||
| 5a445c5c0b | |||
| db855ca99b | |||
| d79cb50aca | |||
| df7b4ff81f | |||
| 574041cf18 | |||
| ff2cc4f999 | |||
| 05c0b0a18b | |||
| 8ee5bc74d5 | |||
| 9286ab6535 | |||
| ffe3d44cac | |||
| dd23b848ac | |||
| d6f0fdac50 | |||
| cc4183a677 | |||
| c2bae56656 | |||
| ba75033f0a | |||
| c6e80a0b6a | |||
| fc18539472 | |||
| de7229aee7 | |||
| 2fc6c30c8f | |||
| 6af5591cf6 | |||
| 41cbe862e5 | |||
| 0aca5aeb07 | |||
| bdbd3583b8 | |||
| f03adb9206 | |||
| 529fa2e4a0 | |||
| acb0a5bd5e | |||
| 0247fe5e7c | |||
| 50bad83fba | |||
| 9c93d6c2f3 | |||
| 59755ec8a5 | |||
| 79dfb4ae87 |
@@ -1,12 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2024
|
||||
// EgalTech 2020-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 23.01.26 Versione : 3.1a3
|
||||
// Contenuto : Implementazione funzione verifica collisione tra
|
||||
// SurfTm e SurfTm.
|
||||
//
|
||||
// Modifiche : 13.11.20 LM Creazione modulo.
|
||||
// 24.03.24 DS Aggiunta TestSurfTmSurfTm.
|
||||
// 23.01.26 DS In TestSurfTmSurfTm aggiunto flag per collisione quando una delle due è chiusa e contiene l'altra.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -45,10 +46,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
pSrfB->GetLocalBBox( b3BoxB) ;
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxB.Expand( dSafeDist) ;
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
if ( ! b3BoxA.Overlaps( b3BoxB))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -61,13 +62,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
continue ;
|
||||
BBox3d b3BoxTriaA ;
|
||||
trTriaA.GetLocalBBox( b3BoxTriaA) ;
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Al termine della chiamata i TempInt dei triangoli valgono 0.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -84,14 +85,14 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// Se il triangolo adiacente al triangolo corrente su questo edge
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
int nAdjTriaTempFlag ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
continue ;
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
|
||||
return true ;
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -111,10 +112,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
}
|
||||
}
|
||||
// Non ho trovato collisioni fra triangoli delle superfici.
|
||||
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
|
||||
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
|
||||
if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA))
|
||||
return false ;
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
Point3d ptPointA, ptPointB ;
|
||||
pSrfA->GetFirstVertex( ptPointA) ;
|
||||
pSrfB->GetFirstVertex( ptPointB) ;
|
||||
@@ -127,7 +128,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist, bool bTestEnclosion)
|
||||
{
|
||||
// Recupero le superfici base
|
||||
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
|
||||
@@ -140,10 +141,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
pSrfB->GetLocalBBox( b3BoxB) ;
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxB.Expand( dSafeDist) ;
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
if ( ! b3BoxA.Overlaps( b3BoxB))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -156,13 +157,13 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
continue ;
|
||||
BBox3d b3BoxTriaA ;
|
||||
trTriaA.GetLocalBBox( b3BoxTriaA) ;
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Al termine della chiamata i TempInt dei triangoli valgono 0.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -179,14 +180,14 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// Se il triangolo adiacente al triangolo corrente su questo edge
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
int nAdjTriaTempFlag ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
continue ;
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
|
||||
return true ;
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -205,6 +206,25 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
pSrfB->SetTempInt( nTB, 1) ;
|
||||
}
|
||||
}
|
||||
// Non c'è interferenza
|
||||
// Se non richiesto test di inclusione, non c'è interferenza
|
||||
if ( ! bTestEnclosion)
|
||||
return false ;
|
||||
// Se la prima superficie è chiusa, verifico se include totalmente la seconda
|
||||
if ( pSrfA->IsClosed() && b3BoxA.Encloses( b3BoxB)) {
|
||||
Point3d ptPointB ;
|
||||
pSrfB->GetFirstVertex( ptPointB) ;
|
||||
DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ;
|
||||
if ( DistPoinBSrfA.IsPointInside() || DistPoinBSrfA.IsEpsilon( dSafeDist))
|
||||
return true ;
|
||||
}
|
||||
// Se la seconda superficie è chiusa, verifico se include totalmente la prima
|
||||
if ( pSrfB->IsClosed() && b3BoxB.Encloses( b3BoxA)) {
|
||||
Point3d ptPointA ;
|
||||
pSrfA->GetFirstVertex( ptPointA) ;
|
||||
DistPointSurfTm DistPoinASrfB( ptPointA, *pSrfB) ;
|
||||
if ( DistPoinASrfB.IsPointInside() || DistPoinASrfB.IsEpsilon( dSafeDist))
|
||||
return true ;
|
||||
}
|
||||
// Non c'è interferenza
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1
|
||||
// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 03.02.26 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
vPrevDer.clear() ;
|
||||
vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
vPrevDer.reserve( nSize) ;
|
||||
vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
|
||||
vPrevDer.push_back( vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = vPrevDer[0] ;
|
||||
vtNextDer = vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[1] + vPar[i+1], vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
vPrevDer.push_back( vtPrevDer) ;
|
||||
vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
vPrevDer.clear() ;
|
||||
vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
vPrevDer.reserve( nSize) ;
|
||||
vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
|
||||
vPrevDer.push_back( vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = vPrevDer[0] ;
|
||||
vtNextDer = vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
vPrevDer.push_back( vtPrevDer) ;
|
||||
vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -179,3 +181,6 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP
|
||||
}
|
||||
return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ;
|
||||
}
|
||||
|
||||
bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
|
||||
bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
|
||||
+536
-273
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -127,7 +127,7 @@ GetHSVFromColor( const Color& cCol)
|
||||
hsv.dSat = dDelta / dMax ;
|
||||
if ( cCol.GetRed() >= dMax) // tra giallo e magenta
|
||||
hsv.dHue = ( cCol.GetGreen() - cCol.GetBlue()) / dDelta ;
|
||||
else if( cCol.GetGreen() >= dMax) // tra ciano e giallo
|
||||
else if ( cCol.GetGreen() >= dMax) // tra ciano e giallo
|
||||
hsv.dHue = 2.0 + ( cCol.GetBlue() - cCol.GetRed()) / dDelta ;
|
||||
else // tra magenta e ciano
|
||||
hsv.dHue = 4.0 + ( cCol.GetRed() - cCol.GetGreen()) / dDelta ;
|
||||
|
||||
+2
-2
@@ -1294,7 +1294,7 @@ CurveArc::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveArc::SimpleOffset( double dDist, int nType)
|
||||
CurveArc::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1329,7 +1329,7 @@ CurveArc::SimpleOffset( double dDist, int nType)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType)
|
||||
CurveArc::MyExtendedOffset( double dDist, bool bAll)
|
||||
{
|
||||
// bAll == true fa accettare raggi nulli ==> da usare solo internamente
|
||||
// quando si è sicuri di aumentare subito il raggio o di cancellare
|
||||
|
||||
+4
-4
@@ -116,7 +116,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
@@ -178,8 +178,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
bool ChangeDeltaN( double dNewDeltaN) override ;
|
||||
bool ChangeAngCenter( double dNewAngCenDeg) override ;
|
||||
bool ChangeStartPoint( double dU) override ;
|
||||
bool ExtendedOffset( double dDist, int nType = OFF_FILLET) override
|
||||
{ return MyExtendedOffset( dDist, false, nType) ; }
|
||||
bool ExtendedOffset( double dDist) override
|
||||
{ return MyExtendedOffset( dDist, false) ; }
|
||||
bool ToExplementary( void) override ;
|
||||
bool Flip( void) override ;
|
||||
|
||||
@@ -200,7 +200,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
{ if ( ! CopyFrom( caSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "CurveArc : copy error")
|
||||
return *this ; }
|
||||
bool MyExtendedOffset( double dDist, bool bAll, int nType = OFF_FILLET) ;
|
||||
bool MyExtendedOffset( double dDist, bool bAll) ;
|
||||
bool MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, double dLinTol) const ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
+622
-140
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -33,5 +33,6 @@ bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ;
|
||||
bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ;
|
||||
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
|
||||
+119
-29
@@ -93,8 +93,11 @@ CurveBezier::Init( int nDeg, bool bIsRational)
|
||||
bool
|
||||
CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl)
|
||||
{
|
||||
// verifico validità indice
|
||||
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
// verifico validità indice e punto
|
||||
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg || ! ptCtrl.IsValid())
|
||||
return false ;
|
||||
|
||||
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore
|
||||
@@ -123,8 +126,11 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
|
||||
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL)
|
||||
// verifico che il punto sia valido e il peso non sia nullo o negativo
|
||||
if ( ! ptCtrl.IsValid() || dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
|
||||
return false ;
|
||||
|
||||
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
@@ -151,7 +157,7 @@ CurveBezier::SetControlWeight( int nInd, double dW)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL)
|
||||
if ( dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
@@ -267,7 +273,7 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
bool
|
||||
CurveBezier::FromLine( const ICurveLine& crLine)
|
||||
{
|
||||
if ( ! crLine.IsValid())
|
||||
if ( m_nStatus != OK || ! crLine.IsValid())
|
||||
return false ;
|
||||
double dWeight = 1 ;
|
||||
int nCount = 0 ;
|
||||
@@ -367,8 +373,11 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc)
|
||||
{
|
||||
if ( &cbSrc == this)
|
||||
return true ;
|
||||
if ( ! cbSrc.IsValid())
|
||||
return false ;
|
||||
if ( ! Init( cbSrc.m_nDeg, cbSrc.m_bRat))
|
||||
return false ;
|
||||
m_dParSing = cbSrc.m_dParSing ;
|
||||
m_vPtCtrl = cbSrc.m_vPtCtrl ;
|
||||
if ( cbSrc.m_bRat)
|
||||
m_vWeCtrl = cbSrc.m_vWeCtrl ;
|
||||
@@ -516,21 +525,21 @@ bool
|
||||
CurveBezier::Validate( void)
|
||||
{
|
||||
if ( m_nStatus == TO_VERIFY) {
|
||||
for ( const auto& ptP : m_vPtCtrl) {
|
||||
if ( ! ptP.IsValid()) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
for ( const auto& ptP : m_vPtCtrl) {
|
||||
if ( ! ptP.IsValid()) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( m_nStatus == TO_VERIFY) {
|
||||
for ( const auto& dWe : m_vWeCtrl) {
|
||||
if ( ! isfinite( dWe)) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
for ( const auto& dWe : m_vWeCtrl) {
|
||||
if ( ! isfinite( dWe)) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( m_nStatus == TO_VERIFY)
|
||||
m_nStatus = ( ( m_nDeg >= 1 && m_vPtCtrl.size() >= 2) ? OK : ERR) ;
|
||||
|
||||
@@ -1657,6 +1666,10 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
|
||||
ICurve*
|
||||
CurveBezier::CopyParamRange( double dUStart, double dUEnd) const
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
|
||||
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
||||
if ( dUStart < - EPS_PARAM || dUStart > 1 + EPS_PARAM ||
|
||||
dUEnd < - EPS_PARAM || dUEnd > 1 + EPS_PARAM)
|
||||
@@ -1799,6 +1812,10 @@ CurveBezier::TrimEndAtParam( double dUTrim)
|
||||
bool
|
||||
CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
||||
if ( dUStartTrim < - EPS_PARAM || dUStartTrim > 1 + EPS_PARAM ||
|
||||
dUEndTrim < - EPS_PARAM || dUEndTrim > 1 + EPS_PARAM)
|
||||
@@ -1808,19 +1825,19 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
return false ;
|
||||
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
|
||||
Point3d ptStart ;
|
||||
if( m_bRat)
|
||||
if ( m_bRat)
|
||||
GetPointD1D2( dUStartTrim, ptStart) ;
|
||||
// trim finale
|
||||
if ( ! TrimEndAtParam( dUEndTrim))
|
||||
return false ;
|
||||
// trim iniziale con il parametro opportunamente ricalcolato
|
||||
double dNewUStartTrim ;
|
||||
if( m_bRat)
|
||||
if ( m_bRat)
|
||||
GetParamAtPoint( ptStart, dNewUStartTrim) ;
|
||||
else
|
||||
dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
//trim iniziale
|
||||
if( ! TrimStartAtParam( dNewUStartTrim))
|
||||
if ( ! TrimStartAtParam( dNewUStartTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1830,6 +1847,10 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
bool
|
||||
CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// lunghezze negative vengono considerate nulle
|
||||
dLenTrim = max( dLenTrim, 0.) ;
|
||||
|
||||
@@ -1839,7 +1860,7 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
if( ! TrimStartAtParam( dUTrim))
|
||||
if ( ! TrimStartAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1849,6 +1870,10 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
bool
|
||||
CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// lunghezze negative vengono considerate nulle
|
||||
dLenTrim = max( dLenTrim, 0.) ;
|
||||
|
||||
@@ -1858,7 +1883,7 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
if( ! TrimEndAtParam( dUTrim))
|
||||
if ( ! TrimEndAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1868,6 +1893,10 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
bool
|
||||
CurveBezier::ExtendStartByLen( double dLenExt)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// la lunghezza deve essere positiva
|
||||
if ( dLenExt < - EPS_ZERO)
|
||||
return false ;
|
||||
@@ -1919,6 +1948,10 @@ CurveBezier::ExtendStartByLen( double dLenExt)
|
||||
bool
|
||||
CurveBezier::ExtendEndByLen( double dLenExt)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// la lunghezza deve essere positiva
|
||||
if ( dLenExt < - EPS_ZERO)
|
||||
return false ;
|
||||
@@ -2258,6 +2291,10 @@ CurveBezier::ResetVoronoiObject() const
|
||||
bool
|
||||
CurveBezier::MakeRational( void)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( m_bRat)
|
||||
return true ;
|
||||
// creo il vettore dei pesi e li setto tutti a 1
|
||||
@@ -2272,6 +2309,10 @@ CurveBezier::MakeRational( void)
|
||||
bool
|
||||
CurveBezier::MakeRationalStandardForm( void)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( ! m_bRat)
|
||||
return false ;
|
||||
double dW0 = m_vWeCtrl.front() ;
|
||||
@@ -2293,6 +2334,10 @@ CurveBezier::MakeRationalStandardForm( void)
|
||||
bool
|
||||
CurveBezier::MakeNonRational( double dTol)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( ! m_bRat)
|
||||
return true ;
|
||||
|
||||
@@ -2307,15 +2352,44 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
|
||||
bool bOk = true ;
|
||||
if ( ! bIsActualRat) {
|
||||
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
|
||||
for ( int p = 0 ; p < m_nDeg ; ++p) {
|
||||
Point3d pt = GetControlPoint( p) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
}
|
||||
// semplicemente tolgo il booleano della razionalità e i punti restano gli stessi
|
||||
m_bRat = false ;
|
||||
}
|
||||
else {
|
||||
// provo ad approssimare la curva di bezier con una controparte non razionale
|
||||
int nDeg = m_nDeg ;
|
||||
// se ho una curva razionale di grado 2 verifico se è un arco, in quel caso la converto in una curva di grado 3 non razionale con la funzione dedicata
|
||||
if ( nDeg == 2 && m_bRat) {
|
||||
// prendo due punti sulla curva e calcolo l'intersezione dei due assi dei segmenti formati da pt2-pt0 e pt3-pt1
|
||||
Point3d pt0 ; GetStartPoint( pt0) ;
|
||||
Point3d pt1 ; GetPointD1D2( 0.3, pt1) ;
|
||||
Point3d pt2 ; GetPointD1D2( 0.6, pt2) ;
|
||||
Point3d pt3 ; GetEndPoint( pt3) ;
|
||||
|
||||
Vector3d vtDir1 = pt2 - pt0 ;
|
||||
Vector3d vtDir2 = pt3 - pt1 ;
|
||||
Vector3d vtN = vtDir2 ^ vtDir1 ;
|
||||
|
||||
CurveLine cl1 ; cl1.Set( pt1, pt1 + (vtDir1 ^ vtN) * 5) ;
|
||||
CurveLine cl2 ; cl1.Set( pt2, pt2 + (vtDir2 ^ vtN) * 5) ;
|
||||
IntersLineLine ill( cl1, cl2, false) ;
|
||||
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||
Point3d ptCen = iccInfo.IciA[0].ptI ;
|
||||
|
||||
// se sia l'inizio che la fine della curva distano uguale dal punto di intersezione tra i due assi trovati allora la curva è un arco di circonferenza
|
||||
if ( abs(Dist( pt0, ptCen) - Dist( pt3, ptCen)) < EPS_SMALL) {
|
||||
PtrOwner<ICurveBezier> pNew ( ApproxArcCurveBezierWithSingleCubic( this, ptCen, vtN)) ;
|
||||
|
||||
if ( IsNull( pNew) || ! pNew->IsValid())
|
||||
return false ;
|
||||
Init( 3, false) ;
|
||||
for ( int i = 0 ; i < 3 ; ++i)
|
||||
SetControlPoint( i, pNew->GetControlPoint(i)) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
// punto di rientro in caso fallisca il primo tentativo
|
||||
retry :
|
||||
nDeg += 2 ;
|
||||
@@ -2338,7 +2412,7 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
Vector3d vDiff = vPntSampling[p] - pt ;
|
||||
double dErrLoc = vDiff.Len() ;
|
||||
if( dErrLoc > dErrMax)
|
||||
if ( dErrLoc > dErrMax)
|
||||
dErrMax = dErrLoc ;
|
||||
// aggiorno il vettore dei punti di controllo della nuova curva
|
||||
vPntCtrl[p] += vDiff ;
|
||||
@@ -2351,7 +2425,7 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
}
|
||||
|
||||
// calcolo l'errore di approssimazione sulla curva
|
||||
CalcBezierApproxError( this, pNewBez, dErr) ;
|
||||
CalcApproxError( this, pNewBez, dErr) ;
|
||||
bOk = dErr < dTol ;
|
||||
if ( bOk) {
|
||||
// aggiorno la curva di bezier originale con quella approssimata
|
||||
@@ -2372,14 +2446,30 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
bool
|
||||
CurveBezier::IsALine( void) const
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
Point3d ptStart ; GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; GetEndPoint( ptEnd) ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
Point3d ptCtrl = GetControlPoint( i) ;
|
||||
DistPointLine dpl( ptCtrl, ptStart, ptEnd) ;
|
||||
double dDist = 0 ; dpl.GetDist( dDist) ;
|
||||
if( dDist > EPS_SMALL)
|
||||
if ( dDist > EPS_SMALL)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PNTVECTOR
|
||||
CurveBezier::GetAllControlPoints( void) const
|
||||
{
|
||||
PNTVECTOR vPntCtrl ;
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return vPntCtrl ;
|
||||
|
||||
return m_vPtCtrl ;
|
||||
}
|
||||
+2
-1
@@ -116,7 +116,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override
|
||||
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
@@ -153,6 +153,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool MakeRationalStandardForm( void) override ;
|
||||
bool MakeNonRational( double dTol) override ;
|
||||
bool IsALine( void) const override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ; // non aggiunta in interfaccia
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+2
-201
@@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void)
|
||||
bool
|
||||
CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// pulisco i vettori delle tangenti
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByApprox::CalcBesselTangents( void)
|
||||
{
|
||||
// pulisco i vettori delle tangenti
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+34
-225
@@ -50,7 +50,37 @@ CurveByInterp::AddPoint( const Point3d& ptP)
|
||||
ICurve*
|
||||
CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
{
|
||||
// calcolo le tangenti
|
||||
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs)
|
||||
if ( nType == CUBIC_BEZIERS_LONG) {
|
||||
// creo la curva composita
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
//pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
|
||||
//debug
|
||||
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ;
|
||||
if ( IsNull(pCrv) || ! pCrv->IsValid())
|
||||
return nullptr ;
|
||||
return Release( pCrv) ;
|
||||
}
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le tangenti
|
||||
if ( nMethod == BESSEL) {
|
||||
if ( ! CalcBesselTangents())
|
||||
return nullptr ;
|
||||
@@ -110,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
bool
|
||||
CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
m_vPar.clear() ;
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByInterp::CalcBesselTangents( void)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
m_vPar.clear() ;
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
+15
-8
@@ -889,14 +889,21 @@ CurveComposite::Validate( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::TestClosure( void)
|
||||
CurveComposite::TestClosure( double dLinTol)
|
||||
{
|
||||
// se non è chiusa, esco subito
|
||||
if ( ! IsClosed())
|
||||
// se non valida o vuota, esco subito
|
||||
if ( m_nStatus != OK || m_CrvSmplS.empty())
|
||||
return true ;
|
||||
// se non è chiusa entro la tolleranza, esco subito
|
||||
Point3d ptStart, ptEnd ;
|
||||
if ( ! m_CrvSmplS.front()->GetStartPoint( ptStart) ||
|
||||
! m_CrvSmplS.back()->GetEndPoint( ptEnd) ||
|
||||
! AreSamePointEpsilon( ptStart, ptEnd, dLinTol))
|
||||
return true ;
|
||||
// se singola retta, esco subito
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_LINE)
|
||||
return true ;
|
||||
// verifico ed eventualmente aggiusto coincidenza punti estremi
|
||||
Point3d ptStart ; m_CrvSmplS.front()->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; m_CrvSmplS.back()->GetEndPoint( ptEnd) ;
|
||||
// se distanza superiore al limite ridotto forzo i punti a coincidere
|
||||
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
|
||||
// se un solo arco
|
||||
@@ -1707,7 +1714,7 @@ CurveComposite::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::SimpleOffset( double dDist, int nType)
|
||||
CurveComposite::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// se distanza di offset nulla, non devo fare alcunché
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
@@ -1729,7 +1736,7 @@ CurveComposite::SimpleOffset( double dDist, int nType)
|
||||
}
|
||||
|
||||
// eseguo l'offset nel piano XY
|
||||
bool bOk = SimpleOffsetXY( dDist, nType) ;
|
||||
bool bOk = SimpleOffsetXY( dDist, nType, dMaxAngExt) ;
|
||||
|
||||
// riporto la curva nel riferimento originale
|
||||
if ( bNeedRef)
|
||||
@@ -3046,7 +3053,7 @@ CurveComposite::ArcsToBezierCurves( void)
|
||||
// se arco, devo trasformare in una o più curve di Bezier
|
||||
if ( (*Iter)->GetType() == CRV_ARC) {
|
||||
// eseguo trasformazione
|
||||
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( (*Iter))) ;
|
||||
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( GetCurveArc( *Iter))) ;
|
||||
if ( IsNull( pNewCrv))
|
||||
return false ;
|
||||
// se risultato è singola curva
|
||||
|
||||
+3
-3
@@ -113,7 +113,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override ;
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
@@ -198,17 +198,17 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
return *this ; }
|
||||
bool RelocateFrom( CurveComposite& ccSrc) ;
|
||||
bool GetApproxLength( double& dLen) const ;
|
||||
bool TestClosure( double dLinTol = EPS_SMALL) ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveComposite& ccSrc) ;
|
||||
bool Validate( void) ;
|
||||
bool TestClosure( void) ;
|
||||
bool AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
|
||||
bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
|
||||
bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ;
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
|
||||
|
||||
+14
-10
@@ -19,6 +19,7 @@
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -30,14 +31,14 @@ static const int TP_IS_VERT_LINE = 1 ;
|
||||
static bool IsVerticalLine( const ICurve* pCrv, double* pdLenZ) ;
|
||||
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
||||
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
||||
CurveComposite& ccAux) ;
|
||||
static bool AddFirstLastVerticalLines( CurveComposite& ccOffs, double dLenVertFirst, double dLenVertLast) ;
|
||||
static bool MediaInternalAngleDeltaZ( CurveComposite& ccOffs) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite::SimpleOffsetXY( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+)
|
||||
CurveComposite ccCopy ;
|
||||
@@ -98,7 +99,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite ccTemp ;
|
||||
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrv2, ccTemp) ||
|
||||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrv2, ccTemp) ||
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, ccTemp)) {
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, dMaxAngExt, ccTemp)) {
|
||||
if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
||||
return false ;
|
||||
}
|
||||
@@ -122,7 +123,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite ccTemp ;
|
||||
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrvNext, ccTemp) ||
|
||||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrvNext, ccTemp) ||
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, ccTemp)) {
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, dMaxAngExt, ccTemp)) {
|
||||
int nCrvCount = ccTemp.GetCurveCount() ;
|
||||
if ( nCrvCount > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
||||
return false ;
|
||||
@@ -174,7 +175,7 @@ bool
|
||||
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -218,7 +219,7 @@ bool
|
||||
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -259,11 +260,11 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAu
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
|
||||
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
||||
CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -272,6 +273,9 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
|
||||
// elimino dal tipo le parti estranee all'angolo esterno
|
||||
nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ;
|
||||
|
||||
// porto il massimo angolo per tipo Extend in limiti accettabili (90° - 150°)
|
||||
dMaxAngExt = Clamp( dMaxAngExt, ANG_RIGHT, 1.667 * ANG_RIGHT) ;
|
||||
|
||||
// calcolo direzioni tangenti sull'estremo in comune
|
||||
Vector3d vtDir1, vtDir2 ;
|
||||
if ( ! pCrv1->GetEndDir( vtDir1) || ! pCrv2->GetStartDir( vtDir2))
|
||||
@@ -319,8 +323,8 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
|
||||
( dDist > 0 && dAngDeg < 0)))
|
||||
return false ;
|
||||
|
||||
// se l'angolo esterno supera il retto, offset extend diventa offset chamfer
|
||||
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL)
|
||||
// se l'angolo esterno supera il limite, offset extend diventa offset chamfer
|
||||
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > dMaxAngExt + EPS_ANG_SMALL)
|
||||
nType = ICurve::OFF_CHAMFER ;
|
||||
|
||||
// se angolo esterno molto piccolo, semplifico tutto
|
||||
|
||||
+1
-1
@@ -577,7 +577,7 @@ CurveLine::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveLine::SimpleOffset( double dDist, int nType)
|
||||
CurveLine::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointSurfBz.cpp Data : 29.10.25 Versione : 2.7j3
|
||||
// Contenuto : Implementazione della classe distanza Punto da superficie Bezier.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 29.10.25 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
|
||||
: m_dDist( -1), m_bIsInside( false)
|
||||
{
|
||||
// Bezier non valida
|
||||
if ( &pSrfBz == nullptr || ! pSrfBz.IsValid())
|
||||
return ;
|
||||
// Calcolo la distanza
|
||||
Calculate( ptP, pSrfBz) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = srfBz.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
const ISurfTriMesh* pStmRef = srfBz.GetAuxSurfRefined() ;
|
||||
if ( pStmRef == nullptr)
|
||||
return ;
|
||||
|
||||
DistPointSurfTm dpst( ptP, *pStmRef) ;
|
||||
|
||||
//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
|
||||
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
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_bIsInside = false ;
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * m_vtN < - EPS_SMALL) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetDist( double& dDist) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
ptMinDistPoint = m_ptMinDistPoint ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
ptParamPoint = m_ptParam ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetNorm( Vector3d& vtN) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
vtN = m_vtN ;
|
||||
return true ;
|
||||
}
|
||||
@@ -94,6 +94,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
// Vettore di indici dei triangoli più vicini inizialmente vuoto
|
||||
m_vnMinDistTriaIndex.clear() ;
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = tmSurf.IsClosed() ;
|
||||
|
||||
@@ -184,6 +186,10 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return ;
|
||||
|
||||
// Inizializzo il vettore dei triangoli a minima distanza
|
||||
for ( auto& Tria : vTria)
|
||||
m_vnMinDistTriaIndex.emplace_back( Tria.first) ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = dMinDist ;
|
||||
// salvo il punto a distanza minima
|
||||
@@ -279,6 +285,18 @@ DistPointSurfTm::GetMinDistTriaIndex( int& nMinDistIndex) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfTm::GetMinDistTriaIndices( INTVECTOR& vMinDistTriaIndex) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < - EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
vMinDistTriaIndex = m_vnMinDistTriaIndex ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
|
||||
+12
-3
@@ -159,11 +159,20 @@ InitFontManager( const string& sNfeFontDir, const string& sDefaultFont)
|
||||
{
|
||||
// recupero il font manager
|
||||
FontManager& fntMgr = FontManager::GetFontManager() ;
|
||||
|
||||
// lo inizializzo
|
||||
fntMgr.Init( sNfeFontDir, sDefaultFont) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
SetDefaultFont( const string& sDefaultFont)
|
||||
{
|
||||
// recupero il font manager
|
||||
FontManager& fntMgr = FontManager::GetFontManager() ;
|
||||
// imposto il dato
|
||||
fntMgr.SetDefaultFont( sDefaultFont) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const string&
|
||||
GetNfeFontDir( void)
|
||||
@@ -185,11 +194,11 @@ GetDefaultFont( void)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static pfProcEvents s_pFunProcEvents = nullptr ;
|
||||
static psfProcEvents s_pFunProcEvents = nullptr ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
SetEGkProcessEvents( pfProcEvents pFun)
|
||||
SetEGkProcessEvents( psfProcEvents pFun)
|
||||
{
|
||||
s_pFunProcEvents = pFun ;
|
||||
return ( pFun != nullptr) ;
|
||||
|
||||
Binary file not shown.
+10
-4
@@ -116,7 +116,7 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -151,7 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -199,7 +199,7 @@ copy $(TargetPath) \EgtProg\DllD64</Command>
|
||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -245,7 +245,7 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
|
||||
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
<IntelJCCErratum>true</IntelJCCErratum>
|
||||
</ClCompile>
|
||||
@@ -281,6 +281,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="BBox3d.cpp" />
|
||||
<ClCompile Include="BiArcs.cpp" />
|
||||
<ClCompile Include="CalcPocketing.cpp" />
|
||||
<ClCompile Include="CalcDerivate.cpp" />
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
@@ -310,7 +311,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="DistPointSurfBz.cpp" />
|
||||
<ClCompile Include="DistPointSurfFr.cpp" />
|
||||
<ClCompile Include="IntersCurvePlane.cpp" />
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
@@ -320,6 +323,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="Trimming.cpp" />
|
||||
<ClCompile Include="MultiGeomDB.cpp" />
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||
<ClCompile Include="VolZmapOffset.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
@@ -340,6 +345,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h" />
|
||||
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
|
||||
<ClInclude Include="..\Include\EGkQuaternion.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
<Filter Include="File di origine\GeoCollisionDetection">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoStriping">
|
||||
<UniqueIdentifier>{54901321-08f6-4428-80c7-a1f859136a32}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vector3d.cpp">
|
||||
@@ -552,6 +555,21 @@
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MultiGeomDB.cpp">
|
||||
<Filter>File di origine\Gdb</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DistPointSurfBz.cpp">
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersCurvePlane.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CalcDerivate.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1235,6 +1253,9 @@
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+1
-1
@@ -1087,7 +1087,7 @@ ExtDimension::Update( void) const
|
||||
if ( m_nType == DT_RADIAL)
|
||||
sVal = "R " + sVal ;
|
||||
else if ( m_nType == DT_DIAMETRAL)
|
||||
sVal = u8"\u00D8 " + sVal ;
|
||||
sVal = reinterpret_cast<const char *>( u8"\u00D8") + sVal ;
|
||||
ReplaceString( m_sCalcText, IS_MEASURE, sVal) ;
|
||||
}
|
||||
// punto di inserimento del testo
|
||||
|
||||
+3
-1
@@ -29,6 +29,8 @@ class FontManager
|
||||
|
||||
public :
|
||||
bool Init( const std::string& sNfeFontDir, const std::string& sDefaultFont) ;
|
||||
bool SetDefaultFont( const std::string& sDefaultFont)
|
||||
{ m_sDefaultFont = sDefaultFont ; return true ; }
|
||||
bool SetCurrFont( const std::string& sFont, int nWeight, bool bItalic,
|
||||
double dHeight, double dRatio, double dAddAdvance) ;
|
||||
const std::string& GetNfeFontDir( void) const
|
||||
@@ -54,7 +56,7 @@ class FontManager
|
||||
OsFont m_OsFont ;
|
||||
|
||||
private :
|
||||
FontManager( void) {}
|
||||
FontManager( void) : m_bCurrNfeFont( false) {}
|
||||
FontManager( FontManager const& copy) = delete ;
|
||||
FontManager& operator=( FontManager const& copy) = delete ;
|
||||
} ;
|
||||
|
||||
+2
-2
@@ -336,7 +336,7 @@ GdbGeo::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoe
|
||||
// curva originale
|
||||
ICurve* pCrv = GetCurve( m_pGeoObj) ;
|
||||
// trasformo in curva di Bezier (semplice o composta)
|
||||
ICurve* pCrvNew = ArcToBezierCurve( pCrv) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc( pCrv)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
// assegno alla nuova curva estrusione e spessore di quella originale
|
||||
@@ -389,7 +389,7 @@ GdbGeo::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDi
|
||||
if ( ! pArc->IsPlane() ||
|
||||
! AreSameOrOppositeVectorExact( pArc->GetNormVersor(), vtNorm)) {
|
||||
// trasformo in curva di Bezier (semplice o composta)
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurve( m_pGeoObj)) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc( m_pGeoObj)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
// assegno alla nuova curva estrusione e spessore di quella originale
|
||||
|
||||
+14
@@ -101,6 +101,20 @@ GdbObj::CopyFrom( const GdbObj* pSou)
|
||||
return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::CopyStippleDataFrom( const GdbObj* pSou)
|
||||
{
|
||||
// se l'oggetto sorgente non esiste
|
||||
if ( pSou == nullptr)
|
||||
return false ;
|
||||
// copio stipple
|
||||
m_nStpFactor = pSou->m_nStpFactor ;
|
||||
m_nStpPattern = pSou->m_nStpPattern ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::CopyAttribsFrom( const GdbObj* pSou)
|
||||
|
||||
@@ -57,6 +57,7 @@ class GdbObj
|
||||
GdbObj( void) ;
|
||||
bool CopyFrom( const GdbObj* pSou) ;
|
||||
bool CopyAttribsFrom( const GdbObj* pSou) ;
|
||||
bool CopyStippleDataFrom( const GdbObj* pSou) ;
|
||||
bool CopyTextureDataFrom( const GdbObj* pSou) ;
|
||||
bool CopyUserObjFrom( const GdbObj* pSou) ;
|
||||
|
||||
|
||||
+35
-35
@@ -28,41 +28,6 @@
|
||||
#define GEOOBJ_NGEIDTOTYPE( nNgeId) GeoObjFactory::NgeIdToType( nNgeId)
|
||||
#define GEOOBJ_CREATE( nKey) GeoObjFactory::Create( nKey)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class GeoObjRegister
|
||||
{
|
||||
public :
|
||||
static bool DoRegister( int nKey, int nNgeId)
|
||||
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
|
||||
return false ;
|
||||
GetTypePrivate() = nKey ;
|
||||
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
|
||||
GetNgeIdPrivate() = nNgeId ;
|
||||
return true ; }
|
||||
static IGeoObj* Create( void)
|
||||
{ return new( std::nothrow) T ; }
|
||||
static int GetType( void)
|
||||
{ return GetTypePrivate() ; }
|
||||
static const std::string& GetKey( void)
|
||||
{ return GetKeyPrivate() ; }
|
||||
static int GetNgeId( void)
|
||||
{ return GetNgeIdPrivate() ; }
|
||||
|
||||
private :
|
||||
GeoObjRegister( void) {}
|
||||
~GeoObjRegister( void) {}
|
||||
static int& GetTypePrivate( void)
|
||||
{ static int s_nType ;
|
||||
return s_nType ; }
|
||||
static std::string& GetKeyPrivate( void)
|
||||
{ static std::string s_sKey ;
|
||||
return s_sKey ; }
|
||||
static int& GetNgeIdPrivate( void)
|
||||
{ static int s_nNgeId ;
|
||||
return s_nNgeId ; }
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class GeoObjFactory
|
||||
{
|
||||
@@ -117,3 +82,38 @@ class GeoObjFactory
|
||||
{ static CreatorMap s_CreatorMap ;
|
||||
return s_CreatorMap ; }
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class GeoObjRegister
|
||||
{
|
||||
public :
|
||||
static bool DoRegister( int nKey, int nNgeId)
|
||||
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
|
||||
return false ;
|
||||
GetTypePrivate() = nKey ;
|
||||
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
|
||||
GetNgeIdPrivate() = nNgeId ;
|
||||
return true ; }
|
||||
static IGeoObj* Create( void)
|
||||
{ return new( std::nothrow) T ; }
|
||||
static int GetType( void)
|
||||
{ return GetTypePrivate() ; }
|
||||
static const std::string& GetKey( void)
|
||||
{ return GetKeyPrivate() ; }
|
||||
static int GetNgeId( void)
|
||||
{ return GetNgeIdPrivate() ; }
|
||||
|
||||
private :
|
||||
GeoObjRegister( void) {}
|
||||
~GeoObjRegister( void) {}
|
||||
static int& GetTypePrivate( void)
|
||||
{ static int s_nType ;
|
||||
return s_nType ; }
|
||||
static std::string& GetKeyPrivate( void)
|
||||
{ static std::string s_sKey ;
|
||||
return s_sKey ; }
|
||||
static int& GetNgeIdPrivate( void)
|
||||
{ static int s_nNgeId ;
|
||||
return s_nNgeId ; }
|
||||
} ;
|
||||
|
||||
+13
-11
@@ -38,20 +38,22 @@ using namespace std ;
|
||||
class LockAddErase
|
||||
{
|
||||
public :
|
||||
LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
|
||||
LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true)
|
||||
: m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
|
||||
{ if ( ! m_bUse) return ;
|
||||
while ( m_bAddEraseOn.test_and_set()) {
|
||||
this_thread::sleep_for( chrono::nanoseconds{ 1}) ;
|
||||
while ( m_bAddEraseOn.test_and_set( memory_order_acquire)) {
|
||||
m_bAddEraseOn.wait( true, memory_order_relaxed) ;
|
||||
}
|
||||
} ;
|
||||
|
||||
~LockAddErase( void)
|
||||
{ if ( ! m_bUse) return ;
|
||||
m_bAddEraseOn.clear() ;
|
||||
m_bAddEraseOn.clear( memory_order_release) ;
|
||||
m_bAddEraseOn.notify_one() ;
|
||||
} ;
|
||||
|
||||
private :
|
||||
std::atomic_flag& m_bAddEraseOn ;
|
||||
atomic_flag& m_bAddEraseOn ;
|
||||
bool m_bUse ;
|
||||
} ;
|
||||
|
||||
@@ -611,7 +613,7 @@ GeomDB::GetGdbObj( int nId) const
|
||||
// radice
|
||||
else if ( nId == GDB_ID_ROOT)
|
||||
return &m_GrpRadix ;
|
||||
// un nodo qualubque
|
||||
// un nodo qualunque
|
||||
else
|
||||
return m_IdManager.FindObj( nId) ;
|
||||
}
|
||||
@@ -658,7 +660,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLo
|
||||
return false ;
|
||||
}
|
||||
// inserisco come figlio, in testa alla lista del padre
|
||||
else if ( nSonBeforeAfter == GDB_FIRST_SON){
|
||||
else if ( nSonBeforeAfter == GDB_FIRST_SON) {
|
||||
GdbGroup* pGroup = ::GetGdbGroup( pGRef) ;
|
||||
if ( pGroup == nullptr)
|
||||
return false ;
|
||||
@@ -877,7 +879,7 @@ GeomDB::GetFirstNameInGroup( int nGroupId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbO->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbO->m_nId) ;
|
||||
// passo al successivo
|
||||
pGdbO = pGdbO->GetNext() ;
|
||||
@@ -905,7 +907,7 @@ GeomDB::GetNextName( int nId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbNext->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbNext->m_nId) ;
|
||||
// passo al successivo
|
||||
pGdbNext = pGdbNext->GetNext() ;
|
||||
@@ -933,7 +935,7 @@ GeomDB::GetLastNameInGroup( int nGroupId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbO->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbO->m_nId) ;
|
||||
// passo al precedente
|
||||
pGdbO = pGdbO->GetPrev() ;
|
||||
@@ -961,7 +963,7 @@ GeomDB::GetPrevName( int nId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbPrev->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbPrev->m_nId) ;
|
||||
// passo al precedente
|
||||
pGdbPrev = pGdbPrev->GetPrev() ;
|
||||
|
||||
@@ -29,6 +29,10 @@ class GeomDB : public IGeomDB
|
||||
friend class GdbObj ;
|
||||
friend class GdbGroup ;
|
||||
friend class GdbGeo ;
|
||||
friend int CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
|
||||
friend int CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
|
||||
friend int DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId) ;
|
||||
friend int DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp) ;
|
||||
|
||||
public :
|
||||
~GeomDB( void) override ;
|
||||
|
||||
@@ -371,12 +371,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// 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)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per precedente di prima curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
|
||||
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)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
|
||||
EraseOtherInfo( i, j) ;
|
||||
}
|
||||
|
||||
+81
-15
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
|
||||
// ciclo sulle curve per verificare se da approssimare
|
||||
for ( int i = 0 ; i < 2 ; ++ i) {
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) ||
|
||||
m_pCurve[i]->GetType() == CRV_BEZIER) {
|
||||
// approssimo con rette
|
||||
@@ -127,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
|
||||
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
|
||||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
||||
}
|
||||
@@ -252,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
|
||||
bool
|
||||
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
|
||||
{
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.empty())
|
||||
return true ;
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
if ( ! bAdjCrvA && ! bAdjCrvB)
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
@@ -291,6 +291,24 @@ IntersCurveCurve::GetIntersCount( void)
|
||||
return m_nIntersCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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)) {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
else {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
}
|
||||
return nCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersCurveCurve::GetCrossIntersCount( void)
|
||||
@@ -340,6 +358,30 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
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)) {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
else {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
if( nCount == nInd) {
|
||||
aInfo = m_Info[nInd] ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI)
|
||||
@@ -347,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
|
||||
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
|
||||
return false ;
|
||||
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
bool bFound = false ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
||||
// se è un'intersezione singola
|
||||
// se è un'intersezione singola
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// faccio la verifica sul punto
|
||||
Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ;
|
||||
@@ -416,7 +458,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
|
||||
}
|
||||
@@ -433,7 +475,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
|
||||
}
|
||||
@@ -498,7 +540,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
double dU2 = Info[j].IciA[1].dU ;
|
||||
if ( dU2 < dU1 && pCurve->IsClosed())
|
||||
dU2 += dEndPar ;
|
||||
// se cade nell'intervallo è da saltare
|
||||
// se cade nell'intervallo è da saltare
|
||||
if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) {
|
||||
bToSkip = true ;
|
||||
break ;
|
||||
@@ -517,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
double dCurrPar = dStartPar ;
|
||||
double dCurrLen = 0 ;
|
||||
double dEndLen ; pCurve->GetLength( dEndLen) ;
|
||||
// se è chiusa, recupero come finisce
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! InfoCorr[nNumInters-1].bOverlap)
|
||||
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
|
||||
@@ -535,7 +577,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
|
||||
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
@@ -557,7 +599,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
// altrimenti, salvo il tipo
|
||||
else
|
||||
nLastTy = InfoCorr[i].IciA[0].nNextTy ;
|
||||
// se è definito un tratto in sovrapposizione
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( InfoCorr[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
@@ -597,7 +639,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
double dStartParB, dEndParB ;
|
||||
if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
|
||||
return false ;
|
||||
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
|
||||
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
|
||||
BBox3d boxCrvA, boxCrvB ;
|
||||
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
|
||||
! pCurveB->GetLocalBBox( boxCrvB))
|
||||
@@ -640,13 +682,37 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
// dichiaro la classe della curva per default
|
||||
int nClass = CRVC_OUT ;
|
||||
// se c'è almeno una intersezione
|
||||
// se c'è almeno una intersezione
|
||||
if ( iCC.GetIntersCount() > 0) {
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
IntCrvCrvInfo aInfo ;
|
||||
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
||||
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
nClass = CRVC_IN ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
|
||||
nClass = CRVC_OUT ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_NULL) {
|
||||
// se il primo punto scelto non va bene allora ne cerco uno che mi dia informazioni sull'essere interno o esterno
|
||||
CurveLine clLine ;
|
||||
Point3d ptNewChoice ; pCurveA->GetPointD1D2( 0.25, ICurve::FROM_MINUS, ptNewChoice) ;
|
||||
if ( ! clLine.SetPDL( ptNewChoice, 0, dLen))
|
||||
return false ;
|
||||
// calcolo l'intersezione
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
if ( iCC.GetIntersCount() > 0) {
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
IntCrvCrvInfo aInfo ;
|
||||
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
||||
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
nClass = CRVC_IN ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
|
||||
nClass = CRVC_OUT ;
|
||||
else
|
||||
return false ; // se arrivo qui potrei ritentare la ricerca
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti sono esterni tra loro
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersCurvePlane.cpp Data : 07.11.25 Versione : 2.7k1
|
||||
// Contenuto : Implementazione della classe intersezione curva-piano.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.11.25 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "IntersLineArc.h"
|
||||
#include "IntersArcArc.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersCurvePlane::IntersCurvePlane( const ICurve& Curve, const Point3d& ptOrig, const Vector3d& vtN)
|
||||
{
|
||||
// Le intersezioni sono calcolate nel piano XY locale.
|
||||
// Il flag bAreSegments vale solo per intersezione tra due linee e riguarda entrambe.
|
||||
|
||||
// inizializzazioni
|
||||
m_nIntersCount = 0 ;
|
||||
m_pCurve = &Curve ;
|
||||
m_plPlane.Set( ptOrig, vtN) ;
|
||||
|
||||
// puntatore alla curva usata nei calcoli (originali o temporanee)
|
||||
const ICurve* pCalcCrv ;
|
||||
// per eventuale esplosione temporanea delle curve
|
||||
PtrOwner<ICurve> pTmpCrv ;
|
||||
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
if ( m_pCurve->GetType() == CRV_ARC || m_pCurve->GetType() == CRV_BEZIER || m_pCurve->GetType() == CRV_COMPO) {
|
||||
// approssimo con rette
|
||||
PolyLine PL ;
|
||||
if ( ! m_pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return ;
|
||||
pTmpCrv.Set( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pTmpCrv))
|
||||
return ;
|
||||
if ( ! GetBasicCurveComposite( pTmpCrv)->FromPolyLine( PL))
|
||||
return ;
|
||||
pCalcCrv = pTmpCrv ;
|
||||
}
|
||||
else
|
||||
pCalcCrv = m_pCurve ;
|
||||
|
||||
m_Info.clear() ;
|
||||
if ( pCalcCrv->GetType() == CRV_LINE) {
|
||||
CalcIntersLinePlane( m_plPlane, *pCalcCrv) ;
|
||||
}
|
||||
else if ( pCalcCrv->GetType() == CRV_COMPO){
|
||||
for ( int i = 0 ; i < GetBasicCurveComposite( pCalcCrv)->GetCurveCount(); ++i) {
|
||||
const ICurve& subCurve = *GetBasicCurveComposite( pCalcCrv)->GetCurve( i) ;
|
||||
CalcIntersLinePlane( m_plPlane, subCurve, i) ;
|
||||
}
|
||||
OrderAndCompleteIntersections() ;
|
||||
}
|
||||
|
||||
// per curve approssimate, sistemo...
|
||||
AdjustIntersParams( pCalcCrv != m_pCurve) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Curve, int nCrv)
|
||||
{
|
||||
if ( Curve.GetType() != CRV_LINE)
|
||||
return false ;
|
||||
Point3d ptStart ; Curve.GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; Curve.GetEndPoint( ptEnd) ;
|
||||
Point3d ptInt ;
|
||||
double dLen = 0 ; Curve.GetLength( dLen) ;
|
||||
int nIntersType = IntersLinePlane( ptStart, ptEnd, m_plPlane, ptInt, true) ;
|
||||
// intersezione con attraversamento
|
||||
if ( nIntersType == ILPT_YES) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.Ici[0].ptI = ptInt ;
|
||||
icpi.Ici[0].dU = Dist( ptInt, ptStart) / dLen + nCrv ;
|
||||
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nNextTy = icpi.Ici[0].nPrevTy == ICPT_IN ? ICPT_OUT : ICPT_IN ;
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
// intersezione con tocco
|
||||
else if ( nIntersType == ILPT_START || nIntersType == ILPT_END) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.Ici[0].ptI = ptInt ;
|
||||
icpi.Ici[0].dU = nIntersType == ILPT_START ? 0 : 1 + nCrv ;
|
||||
|
||||
if ( nIntersType == ILPT_START) {
|
||||
Vector3d vtPos = ptEnd - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nNextTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nPrevTy = ICPT_NULL ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nNextTy = ICPT_NULL ;
|
||||
}
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
// intersezione con sovrapposizione
|
||||
else if ( nIntersType == ILPT_INPLANE) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.bOverlap = true ;
|
||||
icpi.Ici[0].ptI = ptStart ;
|
||||
icpi.Ici[0].dU = 0 + nCrv;
|
||||
icpi.Ici[1].ptI = ptEnd ;
|
||||
icpi.Ici[1].dU = 1 + nCrv ;
|
||||
icpi.Ici[0].nPrevTy = ICPT_NULL ;
|
||||
icpi.Ici[0].nNextTy = ICPT_ON ;
|
||||
icpi.Ici[1].nPrevTy = ICPT_ON ;
|
||||
icpi.Ici[1].nNextTy = ICPT_NULL ;
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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 ;}) ;
|
||||
for ( int curr = m_Info.size() - 1 ; curr > - 1 ; --curr) {
|
||||
int prev = curr == 0 ? m_Info.size() - 1 : curr - 1 ;
|
||||
int next = curr == m_Info.size() - 1 ? 0 : curr + 1 ;
|
||||
bool bErasedCurr = false ;
|
||||
// solo le intersezioni di sovrapposizione o puntuali sullo start o end delle curve possono avere il PrevTy o NextTy non definito
|
||||
if ( ! m_Info[curr].bOverlap) {
|
||||
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
|
||||
if ( ! m_Info[prev].bOverlap) {
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
|
||||
// se ho due puntuali che coincidono cancello il successivo tra i due ( corrente)
|
||||
if ( AreSamePointApprox( m_Info[curr].Ici[0].ptI, m_Info[prev].Ici[0].ptI)) {
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
bErasedCurr = true ;
|
||||
}
|
||||
}
|
||||
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
|
||||
else {
|
||||
m_Info[prev].Ici[1].nNextTy = m_Info[curr].Ici[0].nNextTy ;
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
bErasedCurr = true ;
|
||||
}
|
||||
}
|
||||
if ( ! bErasedCurr && m_Info[curr].Ici[0].nNextTy == ICPT_NULL){
|
||||
if ( ! m_Info[prev].bOverlap)
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[next].Ici[0].nPrevTy ;
|
||||
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
|
||||
else {
|
||||
m_Info[next].Ici[0].nPrevTy = m_Info[curr].Ici[0].nPrevTy ;
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
|
||||
if ( ! m_Info[prev].bOverlap)
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
|
||||
else
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[1].nNextTy ;
|
||||
}
|
||||
if ( m_Info[curr].Ici[1].nNextTy == ICPT_NULL) {
|
||||
if ( ! m_Info[next].bOverlap)
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[0].nPrevTy ;
|
||||
else
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[1].nPrevTy ;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nIntersCount = m_Info.size() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::IsArcToApprox( const ICurve& Curve)
|
||||
{
|
||||
// recupero l'arco
|
||||
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
|
||||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::AdjustIntersParams( bool bAdjCrv)
|
||||
{
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.empty())
|
||||
return true ;
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
if ( ! bAdjCrv)
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
for ( auto& aInfo : m_Info) {
|
||||
// se curve originali approssimate, devo ricalcolare i parametri dei punti di intersezione
|
||||
if ( bAdjCrv) {
|
||||
if ( ! m_pCurve->GetParamAtPoint( aInfo.Ici[0].ptI, aInfo.Ici[0].dU, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
if ( aInfo.bOverlap && ! m_pCurve->GetParamAtPoint( aInfo.Ici[1].ptI, aInfo.Ici[1].dU, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersCurvePlane::GetIntersCount( void)
|
||||
{
|
||||
return m_nIntersCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
|
||||
{
|
||||
if ( m_nIntersCount == 0)
|
||||
return false ;
|
||||
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
bool bFound = false ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
||||
// se è un'intersezione singola
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// faccio la verifica sul punto
|
||||
Point3d ptP = m_Info[i].Ici[0].ptI ;
|
||||
double dSqDist = SqDist( ptNear, ptP) ;
|
||||
if ( dSqDist < dMinSqDist) {
|
||||
dMinSqDist = dSqDist ;
|
||||
ptI = ptP ;
|
||||
dParam = m_Info[i].Ici[0].dU ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
// recupero il tratto di sovrapposizione
|
||||
double dUStartTrim, dUEndTrim ;
|
||||
dUStartTrim = m_Info[i].Ici[0].dU ;
|
||||
dUEndTrim = m_Info[i].Ici[1].dU ;
|
||||
PtrOwner<ICurve> pCrv( m_pCurve->CopyParamRange( dUStartTrim, dUEndTrim)) ;
|
||||
if ( IsNull( pCrv))
|
||||
continue ;
|
||||
// cerco il punto
|
||||
int nFlag ;
|
||||
Point3d ptP ;
|
||||
if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) {
|
||||
// faccio la verifica
|
||||
double dSqDist = SqDist( ptNear, ptP) ;
|
||||
if ( dSqDist < dMinSqDist) {
|
||||
dMinSqDist = dSqDist ;
|
||||
ptI = ptP ;
|
||||
m_pCurve->GetParamAtPoint( ptP, dParam) ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bFound ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetCurveClassification( double dLenMin, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// pulisco vettore classificazioni
|
||||
ccClass.clear() ;
|
||||
|
||||
// verifico definizione della curva
|
||||
if ( m_pCurve == nullptr)
|
||||
return false ;
|
||||
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve, m_Info, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve, ccClass) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcCurveClassification( const ICurve* pCurve, const ICPIVECTOR& Info, double dLenMin, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// numero intersezioni
|
||||
int nNumInters = int( Info.size()) ;
|
||||
if ( nNumInters < 1)
|
||||
return false ;
|
||||
// recupero il dominio parametrico della curva in esame
|
||||
double dStartPar, dEndPar ;
|
||||
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
// limito lunghezza minima
|
||||
dLenMin = max( dLenMin, EPS_ZERO) ;
|
||||
// elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione
|
||||
ICPIVECTOR InfoCorr ;
|
||||
InfoCorr.reserve( Info.size()) ;
|
||||
for ( size_t i = 0 ; i < Info.size() ; ++ i) {
|
||||
// se intersezione puntuale senza attraversamento
|
||||
if ( ! Info[i].bOverlap && Info[i].Ici[0].nPrevTy == Info[i].Ici[0].nNextTy) {
|
||||
// confronto con le intersezioni con sovrapposizione
|
||||
bool bToSkip = false ;
|
||||
for ( size_t j = 0 ; j < Info.size() ; ++ j) {
|
||||
// se coincide o puntuale
|
||||
if ( j == i || ! Info[j].bOverlap)
|
||||
continue ;
|
||||
// determino l'intervallo parametrico tenendo conto di eventuale avvolgimento attorno all'inizio
|
||||
double dU1 = Info[j].Ici[0].dU ;
|
||||
double dU2 = Info[j].Ici[1].dU ;
|
||||
if ( dU2 < dU1 && pCurve->IsClosed())
|
||||
dU2 += dEndPar ;
|
||||
// se cade nell'intervallo è da saltare
|
||||
if ( Info[i].Ici[0].dU >= dU1 && Info[i].Ici[0].dU <= dU2) {
|
||||
bToSkip = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bToSkip)
|
||||
continue ;
|
||||
}
|
||||
// salvo dati intersezione
|
||||
InfoCorr.emplace_back( Info[i]) ;
|
||||
}
|
||||
// aggiorno numero di intersezioni da considerare
|
||||
nNumInters = int( InfoCorr.size()) ;
|
||||
// recupero la classificazione all'inizio della curva
|
||||
int nLastTy = ICCT_NULL ;
|
||||
double dCurrPar = dStartPar ;
|
||||
double dCurrLen = 0 ;
|
||||
double dEndLen ; pCurve->GetLength( dEndLen) ;
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! InfoCorr[nNumInters-1].bOverlap)
|
||||
nLastTy = InfoCorr[nNumInters-1].Ici[0].nNextTy ;
|
||||
else {
|
||||
nLastTy = InfoCorr[nNumInters-1].Ici[1].nNextTy ;
|
||||
// se attraversa il punto di giunzione (parametro di fine minore di quello di inizio)
|
||||
if ( InfoCorr[nNumInters-1].Ici[1].dU < InfoCorr[nNumInters-1].Ici[0].dU) {
|
||||
dCurrPar = InfoCorr[nNumInters-1].Ici[1].dU ;
|
||||
double dTmpLen ; pCurve->GetLengthAtParam( dCurrPar, dTmpLen) ;
|
||||
dCurrLen = dTmpLen - dEndLen ;
|
||||
dEndPar = dCurrPar ;
|
||||
dEndLen = dTmpLen ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].Ici[0].dU, dLenU) ;
|
||||
if ( InfoCorr[i].Ici[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
int nPrevTy = InfoCorr[i].Ici[0].nPrevTy ;
|
||||
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
|
||||
nPrevTy == ICCT_NULL || nPrevTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = InfoCorr[i].Ici[0].dU ;
|
||||
segClass.nClass = (( nPrevTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].Ici[0].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
|
||||
}
|
||||
// altrimenti, salvo il tipo
|
||||
else
|
||||
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( InfoCorr[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = InfoCorr[i].Ici[1].dU ;
|
||||
segClass.nClass = CRVPLN_ON ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].Ici[1].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].Ici[1].nNextTy ;
|
||||
}
|
||||
}
|
||||
// eventuale tratto finale rimasto
|
||||
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia valida
|
||||
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = (( nLastTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcCurveInOrOut( const ICurve* pCurve, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// controllo di non avere intersezioni
|
||||
int nNumInters = int( m_Info.size()) ;
|
||||
if ( nNumInters > 0)
|
||||
return false ;
|
||||
|
||||
// se non ho intersezioni tra curva e piano devo solo capire da che parte del piano sta la curva
|
||||
CrvPlaneClass cpClass ;
|
||||
double dStartPar, dEndPar ;
|
||||
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
|
||||
Vector3d vtCrv = ptStart - m_plPlane.GetPoint() ;
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dStartPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = ( (vtCrv * m_plPlane.GetVersN() < 0) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
return true ;
|
||||
}
|
||||
+17
-5
@@ -113,7 +113,7 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
double dU1, dU2 ;
|
||||
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
|
||||
|
||||
// Se non c'è intersezione
|
||||
// Se non c'è intersezione
|
||||
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
|
||||
return true ;
|
||||
|
||||
@@ -144,8 +144,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
||||
if ( dU1 < - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TG_INSIDE, 0.) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
||||
if ( dU2 > dLen + EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TG_INSIDE, dLen) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
@@ -162,8 +168,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
||||
if ( dU1 < - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_INSIDE, 0.) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
||||
if ( dU2 > dLen + EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_INSIDE, dLen) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
|
||||
@@ -159,6 +159,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
// flag per segmenti che si allontanano significativamente
|
||||
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
|
||||
|
||||
// analisi casi speciali di quasi parallelismo
|
||||
// segmento sovrapposto all'altro
|
||||
double dDist1, dDist2 ;
|
||||
if ( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
|
||||
dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ;
|
||||
dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ;
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
|
||||
bParallel = true ;
|
||||
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
|
||||
}
|
||||
}
|
||||
else if ( nS2Side == 0 || nE2Side == 0 || nS2Side == nE2Side) {
|
||||
dDist1 = CrossXY( ptS2 - ptS1, vtDir1) ;
|
||||
dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ;
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY) {
|
||||
bParallel = true ;
|
||||
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
|
||||
}
|
||||
}
|
||||
// estremità sovrapposte di poco
|
||||
if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
|
||||
if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
|
||||
bParallel = true ;
|
||||
bFarEnds = false ;
|
||||
}
|
||||
}
|
||||
|
||||
// se non sono paralleli e si allontanano tra loro abbastanza
|
||||
if ( ! bParallel && bFarEnds) {
|
||||
// posizioni parametriche dell'intersezione sulle linee
|
||||
|
||||
+271
-14
@@ -14,11 +14,17 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -28,7 +34,6 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
|
||||
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz)
|
||||
{
|
||||
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
|
||||
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
double dDistNew = 0, dDistPre = 0 ;
|
||||
@@ -42,18 +47,18 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
|
||||
while ( dDistNew > EPS_SMALL && nCount < 100) {
|
||||
dDistPre = dDistNew ;
|
||||
Point3d ptIBzNew1 ;
|
||||
pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
|
||||
pSurfBz->GetPointD1D2( ( ptSP.x + dh), ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
|
||||
DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewU.GetDist( dDistNew) ;
|
||||
double dfdU = ( dDistNew - dDistPre) / dh ;
|
||||
Point3d ptIBzNew2 ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x, ( ptSP.y + dh), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
|
||||
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewV.GetDist( dDistNew) ;
|
||||
double dfdV = ( dDistNew - dDistPre) / dh ;
|
||||
// mi avvicino cercando di annullare la distanza in un colpo solo
|
||||
double dr = - dDistPre / ( dfdU + dfdV) ;
|
||||
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU), ( ptSP.y + dr * dfdV), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
dplNew.GetDist( dDistNew) ;
|
||||
++ nCount ;
|
||||
@@ -67,11 +72,11 @@ 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)
|
||||
{
|
||||
if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) {
|
||||
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) ;
|
||||
}
|
||||
else if ( nILT == ILTT_SEGM || nILT == ILTT_SEGM_ON_EDGE) {
|
||||
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) ;
|
||||
@@ -88,8 +93,8 @@ 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.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
{ double dUa = ( ( a.nILTA == ILTA_SEGM || a.nILTA == ILTA_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
@@ -137,16 +142,16 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
|
||||
double dU0, dV0 ;
|
||||
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
|
||||
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
|
||||
ptSP = ptSP + Point3d( dU0, dV0, 0) ;
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
|
||||
pSurfBz->GetPointNrmD1D2(ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
|
||||
double dCos = vtN * vtL ;
|
||||
double dCos2 = 0 ;
|
||||
// eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione)
|
||||
if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) {
|
||||
if ( InfoTm.nILTT == ILTA_SEGM || InfoTm.nILTT == ILTA_SEGM_ON_EDGE ) {
|
||||
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI2, ptSP2, InfoTm.nILTT) ;
|
||||
if ( ! RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) {
|
||||
int nVert[3] ;
|
||||
@@ -157,7 +162,7 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
|
||||
pSurfBz->GetPointNrmD1D2( ptSP2.x, ptSP2.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
|
||||
dCos2 = vtN * vtL ;
|
||||
}
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ;
|
||||
@@ -176,7 +181,7 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
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 ;
|
||||
@@ -185,7 +190,7 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
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) ;
|
||||
}
|
||||
@@ -232,3 +237,255 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBzBilinear( 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 bilineare
|
||||
if ( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat)
|
||||
return false ;
|
||||
|
||||
int nInters = int( vInfo.size()) ;
|
||||
|
||||
PNTVECTOR vPntCtrl ;
|
||||
for ( int p = 0 ; p < 4 ; ++p) {
|
||||
bool bOk = false ;
|
||||
vPntCtrl.push_back( pSurfBz->GetControlPoint( p, &bOk)) ;
|
||||
}
|
||||
|
||||
Vector3d a = vPntCtrl[3] - vPntCtrl[1] + ( vPntCtrl[0] - vPntCtrl[2]) ;
|
||||
Vector3d b = vPntCtrl[1] - vPntCtrl[0] ;
|
||||
Vector3d c = vPntCtrl[2] - vPntCtrl[0] ;
|
||||
Vector3d d = vPntCtrl[0] - ORIG ;
|
||||
|
||||
double A1 = a.x * vtL.z - a.z * vtL.x ;
|
||||
double B1 = b.x * vtL.z - b.z * vtL.x ;
|
||||
double C1 = c.x * vtL.z - c.z * vtL.x ;
|
||||
double A2 = a.y * vtL.z - a.z * vtL.y ;
|
||||
double B2 = b.y * vtL.z - b.z * vtL.y ;
|
||||
double C2 = c.y * vtL.z - c.z * vtL.y ;
|
||||
|
||||
double D1 = ( d.x - ptL.x) * vtL.z - ( d.z - ptL.z) * vtL.x ;
|
||||
double D2 = ( d.y - ptL.y) * vtL.z - ( d.z - ptL.z) * vtL.y ;
|
||||
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
vdCoeff = { (B2 * D1 - B1 * D2), ( A2 * D1 - A1 * D2 + B2 * C1 - B1 * C2), ( A2 * C1 - A1 * C2)} ;
|
||||
int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
bool bFound = false ;
|
||||
for ( int w = 0 ; w < nRoots ; ++w) {
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO ) {
|
||||
double dU = 0, dV = 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( dV - vdRoots[k]) < EPS_PARAM ;
|
||||
if ( ! bAlreadyFound) {
|
||||
dU = (dV * (C1 - C2) + ( D1 - D2)) / ( dV * ( A2 - A1) + ( B2 - B1)) ;
|
||||
if ( dU > - EPS_ZERO && dU < 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 ;
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -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 ;
|
||||
}
|
||||
|
||||
@@ -1662,7 +1662,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
|
||||
// Riordino le soluzioni
|
||||
for ( int ni = 0 ; ni < int( vdPar.size()) - 1 ; ++ ni) {
|
||||
for ( int nj = ni ; nj < int( vdPar.size()) ; ++ nj) {
|
||||
if( vdPar[ni] > vdPar[nj]) {
|
||||
if ( vdPar[ni] > vdPar[nj]) {
|
||||
swap( vdPar[ni], vdPar[nj]) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di unpiano con la superficie di un solido VolZmap
|
||||
// Intersezione di un piano con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
|
||||
@@ -28,9 +28,6 @@ IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR&
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vpLoop == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
|
||||
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : MultiGeomDB.cpp Data : 08.10.25 Versione : 2.7j1
|
||||
// Contenuto : Implementazione delle funzioni tra due GeomDB.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 08.10.25 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeomDB.h"
|
||||
#include "/EgtDev/Include/EGkMultiGeomDB.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// recupero l'oggetto da copiare dal GeomDB sorgente
|
||||
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
|
||||
if ( IsNull( pGObj))
|
||||
return GDB_ID_NULL ;
|
||||
// se in globale
|
||||
if ( bGlob) {
|
||||
// recupero il riferimento del sorgente
|
||||
Frame3d frSou ;
|
||||
if ( ! pSouGDB->GetGlobFrame( nSouId, frSou))
|
||||
return GDB_ID_NULL ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
|
||||
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
|
||||
return GDB_ID_NULL ;
|
||||
// porto la copia da riferimento sorgente a quello destinazione
|
||||
pGObj->LocToLoc( frSou, frDest) ;
|
||||
}
|
||||
// lo inserisco nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, nSonBeforeAfter, Release( pGObj)) ;
|
||||
if ( nNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// recupero il riferimento del gruppo
|
||||
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
|
||||
// se in globale
|
||||
if ( bGlob) {
|
||||
// recupero il riferimento del gruppo in globale
|
||||
if ( ! pSouGDB->GetGroupGlobFrame( nSouId, frFrame))
|
||||
return GDB_ID_NULL ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
|
||||
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
|
||||
return GDB_ID_NULL ;
|
||||
// porto la copia da riferimento sorgente a quello destinazione
|
||||
frFrame.ToLoc( frDest) ;
|
||||
}
|
||||
// inserisco un nuovo gruppo nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGroup( nDestId, nRefId, nSonBeforeAfter, frFrame) ;
|
||||
if ( nNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio gli eventuali figli
|
||||
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
|
||||
while ( nSonSouId != GDB_ID_NULL) {
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nSonNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSonSouType == GDB_TY_GEO)
|
||||
nSonNewId = CopyGeoObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSonSouType == GDB_TY_GROUP)
|
||||
nSonNewId = CopyGroupObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
|
||||
// se copia non riuscita, esco con errore
|
||||
if ( nSonNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// passo al figlio successivo
|
||||
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// adatto e verifico i GeomDB
|
||||
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
|
||||
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
|
||||
if ( pSouGDB == nullptr || pDstGDB == nullptr)
|
||||
return GDB_ID_NULL ;
|
||||
// il sorgente non può essere il gruppo radice
|
||||
if ( nSouId == GDB_ID_ROOT)
|
||||
return GDB_ID_NULL ;
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSouType = pSouGDB->GetGdbType( nSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSouType == GDB_TY_GEO) {
|
||||
nNewId = CopyGeoObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
|
||||
}
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSouType == GDB_TY_GROUP) {
|
||||
nNewId = CopyGroupObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
|
||||
{
|
||||
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, false) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
CopyGlob( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
|
||||
{
|
||||
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, true) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId)
|
||||
{
|
||||
// recupero l'oggetto da copiare dal GeomDB sorgente
|
||||
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
|
||||
if ( IsNull( pGObj))
|
||||
return GDB_ID_NULL ;
|
||||
// lo inserisco nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, GDB_LAST_SON, Release( pGObj)) ;
|
||||
if ( nNewId != nDestId) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp)
|
||||
{
|
||||
int nNewId = GDB_ID_ROOT ;
|
||||
if ( nSouId != GDB_ID_ROOT) {
|
||||
// recupero il riferimento del gruppo
|
||||
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
|
||||
// inserisco un nuovo gruppo nel GeomDB destinazione
|
||||
nNewId = pDstGDB->InsertGroup( nDestId, nRefId, GDB_LAST_SON, frFrame) ;
|
||||
if ( nNewId != nSouId) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
}
|
||||
// copio gli eventuali figli
|
||||
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
|
||||
while ( nSonSouId != GDB_ID_NULL) {
|
||||
// verifico se non richiesto di saltare i temporanei oppure non lo è
|
||||
int nLevel ;
|
||||
if ( ! bSkipTemp || ! pSouGDB->GetLevel( nSonSouId, nLevel) || nLevel != GDB_LV_TEMP) {
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nSonNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSonSouType == GDB_TY_GEO)
|
||||
nSonNewId = DuplicateGeoObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId) ;
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSonSouType == GDB_TY_GROUP)
|
||||
nSonNewId = DuplicateGroupObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId, bSkipTemp) ;
|
||||
// se copia non riuscita, esco con errore
|
||||
if ( nSonNewId != nSonSouId)
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// passo al figlio successivo
|
||||
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DuplicateGeomDB( IGeomDB* pSouGeomDB, IGeomDB* pDestGeomDB, bool bSkipTemp)
|
||||
{
|
||||
// adatto e verifico i GeomDB
|
||||
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
|
||||
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
|
||||
if ( pSouGDB == nullptr || pDstGDB == nullptr)
|
||||
return false ;
|
||||
// verifico che la destinazione sia vuota
|
||||
if ( pDstGDB->GetFirstInGroup( GDB_ID_ROOT) != GDB_ID_NULL)
|
||||
return false ;
|
||||
// eseguo la copia di tutto (se richiesto salto gli oggetti temporanei)
|
||||
return ( DuplicateGroupObj( pSouGDB, GDB_ID_ROOT, pDstGDB, GDB_ID_ROOT, GDB_ID_ROOT, bSkipTemp) != GDB_ID_NULL) ;
|
||||
}
|
||||
+63
-74
@@ -17,6 +17,7 @@
|
||||
#include "NgeKeyW.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtStringConverter.h"
|
||||
#include "/EgtDev/Extern/zlib/Include/zlib.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -34,8 +35,12 @@ NgeReader::Init( const string& sFileIn)
|
||||
break ;
|
||||
case NGE_BINARY :
|
||||
m_bBinary = true ;
|
||||
m_InFile.open( stringtoW( sFileIn), ios::in | ios::binary, _SH_DENYWR) ;
|
||||
return ( ! m_InFile.fail()) ;
|
||||
m_InFile = gzopen_w( stringtoW( sFileIn), "rb") ;
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
const int DIM_BUFFER = 65536 ;
|
||||
gzbuffer( m_InFile, DIM_BUFFER) ;
|
||||
return true ;
|
||||
break ;
|
||||
}
|
||||
return false ;
|
||||
@@ -46,10 +51,12 @@ bool
|
||||
NgeReader::Close( void)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
bool bOk = ( m_InFile.good() && m_InFile.is_open()) ;
|
||||
if ( m_InFile.is_open())
|
||||
m_InFile.close() ;
|
||||
return bOk ;
|
||||
if ( m_InFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_InFile) == Z_OK) ;
|
||||
m_InFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return m_Scan.Terminate() ;
|
||||
@@ -59,31 +66,24 @@ NgeReader::Close( void)
|
||||
int
|
||||
NgeReader::NgeType( const string& sFile)
|
||||
{
|
||||
// apertura del file di ingresso
|
||||
ifstream InFile ;
|
||||
InFile.open( stringtoW( sFile), ios::in | ios::binary) ;
|
||||
if ( InFile.fail())
|
||||
// apertura file
|
||||
gzFile_s* InFile = gzopen_w( stringtoW( sFile), "rb") ;
|
||||
if ( InFile == nullptr)
|
||||
return NGE_ERROR ;
|
||||
|
||||
// lettura dei primi 31 byte
|
||||
char cBuff[32] ;
|
||||
InFile.read( cBuff, 31) ;
|
||||
cBuff[InFile.gcount()] = '\0' ;
|
||||
|
||||
// chiusura del file
|
||||
InFile.close() ;
|
||||
|
||||
// verifico se file compresso (gz)
|
||||
if ( cBuff[0] == '\x1F' && cBuff[1] == '\x8B')
|
||||
return NGE_ASCII ;
|
||||
|
||||
// verifico se iniziano con "START"
|
||||
string sBuff = cBuff ;
|
||||
size_t nPos = sBuff.find( "START") ;
|
||||
if ( nPos != string::npos && nPos < 10)
|
||||
return NGE_ASCII ;
|
||||
else
|
||||
// lettura dei primi caratteri
|
||||
char szBuff[9] = "\0\0\0\0\0\0\0\0" ;
|
||||
int nLen = gzread( InFile, &szBuff, 8) ;
|
||||
if ( gzclose( InFile) != Z_OK || nLen == Z_ERRNO)
|
||||
return NGE_ERROR ;
|
||||
// se binario
|
||||
if ( szBuff[0] == '\x0F' && szBuff[1] == '\x0F')
|
||||
return NGE_BINARY ;
|
||||
// se testo
|
||||
string sBuff{ szBuff} ;
|
||||
if ( sBuff.find( "START") != string::npos)
|
||||
return NGE_ASCII ;
|
||||
// altrimenti errore
|
||||
return NGE_ERROR ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -91,7 +91,7 @@ int
|
||||
NgeReader::GetCurrPos( void)
|
||||
{
|
||||
if ( m_bBinary)
|
||||
return int( m_InFile.tellg()) ;
|
||||
return int( gztell( m_InFile)) ;
|
||||
else
|
||||
return m_Scan.GetCurrLineNbr() ;
|
||||
}
|
||||
@@ -131,10 +131,9 @@ bool
|
||||
NgeReader::ReadUchar( unsigned char& ucVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ucVal, sizeof( ucVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ucVal, sizeof( ucVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -154,10 +153,9 @@ bool
|
||||
NgeReader::ReadBool( bool& bVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &bVal, sizeof( bVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &bVal, sizeof( bVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -173,10 +171,9 @@ bool
|
||||
NgeReader::ReadInt( int& nVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &nVal, sizeof( nVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -203,10 +200,9 @@ bool
|
||||
NgeReader::ReadDouble( double& dVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &dVal, sizeof( dVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &dVal, sizeof( dVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -222,10 +218,9 @@ bool
|
||||
NgeReader::ReadVector( Vector3d& vtV, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &vtV.v, sizeof( vtV.v)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &vtV.v, sizeof( vtV.v)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -241,10 +236,9 @@ bool
|
||||
NgeReader::ReadPoint( Point3d& ptP, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -260,11 +254,10 @@ bool
|
||||
NgeReader::ReadPointW( Point3d& ptP, double& dW, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
m_InFile.read( (char*) &dW, sizeof( dW)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO &&
|
||||
gzread( m_InFile, &dW, sizeof( dW)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -280,17 +273,13 @@ bool
|
||||
NgeReader::ReadFrame( Frame3d& frF, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
Point3d ptOrig ;
|
||||
m_InFile.read( (char*) &ptOrig.v, sizeof( ptOrig.v)) ;
|
||||
Vector3d vtDirX ;
|
||||
m_InFile.read( (char*) &vtDirX.v, sizeof( vtDirX.v)) ;
|
||||
Vector3d vtDirY ;
|
||||
m_InFile.read( (char*) &vtDirY.v, sizeof( vtDirY.v)) ;
|
||||
Vector3d vtDirZ ;
|
||||
m_InFile.read( (char*) &vtDirZ.v, sizeof( vtDirZ.v)) ;
|
||||
if ( ! m_InFile.good())
|
||||
Point3d ptOrig ; Vector3d vtDirX, vtDirY, vtDirZ ;
|
||||
if ( gzread( m_InFile, &ptOrig.v, sizeof( ptOrig.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirX.v, sizeof( vtDirX.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirY.v, sizeof( vtDirY.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirZ.v, sizeof( vtDirZ.v)) == Z_ERRNO)
|
||||
return false ;
|
||||
return frF.Set( ptOrig, vtDirX, vtDirY, vtDirZ) ;
|
||||
}
|
||||
@@ -308,18 +297,20 @@ bool
|
||||
NgeReader::ReadString( string& sVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
const int MAX_STR_DIM = 65535 ;
|
||||
if ( ! m_InFile.is_open())
|
||||
return false ;
|
||||
int nDim ;
|
||||
m_InFile.read( (char*) &nDim, sizeof( nDim)) ;
|
||||
if ( nDim > MAX_STR_DIM || ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &nDim, sizeof( nDim)) == Z_ERRNO || nDim > MAX_STR_DIM)
|
||||
return false ;
|
||||
if ( nDim == 0) {
|
||||
sVal = "" ;
|
||||
return true ;
|
||||
}
|
||||
char* szBuff = new( nothrow) char[ nDim + 1] ;
|
||||
if ( szBuff == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( szBuff, nDim) ;
|
||||
if ( ! m_InFile.good()) {
|
||||
if ( gzread( m_InFile, szBuff, nDim) == Z_ERRNO) {
|
||||
delete[] szBuff ;
|
||||
return false ;
|
||||
}
|
||||
@@ -348,12 +339,11 @@ NgeReader::ReadKey( int& nKey)
|
||||
return true ;
|
||||
}
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
// leggo il dato
|
||||
int nVal ;
|
||||
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
|
||||
if ( ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &nVal, sizeof( nVal)) == Z_ERRNO)
|
||||
return false ;
|
||||
// ricavo l'indice
|
||||
for ( int i = 0 ; i <= NGE_LAST_ID ; ++ i) {
|
||||
@@ -386,11 +376,10 @@ bool
|
||||
NgeReader::ReadCol( Color& cCol, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
unsigned char ucCol[4] ;
|
||||
m_InFile.read( (char*) &ucCol, sizeof( ucCol)) ;
|
||||
if ( ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &ucCol, sizeof( ucCol)) == Z_ERRNO)
|
||||
return false ;
|
||||
cCol.Set( ucCol[0], ucCol[1], ucCol[2], ucCol[3]) ;
|
||||
return true ;
|
||||
|
||||
+7
-5
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : NgeReader.h Data : 14.04.14 Versione : 1.5d5
|
||||
// File : NgeReader.h Data : 29.12.25 Versione : 2.7l6
|
||||
// Contenuto : Dichiarazione della classe NgeReader.
|
||||
//
|
||||
//
|
||||
@@ -18,14 +18,16 @@
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EGnScanner.h"
|
||||
#include "/EgtDev/Include/EgtStringBase.h"
|
||||
#include <fstream>
|
||||
|
||||
struct gzFile_s ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class NgeReader
|
||||
{
|
||||
public :
|
||||
NgeReader( void)
|
||||
: m_iPosStart( std::string::npos), m_bUngetKey( false), m_nFileVer() {}
|
||||
: m_bBinary( false), m_InFile( nullptr), m_iPosStart( std::string::npos),
|
||||
m_bUngetKey( false), m_nLastKey(), m_nFileVer() {}
|
||||
~NgeReader( void)
|
||||
{ Close() ; }
|
||||
bool Init( const std::string& sFileIn) ;
|
||||
@@ -60,7 +62,7 @@ class NgeReader
|
||||
private :
|
||||
bool m_bBinary ;
|
||||
// per file binari
|
||||
std::ifstream m_InFile ;
|
||||
gzFile_s* m_InFile ;
|
||||
// per file ASCII
|
||||
Scanner m_Scan ;
|
||||
std::string::size_type m_iPosStart ;
|
||||
|
||||
+64
-86
@@ -23,23 +23,23 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
WriteStringOutTxt( gzFile OutTxtFile, const char* szVal, const char* szSep, bool bEndL)
|
||||
static bool
|
||||
WriteStringOutTxt( gzFile OutFile, const char* szVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
// verifico apertura file
|
||||
if ( OutTxtFile == nullptr)
|
||||
if ( OutFile == nullptr)
|
||||
return false ;
|
||||
// scrivo stringa
|
||||
if ( gzputs( OutTxtFile, szVal) == Z_ERRNO)
|
||||
if ( gzputs( OutFile, szVal) == Z_ERRNO)
|
||||
return false ;
|
||||
// se fornito, scrivo separatore
|
||||
if ( szSep != nullptr && szSep[0] != '\0') {
|
||||
if ( gzputs( OutTxtFile, szSep) == Z_ERRNO)
|
||||
if ( gzputs( OutFile, szSep) == Z_ERRNO)
|
||||
return false ;
|
||||
}
|
||||
// se richiesto, scrivo fine linea
|
||||
if ( bEndL) {
|
||||
if ( gzputs( OutTxtFile, "\r\n") == Z_ERRNO)
|
||||
if ( gzputs( OutFile, "\r\n") == Z_ERRNO)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
@@ -50,27 +50,22 @@ bool
|
||||
NgeWriter::Init( const string& sFileOut, int nFlag)
|
||||
{
|
||||
// salvo tipo file
|
||||
m_bBinary = ( nFlag == GDB_SV_BIN) ;
|
||||
m_bBinary = ( nFlag == GDB_SV_BIN || nFlag == GDB_SV_CMPBIN) ;
|
||||
|
||||
// apertura del file di uscita
|
||||
if ( m_bBinary) {
|
||||
ios_base::openmode nMode = ios::out | ( m_bBinary ? ios::binary : 0) ;
|
||||
int nProt = _SH_DENYWR ;
|
||||
m_OutBinFile.open( stringtoW( sFileOut), nMode, nProt) ;
|
||||
return m_OutBinFile.good() ;
|
||||
if ( nFlag == GDB_SV_TXT || nFlag == GDB_SV_BIN) {
|
||||
m_OutFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
|
||||
return ( m_OutFile != nullptr) ;
|
||||
}
|
||||
else {
|
||||
if ( nFlag == GDB_SV_TXT)
|
||||
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
|
||||
else // GDB_SV_CMPTXT
|
||||
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wb") ;
|
||||
if ( m_OutTxtFile == nullptr)
|
||||
else { // GDB_SV_CMPTXT o GDB_SV_CMPBIN
|
||||
m_OutFile = gzopen_w( stringtoW( sFileOut), "wb") ;
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
const int DIM_BUFFER = 65536 ;
|
||||
if ( gzbuffer( m_OutTxtFile, DIM_BUFFER) != Z_OK)
|
||||
if ( gzbuffer( m_OutFile, DIM_BUFFER) != Z_OK)
|
||||
return false ;
|
||||
const int COMPR_LEVEL = 3 ; // 0 = no compression ... 9 = max compression
|
||||
if ( gzsetparams( m_OutTxtFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
if ( gzsetparams( m_OutFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
@@ -80,20 +75,12 @@ NgeWriter::Init( const string& sFileOut, int nFlag)
|
||||
bool
|
||||
NgeWriter::Close( void)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
bool bOk = ( m_OutBinFile.good() && m_OutBinFile.is_open()) ;
|
||||
if ( m_OutBinFile.is_open())
|
||||
m_OutBinFile.close() ;
|
||||
if ( m_OutFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_OutFile) == Z_OK) ;
|
||||
m_OutFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
else {
|
||||
if ( m_OutTxtFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_OutTxtFile) == Z_OK) ;
|
||||
m_OutTxtFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -101,13 +88,12 @@ bool
|
||||
NgeWriter::WriteUchar( unsigned char ucVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ucVal, sizeof( ucVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ucVal, sizeof( ucVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ucVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ucVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,13 +102,12 @@ bool
|
||||
NgeWriter::WriteBool( bool bVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &bVal, sizeof( bVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &bVal, sizeof( bVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( bVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( bVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,13 +116,12 @@ bool
|
||||
NgeWriter::WriteInt( int nVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &nVal, sizeof( nVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &nVal, sizeof( nVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( nVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( nVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,13 +130,12 @@ bool
|
||||
NgeWriter::WriteDouble( double dVal, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &dVal, sizeof( dVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &dVal, sizeof( dVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,15 +144,14 @@ bool
|
||||
NgeWriter::WriteString( const string& sVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
int nDim = int( sVal.size()) ;
|
||||
m_OutBinFile.write( (char*) &nDim, sizeof( nDim)) ;
|
||||
m_OutBinFile.write( sVal.c_str(), sVal.size()) ;
|
||||
return m_OutBinFile.good() ;
|
||||
int nDim = ssize( sVal) ;
|
||||
return ( gzwrite( m_OutFile, &nDim, sizeof( nDim)) > 0 &&
|
||||
( nDim == 0 || gzwrite( m_OutFile, sVal.c_str(), sVal.size()) > 0)) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, sVal.c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,13 +160,12 @@ bool
|
||||
NgeWriter::WriteVector( const Vector3d& vtV, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &vtV.v, sizeof( vtV.v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &vtV.v, sizeof( vtV.v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,13 +174,12 @@ bool
|
||||
NgeWriter::WritePoint( const Point3d& ptP, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,14 +188,13 @@ bool
|
||||
NgeWriter::WritePointW( const Point3d& ptP, double dW, const char* szSep, bool bEndL, int nPrecP, int nPrecW)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
m_OutBinFile.write( (char*) &dW, sizeof( dW)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0 &&
|
||||
gzwrite( m_OutFile, &dW, sizeof( dW)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,16 +203,15 @@ bool
|
||||
NgeWriter::WriteFrame( const Frame3d& frF, const char* szSep, bool bEndL, int nPrecP, int nPrecV)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &frF.Orig().v, sizeof( frF.Orig().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersX().v, sizeof( frF.VersX().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersY().v, sizeof( frF.VersY().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersZ().v, sizeof( frF.VersZ().v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &frF.Orig().v, sizeof( frF.Orig().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersX().v, sizeof( frF.VersX().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersY().v, sizeof( frF.VersY().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersZ().v, sizeof( frF.VersZ().v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,13 +223,12 @@ NgeWriter::WriteKey( int nKey)
|
||||
return false ;
|
||||
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &NgeBinKeyW[nKey], sizeof( int)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &NgeBinKeyW[nKey], sizeof( int)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
|
||||
return WriteStringOutTxt( m_OutFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,18 +237,17 @@ bool
|
||||
NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
unsigned char ucCol[4] ;
|
||||
ucCol[0] = cCol.GetIntRed() ;
|
||||
ucCol[1] = cCol.GetIntGreen() ;
|
||||
ucCol[2] = cCol.GetIntBlue() ;
|
||||
ucCol[3] = cCol.GetIntAlpha() ;
|
||||
m_OutBinFile.write( (char*) ucCol, sizeof( ucCol)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, ucCol, sizeof( ucCol)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( cCol).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( cCol).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,9 +255,11 @@ NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
|
||||
bool
|
||||
NgeWriter::WriteRemark( const string& sVal)
|
||||
{
|
||||
if ( m_bBinary)
|
||||
if ( m_bBinary) {
|
||||
return true ;
|
||||
else
|
||||
return ( WriteStringOutTxt( m_OutTxtFile, "//", nullptr, false) &&
|
||||
WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), nullptr, true)) ;
|
||||
}
|
||||
else {
|
||||
return ( WriteStringOutTxt( m_OutFile, "//", nullptr, false) &&
|
||||
WriteStringOutTxt( m_OutFile, sVal.c_str(), nullptr, true)) ;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-9
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : NgeWriter.h Data : 12.04.14 Versione : 1.5d5
|
||||
// File : NgeWriter.h Data : 29.12.25 Versione : 2.7l6
|
||||
// Contenuto : Dichiarazione della classe NgeWriter.
|
||||
//
|
||||
//
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "NgeConst.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include <fstream>
|
||||
|
||||
struct gzFile_s ;
|
||||
|
||||
@@ -24,7 +23,7 @@ struct gzFile_s ;
|
||||
class NgeWriter
|
||||
{
|
||||
public :
|
||||
NgeWriter( void) : m_bBinary( false), m_OutTxtFile( nullptr) {}
|
||||
NgeWriter( void) : m_bBinary( false), m_OutFile( nullptr) {}
|
||||
~NgeWriter( void)
|
||||
{ Close() ; }
|
||||
bool Init( const std::string& sFileOut, int nFlag) ;
|
||||
@@ -44,9 +43,6 @@ class NgeWriter
|
||||
bool WriteRemark( const std::string& sVal /* bEndL = true*/) ;
|
||||
|
||||
private :
|
||||
bool m_bBinary ;
|
||||
// per file binari
|
||||
std::ofstream m_OutBinFile ;
|
||||
// per file ASCII
|
||||
gzFile_s* m_OutTxtFile ;
|
||||
bool m_bBinary ;
|
||||
gzFile_s* m_OutFile ;
|
||||
} ;
|
||||
|
||||
+4
-4
@@ -243,11 +243,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( IsNull( pCrv1))
|
||||
return false ;
|
||||
pCrv1->SetTempProp( nInd1) ;
|
||||
if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
|
||||
if ( ! pCrv1->SimpleOffset( dDist)) {
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv1) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
if ( pArc->MyExtendedOffset( dDist, true))
|
||||
pCrv1->SetTempProp( - nInd1) ;
|
||||
}
|
||||
// curve successive
|
||||
@@ -255,11 +255,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
// eseguo semplice offset
|
||||
pCrv2->SetTempProp( nInd1 + 1) ;
|
||||
if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
|
||||
if ( ! pCrv2->SimpleOffset( dDist)) {
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv2) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
if ( pArc->MyExtendedOffset( dDist, true))
|
||||
pCrv2->SetTempProp( - ( nInd1 + 1)) ;
|
||||
}
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "PointsPCA.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
|
||||
|
||||
+337
-14
@@ -18,6 +18,8 @@
|
||||
#include "PolygonPlane.h"
|
||||
#include "PointsPCA.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
@@ -773,7 +775,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::RemoveAlignedPoints( double dToler)
|
||||
PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd)
|
||||
{
|
||||
// se non ci sono almeno 3 punti, esco subito
|
||||
if ( m_lUPoints.size() < 3)
|
||||
@@ -796,7 +798,7 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||
}
|
||||
// altrimenti chiusa
|
||||
else {
|
||||
@@ -817,15 +819,15 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
vInd.push_back( nMaxInd) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||
}
|
||||
|
||||
// ordino in senso crescente
|
||||
sort( vInd.begin(), vInd.end()) ;
|
||||
|
||||
// se chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[vInd.size()-2]].first).IsEpsilon( dToler)) {
|
||||
// se richiesto e chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( bStartEnd && IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[int(vInd.size())-2]].first).IsEpsilon( dToler)) {
|
||||
vInd.erase( vInd.begin()) ;
|
||||
vInd.back() = vInd.front() ;
|
||||
}
|
||||
@@ -1445,7 +1447,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
}
|
||||
// Determino tangente di riferimento
|
||||
Vector3d vtTang ;
|
||||
// se minima distanza nell'estremo iniziale del segmento
|
||||
// se minima distanza nell'estremo iniziale del segmento
|
||||
if ( AreSamePointApprox( ptMinDist, prev( itMinDistEnd)->first)) {
|
||||
// direzione del segmento
|
||||
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
@@ -1461,7 +1463,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
vtTang = vtPrevTg + vtCurrTg ;
|
||||
vtTang.Normalize() ;
|
||||
}
|
||||
// se altrimenti minima distanza nell'estremo finale del segmento
|
||||
// se altrimenti minima distanza nell'estremo finale del segmento
|
||||
else if ( AreSamePointApprox( ptMinDist, itMinDistEnd->first)) {
|
||||
// direzione del segmento
|
||||
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
@@ -1477,7 +1479,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
vtTang = vtCurrTg + vtNextTg ;
|
||||
vtTang.Normalize() ;
|
||||
}
|
||||
// altrimenti minima distanza con l'interno
|
||||
// altrimenti minima distanza con l'interno
|
||||
else {
|
||||
vtTang = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
}
|
||||
@@ -1529,6 +1531,10 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Se il punto inziale è già quello, non faccio nulla
|
||||
if ( AreSamePointEpsilon( LoopList.begin()->first, ptNewStart, dToler))
|
||||
return true ;
|
||||
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
@@ -1612,8 +1618,9 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
int nPnt2 = PL2.GetPointNbr() ;
|
||||
if ( nPnt1 == 0 || nPnt2 == 0)
|
||||
return false ;
|
||||
|
||||
bCommonInternalPoints = false ; // indica la presenza di punti interni in comune tra le due polylines
|
||||
|
||||
// indica la presenza di punti interni in comune tra le due polylines
|
||||
bCommonInternalPoints = false ;
|
||||
|
||||
vPnt1.reserve( PL1.GetPointNbr()) ;
|
||||
Point3d ptP1 ;
|
||||
@@ -1657,7 +1664,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
nMinJ = nLastJ ;
|
||||
|
||||
// verifica se è un punto interno in comune con l'altra polyline
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt1[i].second = nMinJ ;
|
||||
@@ -1687,12 +1694,328 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
if ( nMinI < nLastI)
|
||||
nMinI = nLastI ;
|
||||
|
||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt2[j].second = nMinI ;
|
||||
nLastI = nMinI ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType, PNTIVECTOR& vPnt1, PNTIVECTOR& vPnt2)
|
||||
{
|
||||
// prima trovo le associazioni senza aggiunte di punti
|
||||
Point3d ptP2 ;
|
||||
CurveComposite cc1, cc2 ;
|
||||
cc1.FromPolyLine( PL1) ;
|
||||
cc2.FromPolyLine( PL2) ;
|
||||
int nPnt1 = PL1.GetPointNbr() ;
|
||||
int nPnt2 = PL2.GetPointNbr() ;
|
||||
vector<POINTU> vMatch2 ;
|
||||
PL2.GetFirstPoint( ptP2) ;
|
||||
while ( PL2.GetNextPoint( ptP2, true)) {
|
||||
DistPointCurve dpc( ptP2, cc1, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
vMatch2.emplace_back( ptJoint, dParam) ;
|
||||
}
|
||||
|
||||
int nAtStart2 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1
|
||||
int nAtEnd2 = 0 ;
|
||||
Point3d ptP1 ; PL1.GetFirstPoint( ptP1) ;
|
||||
int c = 0 ;
|
||||
int nRep1 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1
|
||||
int nRep2 = 0 ;
|
||||
double dLastParamMatch = 0 ;
|
||||
Point3d ptLastPointMatch = ptP1 ;
|
||||
BOOLVECTOR vbRep1( nPnt1) ;
|
||||
INTVECTOR vnAddedOrNextIsRep1 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
|
||||
DBLVECTOR vdSplit1 ;
|
||||
DBLVECTOR vdMatch1 ;
|
||||
fill( vbRep1.begin(), vbRep1.end(), false) ;
|
||||
while ( PL1.GetNextPoint( ptP1, true)) {
|
||||
// devo salvarmi se matcho più punti con lo start o l'end della curva totale
|
||||
DistPointCurve dpc( ptP1, cc2, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
vdMatch1.push_back( dParam) ;
|
||||
if ( dParam < EPS_SMALL ) {
|
||||
++nAtStart2 ;
|
||||
vbRep1[c] = true ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else if ( dParam > nPnt2 - EPS_SMALL ) {
|
||||
vbRep1[c] = nAtEnd2 == 0 ? false : true ;
|
||||
vbRep1.back() = true ;
|
||||
++ nAtEnd2 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
|
||||
dParam = dLastParamMatch ;
|
||||
vbRep1[c] = true ;
|
||||
++ nRep1 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else {
|
||||
dLastParamMatch = dParam ;
|
||||
ptLastPointMatch = ptJoint ;
|
||||
// se sono già troppo vicino ad un split esistente allora non faccio nulla
|
||||
if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM) {
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
vdSplit1.push_back( dParam) ;
|
||||
// verifico se ho un match per questo punto
|
||||
// in tal caso vuol dire che sto creando una ripetizione nRep1
|
||||
int nCase = 0 ;
|
||||
for ( int j = 0 ; j < int( vMatch2.size()) ; ++j) {
|
||||
if ( abs(vMatch2[j].second - (c + 1)) < EPS_SMALL) {
|
||||
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
|
||||
bool bFoundMatch = false ;
|
||||
for ( int z = int( vMatch2[j].second) ; z < int( vdMatch1.size()) ; ++z) {
|
||||
if ( abs( vdMatch1[z] - ( j + 1 )) < EPS_SMALL ) {
|
||||
bFoundMatch = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFoundMatch) {
|
||||
++ nRep2 ;
|
||||
// capisco se il punto è rep o se lo è il suo successivo
|
||||
if ( j + 1 < dParam)
|
||||
nCase = 1 ;
|
||||
else
|
||||
nCase = 2 ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
vnAddedOrNextIsRep1.push_back( nCase) ;
|
||||
}
|
||||
++c ;
|
||||
}
|
||||
int nAtStart1 = 0 ;
|
||||
int nAtEnd1 = 0 ;
|
||||
PL2.GetFirstPoint( ptP2) ;
|
||||
c = 0 ;
|
||||
dLastParamMatch = 0 ;
|
||||
ptLastPointMatch = ptP2 ;
|
||||
INTVECTOR vnAddedOrNextIsRep2 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
|
||||
DBLVECTOR vdSplit2 ;
|
||||
BOOLVECTOR vbRep2( nPnt2) ;
|
||||
fill( vbRep2.begin(), vbRep2.end(), false) ;
|
||||
while ( PL2.GetNextPoint( ptP2, true)) {
|
||||
DistPointCurve dpc( ptP2, cc1, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
if ( dParam < EPS_SMALL ) {
|
||||
++nAtStart1 ;
|
||||
vbRep2[c] = true ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else if ( dParam > nPnt1 - EPS_SMALL ) {
|
||||
vbRep2[c] = ( nAtEnd1 == 0 ? false : true) ;
|
||||
vbRep2.back() = true ;
|
||||
++ nAtEnd1 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
|
||||
dParam = dLastParamMatch ;
|
||||
vbRep2[c] = true ;
|
||||
++ nRep2 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else {
|
||||
dLastParamMatch = dParam ;
|
||||
ptLastPointMatch = ptJoint ;
|
||||
// se sono troppo vicino ad uno split esistente allora non faccio nulla
|
||||
if ( abs( dParam - round( dParam)) < 100 * EPS_PARAM) {
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
vdSplit2.push_back( dParam) ;
|
||||
// verifico se ho un match per questo punto
|
||||
// in tal caso vuol dire che sto creando una ripetizione nRep0
|
||||
int nCase = 0 ;
|
||||
for ( int j = 0 ; j < int( vdMatch1.size()) ; ++j) {
|
||||
if ( abs( vdMatch1[j] - (c + 1)) < EPS_SMALL) {
|
||||
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
|
||||
bool bFoundMatch = false ;
|
||||
for ( int z = int( vdMatch1[j]) ; z < int( vMatch2.size()) ; ++z) {
|
||||
if ( abs( vMatch2[z].second - ( j + 1 )) < EPS_SMALL) {
|
||||
bFoundMatch = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFoundMatch) {
|
||||
++nRep1 ;
|
||||
// capisco se il punto è rep o se lo è il suo successivo
|
||||
if ( j + 1 < dParam)
|
||||
nCase = 1 ;
|
||||
else
|
||||
nCase = 2 ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
vnAddedOrNextIsRep2.push_back( nCase) ;
|
||||
}
|
||||
++c ;
|
||||
}
|
||||
|
||||
// applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep
|
||||
int nUnit = 0 ;
|
||||
if ( ! vdSplit1.empty())
|
||||
nUnit = int( vdSplit1.back()) ;
|
||||
for ( int z = int( vdSplit1.size()) - 1 ; z >= 0 ; --z) {
|
||||
double dSplit = vdSplit1[z] ;
|
||||
int nSplit = int( dSplit) ;
|
||||
// se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo
|
||||
// riscalare
|
||||
if ( nSplit == nUnit && z < int( vdSplit1.size()) - 1) {
|
||||
dSplit = nSplit + ( dSplit - nSplit) / ( vdSplit1[z+1] - nSplit) ;
|
||||
}
|
||||
nUnit = nSplit ;
|
||||
cc2.AddJoint( dSplit) ;
|
||||
switch ( vnAddedOrNextIsRep1[z]) {
|
||||
case 0 :
|
||||
if ( vbRep2[nSplit])
|
||||
++ nRep2 ;
|
||||
// di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, vbRep2[nSplit]) ;
|
||||
break ;
|
||||
case 1 :
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, true) ;
|
||||
break ;
|
||||
case 2 :
|
||||
if ( vbRep2[nSplit])
|
||||
--nRep2 ;
|
||||
else
|
||||
vbRep2[nSplit] = true ;
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, false) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( ! vdSplit2.empty())
|
||||
nUnit = int( vdSplit2.back()) ;
|
||||
for ( int z = int( vdSplit2.size()) - 1 ; z >= 0 ; --z) {
|
||||
double dSplit = vdSplit2[z] ;
|
||||
int nSplit = int( dSplit) ;
|
||||
// se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo
|
||||
// riscalare
|
||||
if ( nSplit == nUnit && z < int( vdSplit2.size()) - 1) {
|
||||
dSplit = nSplit + ( dSplit - nSplit) / (vdSplit2[z+1] - nSplit) ;
|
||||
}
|
||||
nUnit = nSplit ;
|
||||
cc1.AddJoint( dSplit) ;
|
||||
switch ( vnAddedOrNextIsRep2[z]) {
|
||||
case 0 :
|
||||
if ( vbRep1[nSplit])
|
||||
++ nRep1 ;
|
||||
// di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, vbRep1[nSplit]) ;
|
||||
break ;
|
||||
case 1 :
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, true) ;
|
||||
break ;
|
||||
case 2 :
|
||||
if ( vbRep1[nSplit])
|
||||
-- nRep1 ;
|
||||
else
|
||||
vbRep1[nSplit] = true ;
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, false) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
nPnt1 = cc1.GetCurveCount() ;
|
||||
nPnt2 = cc2.GetCurveCount() ;
|
||||
//aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true
|
||||
int nAddedSpan = 0 ;
|
||||
int nCrv1 = 0 ;
|
||||
int nCrv2 = 0 ;
|
||||
while ( nAddedSpan < nPnt1 + nAtStart1 + nAtEnd1 + nRep2) {
|
||||
if ( nCrv1 >= nPnt1)
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
if ( nCrv2 >= nPnt2)
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
if ( bRep1 && bRep2) {
|
||||
vbRep1[nCrv1] = false ;
|
||||
bRep1 = false ;
|
||||
vbRep2[nCrv2] = false ;
|
||||
bRep2 = false ;
|
||||
-- nRep1 ;
|
||||
-- nRep2 ;
|
||||
}
|
||||
if ( ! bRep1 || nCrv2 == nPnt2 - 1)
|
||||
++ nCrv2 ;
|
||||
if ( ! bRep2 || nCrv1 == nPnt1 - 1)
|
||||
++ nCrv1 ;
|
||||
++ nAddedSpan ;
|
||||
}
|
||||
// se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima
|
||||
if ( nCrv2 < nPnt2) {
|
||||
nRep2 += nPnt2 - nCrv2 ;
|
||||
for ( int z = int( vbRep2.size()) - 1 ; z >= nCrv2 ; --z)
|
||||
vbRep2[z] = true ;
|
||||
}
|
||||
if ( nCrv1 < nPnt1) {
|
||||
nRep1 += nPnt1 - nCrv1 ;
|
||||
for ( int z = int( vbRep1.size()) - 1 ; z >= nCrv1 ; --z)
|
||||
vbRep1[z] = true ;
|
||||
}
|
||||
|
||||
// trovo il numero di span che dovrà avere la superficie
|
||||
// ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0)
|
||||
int nPnt = nPnt1 + nAtStart1 + nAtEnd1 + nRep2 ;
|
||||
|
||||
if ( nPnt != nPnt2 + nAtStart2 + nAtEnd2 + nRep1)
|
||||
LOG_DBG_ERR( GetEGkLogger(), "There could be an error in the creation of a ruled surface in mode RLT_B_MINDIST_PLUS") ;
|
||||
|
||||
// aggiungo i punti di controllo scorrendo in contemporanea le due curve
|
||||
nAddedSpan = 0 ;
|
||||
nCrv1 = 0 ;
|
||||
nCrv2 = 0 ;
|
||||
bool bLast1 = false ;
|
||||
bool bLast2 = false ;
|
||||
while ( nAddedSpan < nPnt) {
|
||||
if ( nCrv1 >= nPnt1) {
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
bLast1 = true ;
|
||||
}
|
||||
if ( nCrv2 >= nPnt2) {
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bLast2 = true ;
|
||||
}
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
|
||||
Point3d ptStart1 ; pSubCrv1->GetStartPoint( ptStart1) ;
|
||||
vPnt1.emplace_back( ptStart1, nAddedSpan) ;
|
||||
const ICurve* pSubCrv2 = cc2.GetCurve( nCrv2) ;
|
||||
Point3d ptStart2 ; pSubCrv2->GetStartPoint( ptStart2) ;
|
||||
vPnt2.emplace_back( ptStart2, nAddedSpan) ;
|
||||
if ( ! bRep2)
|
||||
++ nCrv1 ;
|
||||
if ( ! bRep1)
|
||||
++ nCrv2 ;
|
||||
++ nAddedSpan ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
+22
-14
@@ -172,9 +172,9 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
|
||||
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
|
||||
dElev = max( dElev, Inters.dU) ;
|
||||
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
dElev = max( dElev, Inters.dU2) ;
|
||||
}
|
||||
}
|
||||
@@ -206,22 +206,30 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
|
||||
continue ;
|
||||
// calcolo il segmento di linea
|
||||
CurveLine clLine ;
|
||||
CurveLine clLine ;
|
||||
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
|
||||
return false ;
|
||||
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
|
||||
IntersCurveCurve intLL( clLine, ccLoop) ;
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
||||
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
||||
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].first.z) ;
|
||||
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
|
||||
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].second.z) ;
|
||||
if ( intLL.GetIntersCount() == 0) {
|
||||
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
|
||||
ptM.z = 0 ;
|
||||
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
|
||||
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ;
|
||||
}
|
||||
else {
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
||||
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
||||
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].first.z) ;
|
||||
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
|
||||
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].second.z) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+262
-201
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2023
|
||||
// EgalTech 2023-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
|
||||
// File : ProjectCurveSurfTm.cpp Data : 03.01.26 Versione : 3.1a1
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
|
||||
//
|
||||
//
|
||||
@@ -40,6 +40,13 @@ const int P5AX_CONC = 3 ; // in angolo concavo
|
||||
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static double
|
||||
GetSurfBezierTol( double dLinTol)
|
||||
{
|
||||
return max( dLinTol / 10, EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
@@ -52,6 +59,77 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set(vPt5ax[i].ptP, (vPt5ax[i].ptP - vPt5ax[j].ptP) ^ ( vPt5ax[i].vtDir1 + vPt5ax[j].vtDir1)) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
else
|
||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
else
|
||||
vPt5ax[i].nFlag = P5AX_CVEX ;
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
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.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
|
||||
@@ -63,7 +141,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
|
||||
double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ;
|
||||
// Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo
|
||||
int nInd = 0 ;
|
||||
while ( nInd < int( vPt5ax.size())) {
|
||||
while ( nInd < ssize( vPt5ax)) {
|
||||
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
|
||||
// analizzo i punti appena precedenti
|
||||
int nIpv = nInd - 1 ;
|
||||
@@ -79,7 +157,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
|
||||
}
|
||||
// analizzo i punti appena successivi
|
||||
int nInx = nInd + 1 ;
|
||||
while ( nInx < int( vPt5ax.size())) {
|
||||
while ( nInx < ssize( vPt5ax)) {
|
||||
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
|
||||
if ( dSqLen < dSqMaxLen)
|
||||
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
|
||||
@@ -97,7 +175,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
|
||||
int nPrec = 0 ;
|
||||
int nCurr = 1 ;
|
||||
int nNext = 2 ;
|
||||
while ( nNext < int( vPt5ax.size())) {
|
||||
while ( nNext < ssize( vPt5ax)) {
|
||||
bool bRemove = false ;
|
||||
// lunghezza del segmento che unisce gli adiacenti
|
||||
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
|
||||
@@ -154,7 +232,124 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
|
||||
return true ;
|
||||
}
|
||||
|
||||
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ; // vettore di oggetti intersezione massiva rette parallele SurfTM
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulle supefici a minima distanza
|
||||
int nSurfMin = -1 ;
|
||||
int nTriaMin ;
|
||||
Point3d ptMin ;
|
||||
double dMinDist ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ 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 ;
|
||||
}
|
||||
}
|
||||
|
||||
// se trovato
|
||||
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 ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// --- vettore di oggetti intersezione massiva rette parallele SurfTM --------
|
||||
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
@@ -165,11 +360,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
@@ -223,15 +418,18 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
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 :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
@@ -246,9 +444,11 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
// approssimo la curva con una polilinea alla massima risoluzione
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
@@ -259,10 +459,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||
return false ;
|
||||
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
|
||||
for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) {
|
||||
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
|
||||
if ( pIntPLSTM == nullptr) {
|
||||
for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j)
|
||||
for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j)
|
||||
delete vpIntPLSTM[j] ;
|
||||
return false ;
|
||||
}
|
||||
@@ -287,72 +487,12 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
}
|
||||
|
||||
// Libero oggetti per calcolo massivo
|
||||
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i)
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i)
|
||||
delete vpIntPLSTM[i] ;
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, ( vPt5ax[i].ptP - vPt5ax[j].ptP) ^ vtDir) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
@@ -374,11 +514,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
@@ -433,15 +573,18 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
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 :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
@@ -457,9 +600,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
@@ -483,25 +627,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// punto medio
|
||||
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
|
||||
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptMid, vpSurfTm, gpRef, dMid, Pt5ax)) {
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
@@ -526,11 +653,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
@@ -586,15 +713,18 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
{
|
||||
// Sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
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 :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
@@ -610,9 +740,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// Approssimo la curva con una polilinea alla massima risoluzione
|
||||
// Approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
@@ -636,68 +767,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir2 ^ vPt5ax[j].vtDir2) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
@@ -731,11 +802,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
// intersezione della retta con le superfici (conservo l'intersezione più alta)
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
@@ -797,15 +868,18 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
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 :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
@@ -824,8 +898,11 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
pRefTm = GetBasicSurfTriMesh( &sfRef) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurf() ;
|
||||
break ;
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ;
|
||||
break ;
|
||||
@@ -839,9 +916,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
@@ -865,25 +943,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// punto medio
|
||||
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
|
||||
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptMid, vpSurfTm, *pRefTm, dMid, Pt5ax)) {
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
+58
-22
@@ -78,7 +78,7 @@ GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ;
|
||||
if( vbInvert[vnPLIndMat[i][j]])
|
||||
if ( vbInvert[vnPLIndMat[i][j]])
|
||||
vPLOrd.back().Invert() ;
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
|
||||
const ICurve* pCrv = pCC->GetCurve( i) ;
|
||||
if( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
@@ -249,7 +249,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine ) {
|
||||
if( pGuide->GetType() == CRV_LINE)
|
||||
if ( pGuide->GetType() == CRV_LINE)
|
||||
nSpanV = 1 ;
|
||||
else if ( pGuide->GetType() == CRV_COMPO)
|
||||
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
|
||||
@@ -260,7 +260,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
|
||||
if( ! pGuideBez->IsRational())
|
||||
if ( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
@@ -297,7 +297,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
ICRVCOMPOPOVECTOR vCC ;
|
||||
INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ;
|
||||
int nMaxSpanV = nSpanV ;
|
||||
for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
@@ -327,7 +327,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
for ( int w = 0 ; w < int( vCC.size()) ; ++w) {
|
||||
const ICurveComposite* pCCOther = vCC[w] ;
|
||||
int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ;
|
||||
if( nPropCheck != 0)
|
||||
if ( nPropCheck != 0)
|
||||
mRep[w][z] = 1 ;
|
||||
}
|
||||
}
|
||||
@@ -337,11 +337,11 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
// conto in quante colonne di mRep la somma degli elementi è != 0
|
||||
// questo numero va aggiunto all'attuale nSpanV
|
||||
int nSpanPlus = 0 ;
|
||||
for( int z = 0 ; z < nMaxSpanV ; ++z) {
|
||||
for ( int z = 0 ; z < nMaxSpanV ; ++z) {
|
||||
int nPosTot = 0 ;
|
||||
for ( int k = 0 ; k < int( mRep.size()) ; ++k )
|
||||
nPosTot += mRep[k][z] ;
|
||||
if( nPosTot != 0)
|
||||
if ( nPosTot != 0)
|
||||
nSpanPlus += 1 ;
|
||||
}
|
||||
nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ;
|
||||
@@ -349,14 +349,14 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
|
||||
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
|
||||
//// aggiungo i punti di controllo alla superficie
|
||||
//for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
//for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if( pCL == nullptr)
|
||||
// if ( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if( z == 0) {
|
||||
// if ( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
@@ -367,13 +367,13 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
//}
|
||||
|
||||
//// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO
|
||||
//for( int i = 0 ; i < int( vCC.size()) ; ++i) {
|
||||
//for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if( pCL == nullptr)
|
||||
// if ( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if( z == 0) {
|
||||
// if ( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
@@ -422,7 +422,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
//// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
//pCrvU->ToLoc( frStart) ;
|
||||
//for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
//for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
@@ -458,7 +458,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
// // aggiungo i punti di controllo alla superficie
|
||||
// for ( int z = 0 ; z < nSpanV ; ++z) {
|
||||
// const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ;
|
||||
// if( pCrvBez == nullptr)
|
||||
// if ( pCrvBez == nullptr)
|
||||
// return nullptr ;
|
||||
// for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) {
|
||||
// Point3d ptCtrl = pCrvBez->GetControlPoint( k) ;
|
||||
@@ -572,7 +572,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
|
||||
if( ! pSectBez->IsRational())
|
||||
if ( ! pSectBez->IsRational())
|
||||
pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
else
|
||||
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
|
||||
@@ -709,7 +709,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, true, false)) ;
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
@@ -718,7 +718,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, true, false)) ;
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
@@ -733,18 +733,54 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifico che le curve siano valide
|
||||
for ( int i = 0 ; i < int( vCrv.size()) ; ++i) {
|
||||
if( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
|
||||
if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// se ho solo due curve allora faccio la rigata
|
||||
if( vCrv.size() == 2)
|
||||
if ( vCrv.size() == 2)
|
||||
return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ;
|
||||
|
||||
//trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado
|
||||
@@ -752,7 +788,7 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
ICURVEPOVECTOR vCrvBez ;
|
||||
for( int c = 0 ; c < int( vCrv.size()) ; ++c){
|
||||
for ( int c = 0 ; c < int( vCrv.size()) ; ++c){
|
||||
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
|
||||
if ( vCrv[c]->GetType() != CRV_BEZIER )
|
||||
pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ;
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
if( vbInvert[vnPLIndMat[i][j]])
|
||||
if ( vbInvert[vnPLIndMat[i][j]])
|
||||
vPL[vnPLIndMat[i][j]].Invert() ;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
|
||||
if( vbInvert[i])
|
||||
if ( vbInvert[i])
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
// verifico la direzione di estrusione
|
||||
|
||||
@@ -302,7 +302,7 @@ SetTmpPropByOverlap( ICurveComposite* pCrvCheck, const int nInd, const ICurveCom
|
||||
// ultimo tratto di curva della Composita iniziale
|
||||
PtrOwner<CurveComposite> pCrvB( GetBasicCurveComposite( pCrvCheck->CopyParamRange( nInd + 1, pCrvCheck->GetCurveCount()))) ;
|
||||
if ( ! IsNull( pCrvB) && pCrvB->GetCurveCount() > 0 && pCrvB->IsValid())
|
||||
if( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
|
||||
if ( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+13
-9
@@ -37,12 +37,12 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
bool bIsRational = snData.bRat ;
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vU ;
|
||||
int nKnot = (int) snData.vU.size() ;
|
||||
int nKnot = ssize( snData.vU) ;
|
||||
for ( int k = 0 ; k < nKnot ; ++k ) {
|
||||
double dKnot = snData.vU[k] ;
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
for( int j = 0 ; j < snData.nCPV ; ++j) {
|
||||
for ( int j = 0 ; j < snData.nCPV ; ++j) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
@@ -66,12 +66,16 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
|
||||
if ( snData.mCP.size() != nuCurve.vCP.size() ) {
|
||||
snData.mCP.resize( nuCurve.vCP.size()) ;
|
||||
if( snData.bRat)
|
||||
if ( snData.bRat)
|
||||
snData.mW.resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
for ( int i = 0 ; i < ssize( nuCurve.vCP) ; ++i) {
|
||||
if ( snData.mCP[i].empty())
|
||||
snData.mCP[i].resize( snData.nCPV) ;
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
if( snData.bRat) {
|
||||
if ( snData.bRat) {
|
||||
if ( snData.mW[i].empty())
|
||||
snData.mW[i].resize( snData.nCPV) ;
|
||||
snData.mW[i][j] = nuCurve.vW[i] ;
|
||||
snData.mCP[i][j] *= nuCurve.vW[i] ;
|
||||
}
|
||||
@@ -80,18 +84,18 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
}
|
||||
}
|
||||
snData.bPeriodicU = false ;
|
||||
snData.nCPU = int( snData.mCP.size()) ;
|
||||
snData.nCPU = ssize( snData.mCP) ;
|
||||
}
|
||||
if ( snData.bPeriodicV || ! snData.bClampedV) {
|
||||
bool bIsRational = snData.bRat ;
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vV ;
|
||||
int nKnot = (int) snData.vV.size() ;
|
||||
int nKnot = ssize( snData.vV) ;
|
||||
for ( int k = 0 ; k < nKnot ; ++k ) {
|
||||
double dKnot = snData.vV[k] ;
|
||||
vV.push_back( dKnot) ;
|
||||
}
|
||||
for( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
@@ -132,7 +136,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
}
|
||||
}
|
||||
snData.bPeriodicV = false ;
|
||||
snData.nCPV = int( snData.mCP[0].size()) ;
|
||||
snData.nCPV = ssize( snData.mCP[0]) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+1479
-427
File diff suppressed because it is too large
Load Diff
+18
-24
@@ -20,19 +20,9 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
using namespace std ;
|
||||
class Tree ;
|
||||
|
||||
struct PairHashIntInt {
|
||||
std::size_t operator()(const std::pair<int, int>& key) const {
|
||||
std::size_t h1 = std::hash<int>{}(key.first);
|
||||
std::size_t h2 = std::hash<int>{}(key.second);
|
||||
return h1 ^ (h2 << 1); // Combine hashes
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
{
|
||||
@@ -126,18 +116,17 @@ 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) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ;
|
||||
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
|
||||
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
|
||||
// a nIL si può passare 5 come valore di default
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
|
||||
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev = P_INVALID, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
|
||||
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
|
||||
@@ -147,16 +136,23 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
|
||||
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
|
||||
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
|
||||
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; // se la superficie non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
|
||||
// restituisce un vettore con i loop della superficie ( più di uno solo se è trimmata con un parametrico con buchi o più di un chunk)
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const override ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const override ;
|
||||
bool IsPlanar( void) const override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) override ;
|
||||
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
|
||||
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
|
||||
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
|
||||
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ;
|
||||
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
|
||||
bool RemoveCollapsedSpans() override ;
|
||||
bool SwapParameters() ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -168,7 +164,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
|
||||
public :
|
||||
SurfBezier( void) ;
|
||||
SurfBezier( const SurfBezier& sbSrc)
|
||||
SurfBezier( const SurfBezier& sbSrc) : m_pSTM( nullptr), m_pSTMRefined( nullptr), m_pTrimReg(nullptr)
|
||||
{ if ( ! CopyFrom( sbSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "SurfBezier : copy constructor error") }
|
||||
SurfBezier& operator =( const SurfBezier& sbSrc)
|
||||
@@ -210,8 +206,6 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
|
||||
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
|
||||
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||
// funzione che calcola se gli edge sono collassati in poli
|
||||
bool CalcPoles( void) const ;
|
||||
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
|
||||
@@ -230,15 +224,15 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U ( gli edge a V=0 e V=1 coincidono)
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V ( gli edge a U=0 e U=1 coincidono)
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ; // vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable std::vector<ICRVCOMPOPOVECTOR> m_mCCEdge ; // vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
|
||||
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
|
||||
mutable DBLVECTOR m_vBernU ;
|
||||
|
||||
+2
-1
@@ -56,6 +56,7 @@ SurfFlatRegion::Clear( void)
|
||||
for ( auto& pLoop : m_vpLoop)
|
||||
delete pLoop ;
|
||||
m_vpLoop.clear() ;
|
||||
m_vExtInd.clear() ;
|
||||
|
||||
m_nTempProp[0] = 0 ;
|
||||
m_nTempProp[1] = 0 ;
|
||||
@@ -827,7 +828,7 @@ SurfFlatRegion::ConvertArcsToBezierCurves( void)
|
||||
// ciclo sui loop
|
||||
for ( auto& pLoop : m_vpLoop) {
|
||||
if ( pLoop->GetType() == CRV_ARC) {
|
||||
ICurve* pCrvNew = ArcToBezierCurve( pLoop) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc(pLoop)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
delete pLoop ;
|
||||
|
||||
+68
-9
@@ -517,9 +517,9 @@ SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const
|
||||
// verifico esistenza del vertice
|
||||
if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL)
|
||||
return false ;
|
||||
// recupero i dati
|
||||
dU = m_vVert[nId].dU ;
|
||||
dV = m_vVert[nId].dV ;
|
||||
// recupero i dati (verso l'esterno sempre in 0..1..2..3..)
|
||||
dU = m_vVert[nId].dU / PREC_SCALE_COEFF ;
|
||||
dV = m_vVert[nId].dV / PREC_SCALE_COEFF ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -870,15 +870,21 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
if ( nPos == -1)
|
||||
return false ;
|
||||
|
||||
// medio le normali, finch� non incontro degli spigoli
|
||||
vtN = m_vTria[nT].vtN ;
|
||||
// medio le normali, finchè non incontro degli spigoli
|
||||
double dAngW = 1 ;
|
||||
GetTriangleVertexAngle( nT, nV, dAngW) ;
|
||||
vtN = dAngW * m_vTria[nT].vtN ;
|
||||
// parto dal triangolo e vado in direzione positiva
|
||||
int nLim = nPos ;
|
||||
for ( int i = NextIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nPos && i < int( vT.size()) ;
|
||||
i = NextIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
|
||||
int nK ; double dAngW = 1 ;
|
||||
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
|
||||
GetTriangleVertexAngle( vT[i], nK, dAngW))
|
||||
vtN += dAngW * m_vTria[vT[i]].vtN ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
nLim = i ;
|
||||
@@ -887,8 +893,12 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
for ( int i = PrevIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nLim && i >= 0 ;
|
||||
i = PrevIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
|
||||
int nK ; double dAngW = 1 ;
|
||||
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
|
||||
GetTriangleVertexAngle( vT[i], nK, dAngW))
|
||||
vtN += dAngW * m_vTria[vT[i]].vtN ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
}
|
||||
@@ -897,6 +907,23 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetTriangleVertexAngle( int nT, int nV, double& dAng) const
|
||||
{
|
||||
// verifico esistenza del triangolo e validità vertice
|
||||
if ( nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL || nV < 0 || nV > 2)
|
||||
return false ;
|
||||
// determino i vettori dei due lati che partono dal vertice
|
||||
Point3d ptVert = m_vVert[ m_vTria[nT].nIdVert[nV]].ptP ;
|
||||
Point3d ptPrev = m_vVert[ m_vTria[nT].nIdVert[Prev( nV)]].ptP ;
|
||||
Point3d ptNext = m_vVert[ m_vTria[nT].nIdVert[Next( nV)]].ptP ;
|
||||
Vector3d vtPrev = ptPrev - ptVert ;
|
||||
Vector3d vtNext = ptNext - ptVert ;
|
||||
// determino l'angolo tra i due lati
|
||||
return vtPrev.GetAngle( vtNext, dAng) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneTriangle( int nT) const
|
||||
@@ -1340,6 +1367,8 @@ SurfTriMesh::GetTitle( void) const
|
||||
bool
|
||||
SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
{
|
||||
// visualizzazione spigoli
|
||||
sOut += "ShowEdges=" + ToString( GetShowEdges()) + szNewLine ;
|
||||
// area
|
||||
double dArea ;
|
||||
GetArea( dArea) ;
|
||||
@@ -3637,6 +3666,18 @@ SurfTriMesh::Invert( void)
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
|
||||
InvertTriangle( i) ;
|
||||
|
||||
// se bordi della sfaccettatura validi
|
||||
if ( m_bFacEdged) {
|
||||
for ( int nE = 0 ; nE < GetEdgeCount() ; ++ nE) {
|
||||
// inversione dei vertici nel vettore delle sfaccettature
|
||||
swap( m_vFacEdge[nE].nIdVert[0], m_vFacEdge[nE].nIdVert[1]) ;
|
||||
// inversione delle adiacenze nel vettore delle sfaccettature
|
||||
swap( m_vFacEdge[nE].nIdFacAdj[0], m_vFacEdge[nE].nIdFacAdj[1]) ;
|
||||
// inversione dell'angolo interno
|
||||
m_vFacEdge[nE].dIntAng *= -1. ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -4500,3 +4541,21 @@ SurfTriMesh::AdjustTopologyFromZMap( void)
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetTriaFromFace( int nF, int& nT) const
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico stato sfaccettatura
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
// l'indice della faccia deve essere nei limiti
|
||||
if ( nF < 0 || nF >= int( m_vFacet.size()))
|
||||
return false ;
|
||||
// recupero la normale di un triangolo della faccetta
|
||||
nT = m_vFacet[nF] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -322,6 +322,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double& dAng) const override ;
|
||||
bool GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) const override ;
|
||||
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
|
||||
bool GetCurvature( int nV,
|
||||
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const override ;
|
||||
bool Cut( const Plane3d& plPlane, bool bSaveOnEq) override ;
|
||||
bool GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) override ;
|
||||
bool Add( const ISurfTriMesh& Other) override ;
|
||||
@@ -378,6 +380,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool SetTempInt( int nId, int nTempInt) const ;
|
||||
bool AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol = 2 * EPS_SMALL) ;
|
||||
bool AdjustTopologyFromZMap( void) ;
|
||||
bool GetTriaFromFace( int nF, int& nT) const ;
|
||||
|
||||
private :
|
||||
typedef std::vector<StmVert> VERTVECTOR ;
|
||||
@@ -411,6 +414,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
int NextIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
|
||||
int PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
|
||||
bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ;
|
||||
bool GetTriangleVertexAngle( int nT, int nV, double& dAng) const ;
|
||||
bool MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const ;
|
||||
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
|
||||
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const double BOOLEAN_SCALE = 1024 ;
|
||||
const double BOOLEAN_SCALE = PREC_SCALE_COEFF ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const double CUT_SCALE = 1024 ;
|
||||
const double CUT_SCALE = PREC_SCALE_COEFF ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
|
||||
+167
-19
@@ -21,6 +21,8 @@
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -54,7 +56,7 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
bool bOk = true ;
|
||||
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
|
||||
int i = vOldFacet[j] ;
|
||||
// salto triangoli inesistenti o già assegnati
|
||||
// salto triangoli inesistenti o già assegnati
|
||||
if ( i >= int( m_vTria.size()) ||
|
||||
m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nIdFacet != SVT_NULL)
|
||||
@@ -69,7 +71,7 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
|
||||
// ricostruisco le altre sfaccettature
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nIdFacet != SVT_NULL)
|
||||
continue ;
|
||||
@@ -103,7 +105,7 @@ SurfTriMesh::UpdateOneFace( int nFacet, int nT)
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( nT) ;
|
||||
// finchè set non vuoto
|
||||
// finchè set non vuoto
|
||||
bool bOk = true ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
@@ -421,7 +423,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 0 è di contorno
|
||||
// se il lato 0 è di contorno
|
||||
else if ( nAdjF[0] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -433,7 +435,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 1 è di contorno
|
||||
// se il lato 1 è di contorno
|
||||
else if ( nAdjF[1] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -445,7 +447,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 2, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 2 è di contorno
|
||||
// se il lato 2 è di contorno
|
||||
else if ( nAdjF[2] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -457,7 +459,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 0, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti non c'è contorno
|
||||
// altrimenti non c'è contorno
|
||||
else {
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
@@ -476,7 +478,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
return false ;
|
||||
// se loop esterno
|
||||
if ( vtN * plPlane.GetVersN() > 0) {
|
||||
// se non c'è ancora loop esterno in prima posizione
|
||||
// se non c'è ancora loop esterno in prima posizione
|
||||
if ( ! bOutFirst) {
|
||||
// lo sposto in prima posizione
|
||||
if ( i != 0)
|
||||
@@ -517,7 +519,7 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
|
||||
// verifico appartenga alla stessa faccia
|
||||
if ( m_vTria[nAdjT].nIdFacet != nF)
|
||||
return false ;
|
||||
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
|
||||
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
|
||||
int nAdjS = SVT_NULL ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
|
||||
@@ -531,11 +533,11 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
|
||||
return false ;
|
||||
// vertice di fine adiacenza e indice del successivo lato
|
||||
int nAdjV = Next( nAdjS) ;
|
||||
// verifico se il lato successivo è un bordo
|
||||
// verifico se il lato successivo è un bordo
|
||||
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
|
||||
int nNextF = ( nNextT != SVT_NULL ? m_vTria[nNextT].nIdFacet : SVT_NULL) ;
|
||||
if ( nNextF != nF) {
|
||||
// se già recuperato
|
||||
// se già recuperato
|
||||
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
|
||||
bEnd = true ;
|
||||
return true ;
|
||||
@@ -593,7 +595,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
|
||||
// verifico esistenza seconda faccia
|
||||
if ( nF2 < 0 || nF2 >= int( m_vFacet.size()))
|
||||
return false ;
|
||||
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
|
||||
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
|
||||
bAdjac = false ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
double dUs, dUe ;
|
||||
@@ -606,7 +608,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
|
||||
ptP2 = ptPe ;
|
||||
}
|
||||
else {
|
||||
// parametri del segmento già definito
|
||||
// parametri del segmento già definito
|
||||
Vector3d vtT ;
|
||||
double dLen ;
|
||||
DirDist( ptP1, ptP2, vtT, dLen) ;
|
||||
@@ -646,7 +648,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||
return false ;
|
||||
// calcolo il centro del loop esterno (è il primo)
|
||||
// calcolo il centro del loop esterno (è il primo)
|
||||
PolygonPlane PolyPlane ;
|
||||
Point3d ptP ;
|
||||
for ( bool bFound = vPL[0].GetFirstPoint( ptP) ; bFound ; bFound = vPL[0].GetNextPoint( ptP))
|
||||
@@ -730,7 +732,7 @@ SurfTriMesh::CloneFacet( int nF) const
|
||||
// ciclo sui tre vertici
|
||||
int nIdV[3] ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
// verifico se vertice già presente
|
||||
// verifico se vertice già presente
|
||||
const auto it = PntMap.find( m_vTria[nT].nIdVert[j]) ;
|
||||
if ( it == PntMap.end()) {
|
||||
// aggiungo il vertice
|
||||
@@ -773,7 +775,7 @@ SurfTriMesh::RemoveFacet( int nF)
|
||||
if ( ! DoCompacting())
|
||||
return false ;
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
@@ -878,7 +880,7 @@ SurfTriMesh::UpdateFacetEdging( void)
|
||||
m_bFacEdged = false ;
|
||||
m_vFacEdge.clear() ;
|
||||
|
||||
// verifico validità sfaccettatura
|
||||
// verifico validità sfaccettatura
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
|
||||
@@ -957,7 +959,7 @@ SurfTriMesh::GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double&
|
||||
// verifico stato bordi sfaccettatura
|
||||
if ( ! VerifyFacetEdging())
|
||||
return false ;
|
||||
// verifico la validità dell'indice
|
||||
// verifico la validità dell'indice
|
||||
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
|
||||
return SVT_NULL ;
|
||||
// recupero i dati
|
||||
@@ -980,7 +982,7 @@ SurfTriMesh::GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) cons
|
||||
// verifico stato bordi sfaccettatura
|
||||
if ( ! VerifyFacetEdging())
|
||||
return false ;
|
||||
// verifico la validità dell'indice
|
||||
// verifico la validità dell'indice
|
||||
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
|
||||
return SVT_NULL ;
|
||||
// recupero i dati
|
||||
@@ -1015,3 +1017,149 @@ SurfTriMesh::GetEdges( ICURVEPOVECTOR& vpCurve) const
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Funzione per il calcolo della curvatura massima e minima in un vertice della superficie TriMesh
|
||||
// dMinK : curvatura minima
|
||||
// vtMinK : versore direzione curvatura minima
|
||||
// dMaxK : curvatura massima
|
||||
// vtMaxK : versore direzione curvatura massima
|
||||
// bPlanar : Flag per indicare le superficie localmente piana
|
||||
// vtNorm : versore normale del piano tangente alla supericie nel vertice
|
||||
bool
|
||||
SurfTriMesh::GetCurvature( int nV,
|
||||
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const
|
||||
{
|
||||
// Controllo la validità della TriMesh e del Vertice
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
Point3d ptCurr ;
|
||||
if ( ! GetVertex( nV, ptCurr))
|
||||
return false ;
|
||||
bPlanar = false ;
|
||||
|
||||
// Recupero tutti i vertici attorno al vertice corrente ( se presenza di lato libero, allora errore)
|
||||
INTVECTOR vT ;
|
||||
bool bCirc ;
|
||||
if ( ! GetAllTriaAroundVertex( nV, vT, bCirc) || ! bCirc)
|
||||
return false ;
|
||||
|
||||
// Calcolo la normale del vertice pesata mediante angolo sotteso e distanza baricentrica
|
||||
// ["Estimation Normal Vector of Triangular Mesh Vertex by Angle and Centroid Weights"]
|
||||
// Controllo anche di non essere in presenza di uno spigolo vivo
|
||||
INTSET setIndTriaNeightbors ;
|
||||
bool bFirstTria = true ;
|
||||
Vector3d vtNFirstTria = V_NULL ;
|
||||
for ( const int& nT : vT) {
|
||||
// Recupero il triangolo corrente
|
||||
Triangle3d Tria ;
|
||||
int nIdVert[3] ;
|
||||
if ( ! GetTriangle( nT, Tria) || ! GetTriangle( nT, nIdVert))
|
||||
return false ;
|
||||
// Se il triangolo ha area troppo piccola, lo scarto
|
||||
if ( Tria.GetArea() < EPS_SMALL)
|
||||
continue ;
|
||||
// Se primo triangolo salvo la sua normale di riferimento per successivi confronti
|
||||
if ( bFirstTria) {
|
||||
vtNFirstTria = Tria.GetN() ;
|
||||
bFirstTria = false ;
|
||||
}
|
||||
else {
|
||||
// Se spigolo vivo, la curvatura non può esistere
|
||||
if ( Tria.GetN() * vtNFirstTria < m_dCosSmAng - EPS_SMALL)
|
||||
return false ;
|
||||
}
|
||||
// Recupero le direzioni delle semirette per l'angolo al vertice corrente
|
||||
Vector3d vtDir0 = V_NULL, vtDir1 = V_NULL ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( AreSamePointApprox( Tria.GetP( i), ptCurr)) {
|
||||
vtDir0 = Tria.GetP( ( i + 1) % 3) - Tria.GetP( i) ;
|
||||
vtDir0.Normalize() ;
|
||||
vtDir1 = Tria.GetP( ( i + 2) % 3) - Tria.GetP( i) ;
|
||||
vtDir1.Normalize() ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( nV == nIdVert[i]) {
|
||||
setIndTriaNeightbors.insert( nIdVert[( i + 1) % 3]) ;
|
||||
setIndTriaNeightbors.insert( nIdVert[( i + 2) % 3]) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// Calcolo l'angolo sotteso
|
||||
double dCosTheta = max( -1., min( 1., ( vtDir0 * vtDir1))) ;
|
||||
double dTheta = acos( dCosTheta) ;
|
||||
// Calcolo la distanza baricentrica
|
||||
double dSqBarDist = max( EPS_SMALL, ( ptCurr - Tria.GetCentroid()).SqLen()) ;
|
||||
// Aggiorno il contributo della normale al vertice
|
||||
vtNorm += ( ( dTheta / dSqBarDist) * Tria.GetN()) ;
|
||||
}
|
||||
vtNorm.Normalize() ;
|
||||
|
||||
// [ESTIMATING CURVATURE ON TRIANGULAR MESHES, cap. 2.1. Fitting Methods,
|
||||
// par. 2.1.2. Quadric Fitting]
|
||||
// [https://people.eecs.berkeley.edu/~jrs/meshpapers/GatzkeGrimm.pdf]
|
||||
|
||||
// Definisco il piano tangente al vertice corrente
|
||||
Plane3d plTan ;
|
||||
if ( ! plTan.Set( ptCurr, vtNorm))
|
||||
return false ;
|
||||
|
||||
// Proietto i punti Neightbors(1) sul piano tangete ( senza ripeterli)
|
||||
BIPNTVECTOR vPtPtProj ; vPtPtProj.reserve( setIndTriaNeightbors.size()) ;
|
||||
for ( auto nIter = setIndTriaNeightbors.begin() ; nIter != setIndTriaNeightbors.end() ; ++ nIter) {
|
||||
Point3d ptNeightbors ;
|
||||
if ( ! GetVertex( *nIter, ptNeightbors))
|
||||
return false ;
|
||||
vPtPtProj.emplace_back( make_pair( ptNeightbors, ProjectPointOnPlane( ptNeightbors, plTan))) ;
|
||||
}
|
||||
|
||||
// Recupero due versori perpendicolari nel piano definito
|
||||
Vector3d vtTan1 = V_NULL ;
|
||||
if ( abs( vtNorm.x) < 1./64. && abs( vtNorm.y) < 1./64.)
|
||||
vtTan1 = Y_AX ^ vtNorm ;
|
||||
else
|
||||
vtTan1 = Z_AX ^ vtNorm ;
|
||||
vtTan1.Normalize() ;
|
||||
Vector3d vtTan2 = vtNorm ^ vtTan1 ;
|
||||
vtTan2.Normalize() ;
|
||||
|
||||
// Sistema da risolvere mediante minimi quadrati : z(u,v) = Au^2 + Buv + Cv^2
|
||||
// Questo sistema è molto più semplice e robusto rispetto a z(u,v) = Au^2 + Buv + Cv^2 + Du + Ev + F
|
||||
// per il fatto che ora le coordinate sono in locale al piano tangente alla superficie ( mettendo
|
||||
// quindi a 0 i coefficienti del primo ordine e il termine noto F)
|
||||
// Definizione della matrice A(Nx3)
|
||||
const int nPts = int( vPtPtProj.size()) ;
|
||||
Eigen::MatrixXd mat_A( nPts, 3) ;
|
||||
Eigen::VectorXd vec_b( nPts) ;
|
||||
for ( int i = 0 ; i < nPts ; ++ i) {
|
||||
Vector3d vtEdgeProj = vPtPtProj[i].second - ptCurr ;
|
||||
Vector3d vtEdge = ( vPtPtProj[i].first - vPtPtProj[i].second) ;
|
||||
double dU = vtEdgeProj * vtTan1 ;
|
||||
double dV = vtEdgeProj * vtTan2 ;
|
||||
double dW = vtEdge * vtNorm ;
|
||||
mat_A( i, 0) = dU * dU ;
|
||||
mat_A( i, 1) = dU * dV ;
|
||||
mat_A( i, 2) = dV * dV ;
|
||||
vec_b( i) = dW ;
|
||||
}
|
||||
// Risoluzione del sistema
|
||||
Eigen::VectorXd vec_x = mat_A.colPivHouseholderQr().solve( vec_b) ;
|
||||
|
||||
// Costruzione della matrice hessiana
|
||||
Eigen::Matrix2d mat_H {{ 2. * vec_x( 0), vec_x( 1)},
|
||||
{ vec_x( 1), 2. * vec_x( 2)}} ;
|
||||
|
||||
// Calcolo gli autovalori ( quindi le curvature principali) e restituisco i risultati
|
||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> Solver( mat_H) ;
|
||||
dMinK = Solver.eigenvalues()( 0) ;
|
||||
dMaxK = Solver.eigenvalues()( 1) ;
|
||||
Eigen::Vector2d dir_Min = Solver.eigenvectors().col( 0) ;
|
||||
Eigen::Vector2d dir_Max = Solver.eigenvectors().col( 1) ;
|
||||
vtMinK = dir_Min( 0) * vtTan1 + dir_Min( 1) * vtTan2 ;
|
||||
vtMaxK = dir_Max( 0) * vtTan1 + dir_Max( 1) * vtTan2 ;
|
||||
bPlanar = ( abs( dMinK) < EPS_SMALL && abs( dMaxK) < EPS_SMALL) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+685
-10
@@ -9,13 +9,33 @@
|
||||
// Modifiche : 10.06.25 RE Creazione modulo.
|
||||
// 10.06.25 RE Offset di superfici chiuse.
|
||||
// 04.07.25 RE Thickening Offset di superfici generiche.
|
||||
// 10.12.25 RE Creazione superfici Shell.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include <future>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
||||
#include "/EgtDev/Include/EGkStmStandard.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
std::vector<IGeoObj*> VT ;
|
||||
std::vector<Color> VC ;
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -45,6 +65,255 @@ SumStm( const CISURFTMPVECTOR& vStm)
|
||||
return ( Release( pStmAdd)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzioni per la distanza tra punto e superficie TriMesh in parallelo
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
|
||||
{
|
||||
// svuoto il risultato
|
||||
vBoxDiff.clear() ;
|
||||
// se box A vuoto, risultato vuoto
|
||||
if ( boxA.IsEmpty())
|
||||
return false ;
|
||||
// se box B vuoto o i box non si intersecano, risultato è ancora A
|
||||
BBox3d boxInt ;
|
||||
if ( boxB.IsSmall() || ! boxA.FindIntersection( boxB, boxInt)) {
|
||||
vBoxDiff.emplace_back( boxA) ;
|
||||
return true ;
|
||||
}
|
||||
// recupero i punti estremi dei box A e Intersezione
|
||||
Point3d ptMinA, ptMaxA ; boxA.GetMinMax( ptMinA, ptMaxA) ;
|
||||
Point3d ptMinInt, ptMaxInt ; boxInt.GetMinMax( ptMinInt, ptMaxInt) ;
|
||||
// sotto
|
||||
if ( ptMinInt.z - ptMinA.z > EPS_SMALL) {
|
||||
BBox3d boxD( ptMinA, Point3d( ptMaxA.x, ptMaxA.y, ptMinInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// sopra
|
||||
if ( ptMaxA.z - ptMaxInt.z > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMaxInt.z), ptMaxA) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// davanti
|
||||
if ( ptMinInt.y - ptMinA.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMinInt.z), Point3d( ptMaxA.x, ptMinInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// dietro
|
||||
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMaxInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxA.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// sinistra
|
||||
if ( ptMinInt.x - ptMinA.x > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinInt.y, ptMinInt.z), Point3d( ptMinInt.x, ptMaxInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// destra
|
||||
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMaxInt.x, ptMinInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// risultato
|
||||
return ( ! vBoxDiff.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
DistPointSurfTmMultiThread( const Point3d& ptP, const SurfTriMesh& SurfTm, double& dDist,
|
||||
bool& bIsInside, INTVECTOR& vIndClosestTria)
|
||||
{
|
||||
// verifico che la supercicie sia valida
|
||||
if ( ! SurfTm.IsValid())
|
||||
return false ;
|
||||
|
||||
// inizializzo distanza non calcolata
|
||||
dDist = - 1. ;
|
||||
// vettore di indici dei triangoli più vicini inizialmente vuoto
|
||||
vIndClosestTria.clear() ;
|
||||
// vettore dei flag temporanei inizialmente tutto a 0
|
||||
INTVECTOR vIntFlags( SurfTm.GetTriangleCount(), 0) ;
|
||||
|
||||
// recupero e verifico il box locale della superficie
|
||||
BBox3d b3Stm = SurfTm.GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return false ;
|
||||
|
||||
// cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
|
||||
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
|
||||
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
|
||||
double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ;
|
||||
double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ;
|
||||
// considero anche il box precedente per poter analizzare solo il volume differenza tra i due
|
||||
BBox3d boxPPrev( ptP) ;
|
||||
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
|
||||
// variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
|
||||
double dMinDist = DBL_MAX ;
|
||||
int nMinDistTriaIndex = SVT_NULL ;
|
||||
Point3d ptMinDistPoint ;
|
||||
// finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
bool bContinue = true ;
|
||||
|
||||
// creazione del vettore dei triangoli più vicini a ptP
|
||||
vector<pair<int, Triangle3d>> vTria ; // <indice triangolo, Triangolo>
|
||||
while ( bContinue) {
|
||||
// calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
bool bCollide = false ;
|
||||
for ( const auto& b3Box : vBox) {
|
||||
// interseco il box con quello della superficie e ne verifico la distanza minima dal punto
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.DistFromPoint( ptP) > dMinDist)
|
||||
continue ;
|
||||
// ricerca sui triangoli nel box
|
||||
bCollide = true ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( SurfTm.GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
// ciclo sui triangoli del sotto-box corrente
|
||||
for ( auto nT : vnIds) {
|
||||
Triangle3d trCurTria ;
|
||||
if ( vIntFlags[nT] == 0 && SurfTm.GetTriangle( nT, trCurTria)) {
|
||||
vIntFlags[nT] = 1 ;
|
||||
DistPointTriangle distPT( ptP, trCurTria) ;
|
||||
double dCurrDist ;
|
||||
// se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetDist( dCurrDist)) {
|
||||
// se distanze uguali...
|
||||
if ( abs( dCurrDist - dMinDist) < EPS_SMALL)
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
// se minore...
|
||||
else if ( dCurrDist < dMinDist) {
|
||||
// pulisco il vettore
|
||||
vTria.clear() ;
|
||||
dMinDist = dCurrDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
|
||||
if ( ! bCollide || dMinDist < EPS_SMALL)
|
||||
bContinue = false ;
|
||||
else {
|
||||
boxPPrev = boxP ;
|
||||
boxP.Expand( dDeltaLen) ;
|
||||
}
|
||||
}
|
||||
// se non ho trovato nessun triangolo, errore
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return false ;
|
||||
|
||||
// riempio il vettore dei triangoli a minima distanza
|
||||
for ( auto& Tria : vTria)
|
||||
vIndClosestTria.emplace_back( Tria.first) ;
|
||||
// salvo la distanza
|
||||
dDist = dMinDist ;
|
||||
|
||||
// determino il Side
|
||||
if ( dDist < EPS_SMALL) {
|
||||
bIsInside = false ;
|
||||
return true ;
|
||||
}
|
||||
// se ho solo un triangolo
|
||||
else if ( int( vTria.size()) == 1) {
|
||||
bIsInside = ( ( ptP - ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// controllo se tutti i triangoli a minima distanza forniscono la stessa informazione
|
||||
// ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito )
|
||||
bool bInside = false ;
|
||||
bool bOutside = false ;
|
||||
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) {
|
||||
if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL)
|
||||
bInside = true ;
|
||||
else
|
||||
bOutside = true ;
|
||||
}
|
||||
|
||||
bIsInside = false ;
|
||||
if ( bOutside == bInside) {
|
||||
Point3d ptBar_tot ;
|
||||
for ( const auto& Tria : vTria)
|
||||
ptBar_tot += Tria.second.GetCentroid() ;
|
||||
for ( const auto& Tria : vTria) {
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ;
|
||||
if ( nType == ILTT_IN) {
|
||||
DistPointTriangle( ptP, Tria.second).GetMinDistPoint( ptMinDistPoint) ;
|
||||
bIsInside = ( ( ptP - ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ;
|
||||
nMinDistTriaIndex = Tria.first ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
bIsInside = bInside ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ClassifyTrianglesMultiThread( const TRIA3DEXVECTOR& vTria, int nIndS, int nIndE,
|
||||
const SurfTriMesh& SurfTm, double dOffs, double dPrec,
|
||||
bool bSaveInside, BOOLVECTOR& vbSafe)
|
||||
{
|
||||
// verifico che la superficie sia valida
|
||||
if ( ! SurfTm.IsValid())
|
||||
return false ;
|
||||
// verifico la validità degli indici
|
||||
if ( nIndS < 0 || nIndE >= int( vTria.size()))
|
||||
return false ;
|
||||
// verifico la dimensione dei vettori
|
||||
if ( vTria.size() != vbSafe.size())
|
||||
return false ;
|
||||
|
||||
// scorro gli indici dei triangoli da classificare
|
||||
for ( int k = nIndS ; k <= nIndE ; ++ k) {
|
||||
// recupero il triangolo corrente
|
||||
const Triangle3dEx& Tria = vTria[k] ;
|
||||
// preparo gli elementi di classificazione
|
||||
DBLVECTOR vDists ; vDists.resize( 3) ;
|
||||
INTMATRIX matIndClosestTria ; matIndClosestTria.resize( 3) ;
|
||||
// verifico che i suoi punti siano distanti almeno |dOffs| - dTol dalla superficie
|
||||
vbSafe[k] = true ;
|
||||
for ( int i = 0 ; vbSafe[k] && i < 3 ; ++ i) {
|
||||
bool bIsInside = false ;
|
||||
DistPointSurfTmMultiThread( Tria.GetP( i), SurfTm, vDists[i], bIsInside, matIndClosestTria[i]) ;
|
||||
vbSafe[k] = ( ( vDists[i] > abs( dOffs) - 0.25 * dPrec) &&
|
||||
( vDists[i] < abs( dOffs) + 0.25 * dPrec) &&
|
||||
( bIsInside == bSaveInside)) ;
|
||||
}
|
||||
// se tutti sufficientemente distanti
|
||||
if ( vbSafe[k]) {
|
||||
// i triangoli a minima distanza devono avere normale simile
|
||||
bool bPerp = true ;
|
||||
for ( int i = 0 ; bPerp && i < 3 ; ++ i) {
|
||||
for ( int j = 0 ; bPerp && j < int( matIndClosestTria[i].size()) ; ++ j) {
|
||||
Triangle3d TriaCloser ;
|
||||
SurfTm.GetTriangle( matIndClosestTria[i][j], TriaCloser) ;
|
||||
bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < cos( 30. * DEGTORAD)) ;
|
||||
}
|
||||
}
|
||||
vbSafe[k] = ( ! bPerp) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -73,20 +342,146 @@ CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPr
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
double dMyPrec = max( dPrec, 100. * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
if ( abs( dOffs) < 10. * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
||||
VolZmap myVolZmap ;
|
||||
if ( ! myVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
if ( ! myVolZmap.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
// recupero le superfici aperte
|
||||
CISURFTMPVECTOR vStmOpen ;
|
||||
for ( const ISurfTriMesh* pStm : vStm) {
|
||||
if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed())
|
||||
vStmOpen.emplace_back( pStm) ;
|
||||
}
|
||||
|
||||
// --- se non ho superfici aperte
|
||||
if ( vStmOpen.empty()) {
|
||||
// restituisco la superficie TriMesh di Offset
|
||||
return ( myVolZmap.GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
// --- se ho delle superfici chiuse
|
||||
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
|
||||
for ( int nB = 0 ; nB < myVolZmap.GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria, vTriaSafe ;
|
||||
myVolZmap.GetBlockTriangles( nB, vTria) ;
|
||||
#if DEBUG
|
||||
TRIA3DVECTOR vTriaUnsafe ;
|
||||
#endif
|
||||
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
|
||||
Triangle3dEx& Tria = vTria[nT] ;
|
||||
BBox3d BBoxTria ;
|
||||
Tria.GetLocalBBox( BBoxTria) ;
|
||||
// azzero flag di colore
|
||||
vAllTria.push_back( Tria) ;
|
||||
}
|
||||
}
|
||||
// classifico i triangoli
|
||||
PtrOwner<const SurfTriMesh> pStmBasic( nullptr) ;
|
||||
if ( int( vStmOpen.size() == 1))
|
||||
pStmBasic.Set( GetBasicSurfTriMesh( CloneSurfTriMesh( vStmOpen[0]))) ;
|
||||
else {
|
||||
StmFromTriangleSoup AllOpenStmSoup ; AllOpenStmSoup.Start() ;
|
||||
for ( const ISurfTriMesh* pStmOpen : vStmOpen) {
|
||||
if ( pStmOpen != nullptr && pStmOpen->IsValid()) {
|
||||
for ( int nT = 0 ; nT < pStmOpen->GetTriangleCount() ; ++ nT) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStmOpen->GetTriangle( nT, Tria))
|
||||
AllOpenStmSoup.AddTriangle( Tria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
AllOpenStmSoup.End() ;
|
||||
pStmBasic.Set( GetBasicSurfTriMesh( AllOpenStmSoup.GetSurf())) ;
|
||||
}
|
||||
if ( pStmBasic == nullptr)
|
||||
return nullptr ;
|
||||
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return nullptr ;
|
||||
// numero di triangoli da analizzare
|
||||
int nTriaCnt = int( vAllTria.size()) ;
|
||||
// definisco un vettore di Flag per i triangoli già visitati
|
||||
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
|
||||
// numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
|
||||
if ( nThreadMax <= 1 || nTriaCnt < 50)
|
||||
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, abs( dOffs), dPrec, ( dOffs < 0.), vbSafeTria) ;
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = nTriaCnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
|
||||
vFstLst[i].second, cref( *pStmBasic), abs( dOffs), dPrec, ( dOffs < 0.), ref( vbSafeTria)) ;
|
||||
}
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
|
||||
#if DEBUG
|
||||
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
|
||||
#endif
|
||||
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
|
||||
if ( vbSafeTria[i])
|
||||
vTriaSafe.emplace_back( vAllTria[i]) ;
|
||||
#if DEBUG
|
||||
if ( ! vbSafeTria[i])
|
||||
vTriaUnSafe.emplace_back( vAllTria[i]) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
// definisco la superficie con i soli triangoli validi
|
||||
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
|
||||
for ( const Triangle3d& SafeTria : vTriaSafe)
|
||||
TriaSoup.AddTriangle( SafeTria) ;
|
||||
TriaSoup.End() ;
|
||||
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
|
||||
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
|
||||
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
|
||||
_invalidSoup.AddTriangle( _unsafeTria) ;
|
||||
_invalidSoup.End() ;
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( _invalidSoup.GetSurf()) ;
|
||||
VC.emplace_back( RED) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
|
||||
#endif
|
||||
|
||||
return ( Release( pStmOffs)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -107,10 +502,290 @@ CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs,
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
||||
VolZmap OneVolZmap ;
|
||||
if ( ! OneVolZmap.CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
if ( ! OneVolZmap.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
return ( OneVolZmap.GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per creare la Superficie TriMesh Shell da una Trimesh aperta
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshShell( const ISurfTriMesh* pStm, double dThick, double dPrec)
|
||||
{
|
||||
// verifico che la superficie sia valida ed aperta
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || pStm->IsClosed())
|
||||
return nullptr ;
|
||||
// lo spessore deve essere sempre positivo, il verso è sempre dato dalla normale dei triangoli
|
||||
dThick = - max( 10. * EPS_SMALL, abs( dThick)) ;
|
||||
|
||||
// creo il suo Offset ( salvandomi lo Zmap per l'orientamento)
|
||||
#if DEBUG
|
||||
PerformanceCounter PC ; PC.Start() ;
|
||||
#endif
|
||||
VolZmap myVolZMap ;
|
||||
if ( ! myVolZMap.CreateFromTriMeshOffset( { pStm}, dThick, dPrec))
|
||||
return nullptr ;
|
||||
if ( ! myVolZMap.IsValid())
|
||||
return nullptr ;
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time : "} + ToString( PC.Stop())).c_str()) ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
VT.emplace_back( myVolZMap.Clone()) ;
|
||||
VC.emplace_back( BLACK) ;
|
||||
VT.emplace_back( pStm->Clone()) ;
|
||||
VC.emplace_back( YELLOW) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\VolZMapOffs.nge") ;
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
VT.clear() ; VC.clear() ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// recupero i triangoli dallo ZMap creato
|
||||
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
|
||||
for ( int nB = 0 ; nB < myVolZMap.GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria, vTriaSafe ;
|
||||
myVolZMap.GetBlockTriangles( nB, vTria) ;
|
||||
#if DEBUG
|
||||
TRIA3DVECTOR vTriaUnsafe ;
|
||||
#endif
|
||||
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
|
||||
Triangle3dEx& Tria = vTria[nT] ;
|
||||
BBox3d BBoxTria ;
|
||||
Tria.GetLocalBBox( BBoxTria) ;
|
||||
// azzero flag di colore
|
||||
vAllTria.push_back( Tria) ;
|
||||
}
|
||||
}
|
||||
// classifico i triangoli
|
||||
const SurfTriMesh* pStmBasic = GetBasicSurfTriMesh( pStm) ;
|
||||
if ( pStmBasic == nullptr)
|
||||
return nullptr ;
|
||||
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return nullptr ;
|
||||
// numero di triangoli da analizzare
|
||||
int nTriaCnt = int( vAllTria.size()) ;
|
||||
// definisco un vettore di Flag per i triangoli già visitati
|
||||
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
|
||||
// numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
|
||||
if ( nThreadMax <= 1 || nTriaCnt < 50)
|
||||
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, dThick, dPrec, true, vbSafeTria) ;
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = nTriaCnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
|
||||
vFstLst[i].second, cref( *pStmBasic), dThick, dPrec, true, ref( vbSafeTria)) ;
|
||||
}
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
|
||||
#if DEBUG
|
||||
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
|
||||
#endif
|
||||
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
|
||||
if ( vbSafeTria[i])
|
||||
vTriaSafe.emplace_back( vAllTria[i]) ;
|
||||
#if DEBUG
|
||||
if ( ! vbSafeTria[i])
|
||||
vTriaUnSafe.emplace_back( vAllTria[i]) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
// definisco la superficie con i soli triangoli validi
|
||||
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
|
||||
for ( const Triangle3d& SafeTria : vTriaSafe)
|
||||
TriaSoup.AddTriangle( SafeTria) ;
|
||||
TriaSoup.End() ;
|
||||
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
|
||||
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time ( exceed Approx) : "} + ToString( PC.Stop())).c_str()) ;
|
||||
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
|
||||
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
|
||||
_invalidSoup.AddTriangle( _unsafeTria) ;
|
||||
_invalidSoup.End() ;
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( _invalidSoup.GetSurf()) ;
|
||||
VC.emplace_back( RED) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// recupero i loops della superficie originaria e del suo Offset orientato ( non devono essere diminuiti)
|
||||
POLYLINEVECTOR vPL, vPLOffs ;
|
||||
if ( ! pStm->GetLoops( vPL) || ! pStmOffs->GetLoops( vPLOffs))
|
||||
return nullptr ;
|
||||
|
||||
// trasformo ogni loop in curve composite ( devono essere chiuse)
|
||||
ICRVCOMPOPOVECTOR vCompoLoops ; vCompoLoops.reserve( vPL.size()) ;
|
||||
for ( const PolyLine& PL : vPL) {
|
||||
if ( PL.IsClosed()) {
|
||||
if ( ! vCompoLoops.emplace_back( CreateCurveComposite()) ||
|
||||
! vCompoLoops.back()->FromPolyLine( PL) ||
|
||||
! vCompoLoops.back()->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
ICRVCOMPOPOVECTOR vCompoOffsLoops ; vCompoOffsLoops.reserve( vPLOffs.size()) ;
|
||||
for ( const PolyLine& PLOffs : vPLOffs) {
|
||||
if ( PLOffs.IsClosed()) {
|
||||
if ( ! vCompoOffsLoops.emplace_back( CreateCurveComposite()) ||
|
||||
! vCompoOffsLoops.back()->FromPolyLine( PLOffs) ||
|
||||
! vCompoOffsLoops.back()->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( YELLOW) ;
|
||||
for ( ICurveComposite* pCompo : vCompoLoops) {
|
||||
VT.emplace_back( pCompo->Clone()) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
}
|
||||
for ( ICurveComposite* pCompoOffs : vCompoOffsLoops) {
|
||||
VT.emplace_back( pCompoOffs->Clone()) ;
|
||||
VC.emplace_back( ORANGE) ;
|
||||
}
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\myCurve.nge") ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
#endif
|
||||
|
||||
// per ogni curva della superficie originale cerco la sua associata
|
||||
// NB. per la creazione della superficie ruled la prima curva è quellla che determina il verso
|
||||
// dei triangoli associati. Per un corretto ed automatico orientamento della superficie
|
||||
// la prima curva deve essere sempre definita dalla superficie originale ed invertita ( le
|
||||
// curve nella rigata devono seguire lo stesso orientamento
|
||||
ISURFTMPOVECTOR vStmRuled ; vStmRuled.reserve( vCompoLoops.size()) ;
|
||||
BOOLVECTOR vIndMatched( vCompoOffsLoops.size(), false) ;
|
||||
for ( ICurveComposite* pCompoLoop : vCompoLoops) {
|
||||
// sposto il punto iniziale della curva nel tratto più lungo
|
||||
double dMaxLen = - INFINITO ;
|
||||
int nIndCrv = 0 ;
|
||||
for ( int nCrv = 0 ; nCrv < pCompoLoop->GetCurveCount() ; ++ nCrv) {
|
||||
const ICurve* pCurve = pCompoLoop->GetCurve( nCrv) ;
|
||||
if ( pCurve != nullptr && pCurve->IsValid()) {
|
||||
double dCurrLen = 0. ;
|
||||
pCurve->GetLength( dCurrLen) ;
|
||||
if ( dCurrLen > dMaxLen) {
|
||||
dMaxLen = dCurrLen ;
|
||||
nIndCrv = nCrv ;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCompoLoop->ChangeStartPoint( nIndCrv + 0.5) ;
|
||||
Point3d ptStart ; pCompoLoop->GetStartPoint( ptStart) ;
|
||||
// dalle altre curve derivanti dalla superficie di Offset cerco quella più vicina al punto inziale
|
||||
double dMinSqDist = INFINITO ;
|
||||
int nIndOffsCrv = -1 ;
|
||||
Point3d ptMinDist ;
|
||||
for ( int nOffsCrv = 0 ; nOffsCrv < int( vCompoOffsLoops.size()) ; ++ nOffsCrv) {
|
||||
if ( vIndMatched[nOffsCrv])
|
||||
continue ;
|
||||
// recupero la curva e calcolo la distanza
|
||||
const ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nOffsCrv] ;
|
||||
int nFlag = 0 ;
|
||||
Point3d ptCurrMinDist ;
|
||||
if ( DistPointCurve( ptStart, *pCompoOffsLoop).GetMinDistPoint( 0., ptCurrMinDist, nFlag)) {
|
||||
double dCurrSqDist = SqDist( ptStart, ptCurrMinDist) ;
|
||||
if ( dCurrSqDist < dMinSqDist) {
|
||||
dMinSqDist = dCurrSqDist ;
|
||||
nIndOffsCrv = nOffsCrv ;
|
||||
ptMinDist = ptCurrMinDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nIndOffsCrv == -1)
|
||||
return nullptr ;
|
||||
vIndMatched[ nIndOffsCrv] = true ;
|
||||
// associo le due curve
|
||||
ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nIndOffsCrv] ;
|
||||
double dParMinDist = 0. ;
|
||||
pCompoOffsLoop->GetParamAtPoint( ptMinDist, dParMinDist, 10. * EPS_SMALL) ;
|
||||
pCompoOffsLoop->ChangeStartPoint( dParMinDist) ;
|
||||
|
||||
#if DEBUG
|
||||
Color _cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ;
|
||||
VT.emplace_back( pCompoLoop->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
VT.emplace_back( pCompoOffsLoop->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
#endif
|
||||
|
||||
// creo la superficie tra queste due curve e la oriento in modo da definire un volume
|
||||
pCompoLoop->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pStmRuled( GetSurfTriMeshRuled( pCompoLoop, pCompoOffsLoop, ISurfTriMesh::RuledType::RLT_MINDIST)) ;
|
||||
if ( IsNull( pStmRuled) || ! pStmRuled->IsValid() ||
|
||||
! vStmRuled.emplace_back( Release( pStmRuled)))
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Strip generation : "} + ToString( PC.Stop())).c_str()) ;
|
||||
VT.emplace_back( vStmRuled.back()->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
_cCol.SetAlpha( .5) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\Strips.nge") ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// compongo la superficie finale
|
||||
PtrOwner<ISurfTriMesh> pStmOrig( CloneSurfTriMesh( pStm)) ;
|
||||
if ( IsNull( pStmOrig) || ! pStmOrig->IsValid())
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pStmRef( Release( pStmOrig)) ;
|
||||
if ( IsNull( pStmRef) || ! pStmRef->IsValid())
|
||||
return nullptr ;
|
||||
for ( int nStrip = 0 ; nStrip < int( vStmRuled.size()) ; ++ nStrip) {
|
||||
if ( ! pStmRef->DoSewing( *vStmRuled[nStrip]))
|
||||
return nullptr ;
|
||||
}
|
||||
if ( ! pStmRef->DoSewing( *pStmOffs))
|
||||
return nullptr ;
|
||||
pStmRef->Repair() ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Sewing : "} + ToString( PC.Stop())).c_str()) ;
|
||||
#endif
|
||||
|
||||
return ( ( ! IsNull( pStmRef) && pStmRef->IsValid()) ? Release( pStmRef) : nullptr) ;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ Tree::GetPoint( double dU, double dV, Point3d& ptP) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::SavePoint( double dU, double dV, Point3d& ptP)
|
||||
Tree::SavePoint( double dU, double dV, const Point3d& ptP)
|
||||
{
|
||||
pair<int64_t, int64_t> key( int64_t( GetHalfKey( dU)), int64_t( GetHalfKey( dV))) ;
|
||||
if ( m_mPt3d.find( key) == m_mPt3d.end())
|
||||
@@ -455,11 +455,48 @@ Tree::Split( int nId, double dSplitValue)
|
||||
{
|
||||
Cell& cToSplit = m_mTree.at(nId) ;
|
||||
// controllo che lo split non venga fatto sul lato della cella
|
||||
if ( ( cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + EPS_SMALL &&
|
||||
dSplitValue < cToSplit.GetTopRight().x - EPS_SMALL) ||
|
||||
( ! cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().y + EPS_SMALL &&
|
||||
dSplitValue < cToSplit.GetTopRight().y - EPS_SMALL)) {
|
||||
// quando si implementerà lo split a parametro libero bisognerà impedire che si facciano split troppo vicini al bordo della cella!!!!!!!!!!!!!!!!!!!
|
||||
bool bGoodSplitVert = cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + 10 * EPS_SMALL &&
|
||||
dSplitValue < cToSplit.GetTopRight().x - 10 * EPS_SMALL ;
|
||||
bool bGoodSplitHoriz = ! cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().y + 10 * EPS_SMALL &&
|
||||
dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ;
|
||||
Point3d ptP00, ptP01, ptP10, ptP11 ;
|
||||
|
||||
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) ;
|
||||
GetPoint( dSplitValue, cToSplit.GetTopRight().y, ptP11) ;
|
||||
}
|
||||
else {
|
||||
GetPoint( dSplitValue, cToSplit.GetBottomLeft().y, ptP00) ;
|
||||
GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ;
|
||||
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))
|
||||
bGoodSplitVert = false ;
|
||||
}
|
||||
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) ;
|
||||
GetPoint( cToSplit.GetTopRight().x, dSplitValue, ptP11) ;
|
||||
}
|
||||
else {
|
||||
GetPoint( cToSplit.GetBottomLeft().x, dSplitValue, ptP00) ;
|
||||
GetPoint( cToSplit.GetBottomRight().x, dSplitValue, ptP10) ;
|
||||
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))
|
||||
bGoodSplitHoriz = false ;
|
||||
}
|
||||
|
||||
if ( bGoodSplitVert || bGoodSplitHoriz) {
|
||||
cToSplit.m_dSplit = dSplitValue ;
|
||||
Cell cChild1, cChild2 ;
|
||||
cChild1.m_nDepth = cToSplit.m_nDepth + 1 ;
|
||||
@@ -727,9 +764,14 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
// se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
|
||||
// ( dSideMinVal è zero se entrambi i lati da splittare sono collassati in un punto, controllo dLengMinVal)
|
||||
bool bSplit = false ;
|
||||
bool bDimOk = ( dSideMinVal / 2 >= dSideMin || ( dSideMinVal < EPS_SMALL && dLengMinVal / 2 >= dSideMin)) ;
|
||||
bool bParamDimOk = false ;
|
||||
if ( bVert)
|
||||
bParamDimOk = ( pcToSplit->GetTopRight().x - pcToSplit->GetBottomLeft().x) / 2 > 100 * EPS_PARAM ;
|
||||
else
|
||||
bParamDimOk = ( pcToSplit->GetTopRight().y - pcToSplit->GetBottomLeft().y) / 2 > 100 * EPS_PARAM ;
|
||||
bool bDimOk = ( dSideMinVal / 2 >= dSideMin || ( dSideMinVal < EPS_SMALL && dLengMinVal / 2 >= dSideMin)) && bParamDimOk ;
|
||||
if ( dSideMaxVal > dSideMax) {
|
||||
bSplit = true ;
|
||||
bSplit = true ;
|
||||
//LOG_DBG_INFO( GetEGkLogger(), " Split by SideMax")
|
||||
}
|
||||
else if ( dSagV > dLinTol || dSagU > dLinTol) {
|
||||
@@ -741,15 +783,25 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
if ( bSplit) {
|
||||
pcToSplit->SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
if ( Split( nCToSplit)) {
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else {
|
||||
// sono arrivato ad una cella Leaf, quindi salvo la cella
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
pcToSplit->SetProcessed() ;
|
||||
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11))
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::VERT_EDGES ;
|
||||
else if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11))
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::HORIZ_EDGES ;
|
||||
else
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::NO_COLLAPSE ;
|
||||
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = pcToSplit->m_nParent ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
@@ -846,16 +898,26 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) {
|
||||
pcToSplit->SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
if ( Split( nCToSplit)){
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = pcToSplit->m_nChild1 ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else {
|
||||
// sono arrivato ad una cella Leaf, quindi salvo la cella
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
pcToSplit->SetProcessed() ;
|
||||
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11))
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::VERT_EDGES ;
|
||||
else if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11))
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::HORIZ_EDGES ;
|
||||
else {
|
||||
pcToSplit->m_nCollapsed = Cell::Collapsed::NO_COLLAPSE ;
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
}
|
||||
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = pcToSplit->m_nParent ;
|
||||
pcToSplit = &m_mTree[nCToSplit] ;
|
||||
@@ -889,9 +951,16 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
|
||||
Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs, DBLDBL ddInt) const
|
||||
{
|
||||
const Cell& cell = m_mTree.at( nId) ;
|
||||
double dMax = cell.GetTopRight().x ;
|
||||
double dMin = cell.GetBottomLeft().x ;
|
||||
if ( ddInt.second > 0) {
|
||||
dMax = ddInt.second ;
|
||||
dMin = ddInt.first ;
|
||||
}
|
||||
|
||||
// le celle restituite sono ordinate per x crescente
|
||||
if ( vTopNeighs.empty()) {
|
||||
if ( cell.m_nTop == -2)
|
||||
@@ -902,14 +971,14 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
|
||||
if ( m_mTree.at( cell.m_nTop).IsSplitVert()) {
|
||||
// se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( cell.m_nTop).GetTopRight().x - m_mTree.at( cell.m_nTop).GetBottomLeft().x <=
|
||||
cell.GetTopRight().x - cell.GetBottomLeft().x) {
|
||||
dMax - dMin) {
|
||||
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild1) ;
|
||||
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x )
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetTopRight().x <= dMin ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetBottomLeft().x >= dMax )
|
||||
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ;
|
||||
else
|
||||
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild1) ;
|
||||
@@ -940,14 +1009,14 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
|
||||
if ( m_mTree.at( i).IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( i).GetTopRight().x - m_mTree.at( i).GetBottomLeft().x <=
|
||||
cell.GetTopRight().x - cell.GetBottomLeft().x) {
|
||||
dMax - dMin) {
|
||||
vTopNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
vTopNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x )
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= dMin ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= dMax)
|
||||
vTopNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
else
|
||||
vTopNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
@@ -972,9 +1041,16 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
|
||||
Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs, DBLDBL ddInt) const
|
||||
{
|
||||
const Cell& cell = m_mTree.at( nId) ;
|
||||
double dMax = cell.GetTopRight().x ;
|
||||
double dMin = cell.GetBottomLeft().x ;
|
||||
if ( ddInt.second > 0) {
|
||||
dMax = ddInt.second ;
|
||||
dMin = ddInt.first ;
|
||||
}
|
||||
|
||||
// le celle restituite sono ordinate per x crescente
|
||||
if ( vBottomNeighs.empty()) {
|
||||
if ( cell.m_nBottom == -2)
|
||||
@@ -985,14 +1061,14 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
|
||||
if ( m_mTree.at( cell.m_nBottom).IsSplitVert()) {
|
||||
// se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( cell.m_nBottom).GetTopRight().x - m_mTree.at( cell.m_nBottom).GetBottomLeft().x <=
|
||||
cell.GetTopRight().x - cell.GetBottomLeft().x) {
|
||||
dMax - dMin) {
|
||||
vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild1) ;
|
||||
vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else{
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x )
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetTopRight().x <= dMin ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetBottomLeft().x >= dMax )
|
||||
vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild2) ;
|
||||
else
|
||||
vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild1) ;
|
||||
@@ -1023,14 +1099,14 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
|
||||
if ( m_mTree.at( i).IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( i).GetTopRight().x - m_mTree.at( i).GetBottomLeft().x <=
|
||||
cell.GetTopRight().x - cell.GetBottomLeft().x) {
|
||||
dMax - dMin) {
|
||||
vBottomNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
vBottomNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x)
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= dMin ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= dMax)
|
||||
vBottomNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
else
|
||||
vBottomNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
@@ -1054,9 +1130,16 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
|
||||
Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs, DBLDBL ddInt) const
|
||||
{
|
||||
const Cell& cell = m_mTree.at( nId) ;
|
||||
double dMax = cell.GetTopRight().y ;
|
||||
double dMin = cell.GetBottomLeft().y ;
|
||||
if ( ddInt.second > 0) {
|
||||
dMax = ddInt.second ;
|
||||
dMin = ddInt.first ;
|
||||
}
|
||||
|
||||
// le celle restituite sono ordinate per y crescente
|
||||
if ( vLeftNeighs.empty()) {
|
||||
if ( cell.m_nLeft == -2)
|
||||
@@ -1067,14 +1150,14 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
|
||||
if ( ! m_mTree.at( cell.m_nLeft).IsSplitVert()) {
|
||||
// se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( cell.m_nLeft).GetTopRight().y - m_mTree.at( cell.m_nLeft).GetBottomLeft().y <=
|
||||
cell.GetTopRight().y - cell.GetBottomLeft().y) {
|
||||
dMax - dMin) {
|
||||
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ;
|
||||
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else{
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetTopRight().y <= dMin ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetBottomLeft().y >= dMax)
|
||||
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ;
|
||||
else
|
||||
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ;
|
||||
@@ -1105,14 +1188,14 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
|
||||
if ( ! m_mTree.at( i).IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( i).GetTopRight().y - m_mTree.at( i).GetBottomLeft().y <=
|
||||
cell.GetTopRight().y - cell.GetBottomLeft().y) {
|
||||
dMax - dMin) {
|
||||
vLeftNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
vLeftNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= dMin ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= dMax)
|
||||
vLeftNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
else
|
||||
vLeftNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
@@ -1136,9 +1219,16 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
|
||||
Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs, DBLDBL ddInt) const
|
||||
{
|
||||
const Cell& cell = m_mTree.at( nId) ;
|
||||
double dMax = cell.GetTopRight().y ;
|
||||
double dMin = cell.GetBottomLeft().y ;
|
||||
if ( ddInt.second > 0) {
|
||||
dMax = ddInt.second ;
|
||||
dMin = ddInt.first ;
|
||||
}
|
||||
|
||||
// le celle restituite sono ordinate per y crescente
|
||||
if ( vRightNeighs.empty()) {
|
||||
if ( cell.m_nRight == -2)
|
||||
@@ -1149,14 +1239,14 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
|
||||
if ( ! m_mTree.at( cell.m_nRight).IsSplitVert()) {
|
||||
// se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( cell.m_nRight).GetTopRight().y - m_mTree.at( cell.m_nRight).GetBottomLeft().y <=
|
||||
cell.GetTopRight().y - cell.GetBottomLeft().y) {
|
||||
dMax - dMin) {
|
||||
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ;
|
||||
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else{
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
|
||||
if ( m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetTopRight().y <= dMin ||
|
||||
m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetBottomLeft().y >= dMax)
|
||||
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild2) ;
|
||||
else
|
||||
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ;
|
||||
@@ -1187,14 +1277,14 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
|
||||
if ( ! m_mTree.at( i).IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree.at( i).GetTopRight().y - m_mTree.at( i).GetBottomLeft().y <=
|
||||
cell.GetTopRight().y - cell.GetBottomLeft().y) {
|
||||
dMax - dMin) {
|
||||
vRightNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
vRightNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
|
||||
if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= dMin ||
|
||||
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= dMax)
|
||||
vRightNeighs.push_back( m_mTree.at( i).m_nChild2) ;
|
||||
else
|
||||
vRightNeighs.push_back( m_mTree.at( i).m_nChild1) ;
|
||||
@@ -1316,7 +1406,7 @@ Tree::GetDepth( int nId, int nRef = -2) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vector<ICRVCOMPOPOVECTOR>& vvCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops)
|
||||
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vector<ICRVCOMPOPOVECTOR>& vvCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops, bool bUpdateEdges)
|
||||
{
|
||||
POLYLINEVECTOR vPolygonsBasic ;
|
||||
POLYLINEVECTOR vPolygonsCorrected ;
|
||||
@@ -1351,18 +1441,21 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
|
||||
if ( ! TraceLoopLabelCell( vPolygonsBasic))
|
||||
return false ;
|
||||
// scorro sulle celle e costruisco i poligoni
|
||||
int nCells = int( vPolygonsBasic.size()) ;
|
||||
for ( int i = 0 ; i < nCells ; ++ i) {
|
||||
int nPolyInd = 0 ; // indice del poligono corrispondente alla cella, nel vettore dei poligoni
|
||||
for ( int nId: m_vnLeaves) {
|
||||
// costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps
|
||||
int nId = m_vnLeaves[i] ;
|
||||
if ( m_mTree[nId].m_nFlag == 4) {
|
||||
// vettore dei poligoni ( loop) della cella nId
|
||||
vvPolygons.emplace_back() ;
|
||||
vvPolygons.back().push_back(std::move(vPolygonsCorrected[i])) ;
|
||||
vvPolygons.back().push_back(std::move(vPolygonsCorrected[nPolyInd])) ;
|
||||
vvPolygons3d.emplace_back() ;
|
||||
vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[i])) ;
|
||||
vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[nPolyInd])) ;
|
||||
}
|
||||
else if ( m_mTree[nId].m_nFlag == 0)
|
||||
else if ( m_mTree[nId].m_nFlag == 0) {
|
||||
++ nPolyInd ;
|
||||
continue ;
|
||||
}
|
||||
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
|
||||
@@ -1377,19 +1470,22 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
|
||||
while ( ! vToCheck.empty()) {
|
||||
int nPolyBefore = nPoly ;
|
||||
PolyLine pl3d ;
|
||||
CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsCorrected[i], vPolygonsBasic3d[i]) ;
|
||||
CreateCellPolygons( nId, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsCorrected[nPolyInd], vPolygonsBasic3d[nPolyInd]) ;
|
||||
if ( nPolyBefore == nPoly)
|
||||
break ;
|
||||
}
|
||||
// ora analizzo anche i loop che sono contenuti nella cella
|
||||
CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, vPolygonsCorrected[i], vPolygonsBasic3d[i]) ;
|
||||
CreateIslandAndHoles( nId, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, vPolygonsCorrected[nPolyInd], vPolygonsBasic3d[nPolyInd]) ;
|
||||
}
|
||||
++ nPolyInd ;
|
||||
}
|
||||
}
|
||||
|
||||
// aggiorno gli edge 3d e i loop della superficie
|
||||
GetEdges3D( vvCCEdges3D, vPolygonsCorrected) ;
|
||||
GetSplitLoops( vCCLoops) ;
|
||||
// se richiesto aggiorno gli edge 3d e i loop della superficie
|
||||
if ( bUpdateEdges || vvCCEdges3D.empty()) {
|
||||
GetEdges3D( vvCCEdges3D, vPolygonsBasic) ;
|
||||
GetSplitLoops( vCCLoops) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1424,6 +1520,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
int c = 0 ;
|
||||
for ( int nId : m_vnLeaves) {
|
||||
Cell& cell = m_mTree.at( nId) ;
|
||||
if ( cell.m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
|
||||
continue ;
|
||||
vVertices.clear() ;
|
||||
vVertices3d.clear() ;
|
||||
vNeigh.clear() ;
|
||||
@@ -1435,6 +1533,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
std::fill( vbBonusVert.begin(), vbBonusVert.end(), false) ;
|
||||
vnVert.push_back( int(vVertices.size()) - 1) ;
|
||||
GetBottomNeigh( nId, vNeigh) ;
|
||||
if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES)
|
||||
GetBottomNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().x, cell.GetTopRight().x)) ;
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
GetPoint( cell.GetBottomLeft().x, cell.GetBottomLeft().y, ptP00) ;
|
||||
GetPoint( cell.GetTopRight().x, cell.GetBottomLeft().y, ptP10) ;
|
||||
@@ -1469,6 +1569,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
bBottomRight = false ;
|
||||
vNeigh.clear() ;
|
||||
GetRightNeigh ( nId, vNeigh) ;
|
||||
if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES)
|
||||
GetRightNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().y, cell.GetTopRight().y)) ;
|
||||
// aggiungo i vertici che sono sul lato right, solo se ho più di un vicino right
|
||||
if ( vNeigh.size() > 1){
|
||||
// se la superficie è chiusa lungo il parametro U e le celle vicine right sono sul lato Left
|
||||
@@ -1509,6 +1611,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
vVertices3d.push_back( pt3d) ;
|
||||
vnVert.push_back( int(vVertices.size()) - 1) ;
|
||||
GetTopNeigh ( nId, vNeigh) ;
|
||||
if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::VERT_EDGES)
|
||||
GetTopNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().x, cell.GetTopRight().x)) ;
|
||||
std::reverse( vNeigh.begin(), vNeigh.end()) ;
|
||||
// aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
|
||||
if ( vNeigh.size() > 1) {
|
||||
@@ -1539,6 +1643,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
bTopLeft = false ;
|
||||
vNeigh.clear() ;
|
||||
GetLeftNeigh ( nId, vNeigh) ;
|
||||
if ( ! vNeigh.empty() && m_mTree.at(vNeigh[0]).m_nCollapsed == Cell::Collapsed::HORIZ_EDGES)
|
||||
GetLeftNeigh( vNeigh[0], vNeigh, DBLDBL( cell.GetBottomLeft().y, cell.GetTopRight().y)) ;
|
||||
std::reverse( vNeigh.begin(), vNeigh.end()) ;
|
||||
// aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left
|
||||
if ( vNeigh.size() > 1) {
|
||||
@@ -1588,6 +1694,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
// ora devo controllare se uno dei lati della cella è collassato in un punto.
|
||||
// se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra
|
||||
// se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato
|
||||
bool bAlreadyCropped = false ;
|
||||
if ( AreSamePointApprox(ptP00, ptP10)) {
|
||||
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
|
||||
if ( vbBonusVert[1] && ! vbBonusVert[3]) {// lati contati a partire da quello sopra in senso CCW
|
||||
@@ -1616,8 +1723,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
vbKeepPoint[vnVert[1]] = false ;
|
||||
cell.m_nVertToErase = 1 ; // ptBr
|
||||
}
|
||||
bAlreadyCropped = true ;
|
||||
}
|
||||
if ( AreSamePointApprox(ptP10, ptP11)) {
|
||||
if ( bAlreadyCropped)
|
||||
continue ;
|
||||
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
|
||||
if ( vbBonusVert[0] && ! vbBonusVert[2]){ // lati contati a partire da quello sopra in senso CCW
|
||||
if ( ! m_bTrimmed) {
|
||||
@@ -1641,8 +1751,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
vbKeepPoint[vnVert[2]] = false ;
|
||||
cell.m_nVertToErase = 2 ; // ptTR
|
||||
}
|
||||
bAlreadyCropped = true ;
|
||||
}
|
||||
if ( AreSamePointApprox(ptP11, ptP01)) {
|
||||
if ( bAlreadyCropped)
|
||||
continue ;
|
||||
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
|
||||
if ( vbBonusVert[1] && ! vbBonusVert[3]){ // lati contati a partire da quello sopra in senso CCW
|
||||
if ( ! m_bTrimmed) {
|
||||
@@ -1666,8 +1779,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
vbKeepPoint[vnVert[3]] = false ;
|
||||
cell.m_nVertToErase = 3 ; // ptTl
|
||||
}
|
||||
bAlreadyCropped = true ;
|
||||
}
|
||||
if ( AreSamePointApprox(ptP01, ptP00)) {
|
||||
if ( bAlreadyCropped)
|
||||
continue ;
|
||||
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
|
||||
if ( vbBonusVert[0] && ! vbBonusVert[2]) { // lati contati a partire da quello sopra in senso CCW
|
||||
if ( ! m_bTrimmed) {
|
||||
@@ -1695,6 +1811,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
vbKeepPoint[vnVert[3]] = false ;
|
||||
cell.m_nVertToErase = 3 ; // ptTl
|
||||
}
|
||||
bAlreadyCropped = true ;
|
||||
}
|
||||
|
||||
if ( ! m_bTrimmed) {
|
||||
@@ -1731,10 +1848,10 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
|
||||
int nVertCorr = int(vVerticesCorr.size());
|
||||
for ( int i = 0 ; i < (int) vVertices.size() ; ++i) {
|
||||
int dPar = i ;
|
||||
if( ! vbKeepPoint[i])
|
||||
if ( ! vbKeepPoint[i])
|
||||
dPar = -1 ;
|
||||
vPolygonsBasic.back().AddUPoint( dPar, vVertices.at( i)) ;
|
||||
if( i < nVertCorr){
|
||||
if ( i < nVertCorr){
|
||||
vPolygonsCorrected.back().AddUPoint( dPar, vVerticesCorr.at( i)) ;
|
||||
vPolygons3d.back().AddUPoint( dPar, vVertices3d.at( i)) ;
|
||||
}
|
||||
@@ -1803,10 +1920,9 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
|
||||
nCells.push_back( nId) ;
|
||||
if ( ! bRecurs) {
|
||||
// se sono in un vertice o su un lato devo controllare di aver trovato la cella giusta
|
||||
Point3d ptBr( m_mTree.at( nId).GetTopRight().x , m_mTree.at( nId).GetBottomLeft().y) ;
|
||||
Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x , m_mTree.at( nId).GetTopRight().y) ;
|
||||
if ( abs( ptToAssign.x - ptTl.x) < EPS_SMALL || abs( ptToAssign.x - ptBr.x) < EPS_SMALL ||
|
||||
abs( ptToAssign.y - ptTl.y) < EPS_SMALL || abs( ptToAssign.y - ptBr.y) < EPS_SMALL) {
|
||||
int nEdge = - 2 ;
|
||||
OnWhichEdge( nId, ptToAssign, nEdge) ;
|
||||
if ( nEdge != - 2) {
|
||||
Vector3d vtDir ;
|
||||
clTrim.GetStartDir( vtDir) ;
|
||||
// proseguo lungo la curva di trim di EPS_SMALL
|
||||
@@ -1857,12 +1973,16 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
}
|
||||
// se non ho trovato nulla vuol dire che sono su un vertice o su un lato
|
||||
if ( nCells.empty() && ! bRecurs) {
|
||||
int nEdge = -1 ;
|
||||
int nEdge = -2 ;
|
||||
for ( int nCell : vCells) {
|
||||
OnWhichEdge( nCell,ptToAssign, nEdge) ;
|
||||
if ( nEdge != -1)
|
||||
break ;
|
||||
OnWhichEdge( nCell, ptToAssign, nEdge) ;
|
||||
if ( nEdge != -2 && (m_mTree.at(nCell).m_nCollapsed == Cell::Collapsed::NO_COLLAPSE || m_mTree.at(nCell).m_nCollapsed == Cell::Collapsed::TO_VERIFY))
|
||||
nCells.push_back( nCell) ;
|
||||
nEdge = -2 ;
|
||||
}
|
||||
if( ssize( nCells) == 1)
|
||||
return nCells ;
|
||||
|
||||
Vector3d vtDir ;
|
||||
cl.GetStartDir( vtDir) ;
|
||||
Point3d ptIntersPlus = ptToAssign ;
|
||||
@@ -1870,7 +1990,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
// potrei essere su un lato
|
||||
if ( nEdge == 0 || nEdge == 1 || nEdge == 2 || nEdge == 3) {
|
||||
// se è orientato con il lato mi sposto a destra
|
||||
if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL/100 ) {
|
||||
if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL/100) {
|
||||
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -90) ;
|
||||
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
|
||||
}
|
||||
@@ -1889,10 +2009,17 @@ 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 {
|
||||
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 */ {
|
||||
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
|
||||
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
|
||||
}
|
||||
}
|
||||
//
|
||||
else
|
||||
@@ -1904,7 +2031,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
ptIntersPlus = ptToAssign + vtDirSX * EPS_SMALL ;
|
||||
}
|
||||
// rilancio la rigida ricerca
|
||||
nCells = FindCell( ptIntersPlus, cl, vCells, true) ;
|
||||
nCells = FindCell( ptIntersPlus, cl, nCells, true) ;
|
||||
}
|
||||
|
||||
return nCells ;
|
||||
@@ -1930,7 +2057,7 @@ Tree::UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt)
|
||||
}
|
||||
bAdded = true ;
|
||||
}
|
||||
if( pCC->IsValid()) {
|
||||
if ( pCC->IsValid()) {
|
||||
if ( ! bAdded)
|
||||
pCC->AddLine( pt) ;
|
||||
Vector3d vtDir = pt - ptLast ;
|
||||
@@ -2010,9 +2137,10 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
pCell->m_vInters.back().nChunk = m_mChunk[i] ;
|
||||
bool bLoopInside = true ;
|
||||
Point3d ptCurr ;
|
||||
auto iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
|
||||
int nIdPolygon = distance( m_vnLeaves.begin(), iter) ;
|
||||
if ( nIdPolygon > int( vplPolygons.size()) - 1)
|
||||
int nIdPolygon = - 1;
|
||||
if( ! pCell->m_vnPolyId.empty())
|
||||
nIdPolygon = pCell->m_vnPolyId[0] ;
|
||||
else
|
||||
return false ;
|
||||
bool bEraseNextPoint = false ;
|
||||
while ( plLoop.GetNextPoint( ptCurr)) {
|
||||
@@ -2021,6 +2149,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
plLoop.GetNextPoint( ptTEnd) ;
|
||||
CurveLine clTrim ;
|
||||
clTrim.Set( ptTStart, ptTEnd) ;
|
||||
Point3d ptLastInters = P_INVALID ;
|
||||
int nInfiniteLoopCount = 0 ;
|
||||
// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva
|
||||
while ( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) {
|
||||
// sto uscendo dalla cella, quindi cerco l'intersezione
|
||||
@@ -2046,13 +2176,23 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
return false ;
|
||||
bEraseNextPoint = true ;
|
||||
}
|
||||
// ricalcolo la posizione di nId nel vettore delle foglie
|
||||
iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
|
||||
nIdPolygon = distance( m_vnLeaves.begin(), iter) ;
|
||||
if ( nIdPolygon > int( vplPolygons.size()) - 1)
|
||||
return false ;
|
||||
// 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)) {
|
||||
++ nInfiniteLoopCount ;
|
||||
if( nInfiniteLoopCount == 4) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
ptLastInters = vptInters.back() ;
|
||||
// aggiorno il puntatore alla cella
|
||||
pCell = &m_mTree[nId] ;
|
||||
// recupero l'indice del poligono base associato alla cella
|
||||
if( ! pCell->m_vnPolyId.empty())
|
||||
nIdPolygon = pCell->m_vnPolyId[0] ;
|
||||
else
|
||||
return false ;
|
||||
// salvo il verso del loop
|
||||
pCell->m_vInters.back().bCCW = bCCW ;
|
||||
// salvo il chunk del loop
|
||||
@@ -2061,7 +2201,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
|
||||
UpdateSplitLoop( pCCLoopSplit, vptInters.back()) ;
|
||||
}
|
||||
// controllo di aggiungere un punto abbastanza distante dal precedente
|
||||
if( ! AreSamePointXYEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) {
|
||||
if ( ! AreSamePointXYEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) {
|
||||
// aggiungo la fine del segmento nel vettore delle intersezioni
|
||||
vptInters.push_back( ptCurr) ;
|
||||
// aggiorno la compo splittata
|
||||
@@ -2300,7 +2440,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
|
||||
if ( icc.GetOverlaps()) {
|
||||
for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) {
|
||||
icc.GetIntCrvCrvInfo( i, iccInfo) ;
|
||||
if( iccInfo.bOverlap){
|
||||
if ( iccInfo.bOverlap){
|
||||
ptInters = iccInfo.IciA[1].ptI ;
|
||||
break ;
|
||||
}
|
||||
@@ -2308,14 +2448,14 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
|
||||
}
|
||||
else {
|
||||
int nLastInters = icc.GetIntersCount() -1 ;
|
||||
if( nLastInters < 0)
|
||||
if ( nLastInters < 0)
|
||||
return false ;
|
||||
icc.GetIntCrvCrvInfo( nLastInters, iccInfo) ;
|
||||
ptInters = iccInfo.IciA[0].ptI ;
|
||||
}
|
||||
|
||||
// determino il lato/vertice di uscita
|
||||
if( ! OnWhichEdge( nId, ptInters, nEdge))
|
||||
if ( ! OnWhichEdge( nId, ptInters, nEdge))
|
||||
return false ;
|
||||
pCell->m_vInters.back().nOut = nEdge ;
|
||||
// se è risultato che sono abbastanza vicino( di EPS_SMALL) ad un vertice allora il punto aggiunto sarà il vertice vero e proprio
|
||||
@@ -2676,11 +2816,10 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk,
|
||||
const PolyLine& plCell, const PolyLine& plCell3d)
|
||||
Tree::CreateCellPolygons( int nId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly,
|
||||
INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d)
|
||||
{
|
||||
// conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato
|
||||
int nId = m_vnLeaves[nLeafId] ;
|
||||
// conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato
|
||||
Cell& cCell = m_mTree[nId] ;
|
||||
PNTMATRIX vEdgeVertex(4) ;
|
||||
PNTMATRIX vEdgeVertex3d(4) ;
|
||||
@@ -2688,39 +2827,37 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
|
||||
Point3d ptTR = cCell.GetTopRight() ;
|
||||
Point3d ptTl = cCell.GetTopLeft() ;
|
||||
Point3d ptBr = cCell.GetBottomRight() ;
|
||||
int nVertToErase = m_mTree.at(nId).m_nVertToErase ;
|
||||
if( nVertToErase != 2)
|
||||
int nVertToErase = cCell.m_nVertToErase ;
|
||||
if ( nVertToErase != 2)
|
||||
vEdgeVertex[0].push_back( ptTR) ;
|
||||
if( nVertToErase != 3)
|
||||
if ( nVertToErase != 3)
|
||||
vEdgeVertex[1].push_back( ptTl) ;
|
||||
if( nVertToErase != 0)
|
||||
if ( nVertToErase != 0)
|
||||
vEdgeVertex[2].push_back( ptBL) ;
|
||||
if( nVertToErase != 1)
|
||||
if ( nVertToErase != 1)
|
||||
vEdgeVertex[3].push_back( ptBr) ;
|
||||
// capisco se sono in modalità ForTriangulation
|
||||
bool bForTriangulation = plCell3d.GetPointNbr() != 0 ;
|
||||
if ( bForTriangulation) {
|
||||
if( nVertToErase != 2) {
|
||||
if ( nVertToErase != 2) {
|
||||
Point3d pt3d ; GetPoint( cCell.GetTopRight().x, cCell.GetTopRight().y, pt3d) ;
|
||||
vEdgeVertex3d[0].push_back( pt3d) ;
|
||||
}
|
||||
if( nVertToErase != 3){
|
||||
if ( nVertToErase != 3) {
|
||||
Point3d pt3d ; GetPoint( cCell.GetBottomLeft().x, cCell.GetTopRight().y, pt3d) ;
|
||||
vEdgeVertex3d[1].push_back( pt3d) ;
|
||||
}
|
||||
if( nVertToErase != 0) {
|
||||
if ( nVertToErase != 0) {
|
||||
Point3d pt3d ; GetPoint( cCell.GetBottomLeft().x, cCell.GetBottomLeft().y, pt3d) ;
|
||||
vEdgeVertex3d[2].push_back( pt3d) ;
|
||||
}
|
||||
if( nVertToErase != 1) {
|
||||
if ( nVertToErase != 1) {
|
||||
Point3d pt3d ; GetPoint( cCell.GetTopRight().x, cCell.GetBottomLeft().y, pt3d) ;
|
||||
vEdgeVertex3d[3].push_back( pt3d) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// la PolyLine è riempita a partire dal lato bottom
|
||||
// la PolyLine è riempita a partire dal lato bottom
|
||||
Point3d ptStart, pt3d ;
|
||||
plCell.GetFirstPoint( ptStart) ;
|
||||
if ( bForTriangulation)
|
||||
@@ -2735,7 +2872,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
|
||||
Point3d ptNextVert ;
|
||||
switch ( next ) {
|
||||
case 0 : ptNextVert = ptTR ; break ;
|
||||
case 1 : ptNextVert = ptTl; break ;
|
||||
case 1 : ptNextVert = ptTl ; break ;
|
||||
case 2 : ptNextVert = ptBL ; break ;
|
||||
case 3 : ptNextVert = ptBr ; break ;
|
||||
}
|
||||
@@ -2982,7 +3119,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
|
||||
if ( dArea > 0) {
|
||||
vPolygons.emplace_back() ;
|
||||
vPolygons.back().push_back(std::move(plTrimmedPoly)) ;
|
||||
if( bForTriangulation) {
|
||||
if ( bForTriangulation) {
|
||||
vPolygons3d.emplace_back() ;
|
||||
vPolygons3d.back().push_back(std::move(plTrimmedPoly3d)) ;
|
||||
}
|
||||
@@ -3011,11 +3148,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
|
||||
Tree::CreateIslandAndHoles( int nId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
|
||||
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d)
|
||||
{
|
||||
// costruisco i poligoni partendo dal vettore delle intersezioni
|
||||
int nId = m_vnLeaves[nLeafId] ;
|
||||
Cell& cCell = m_mTree[nId] ;
|
||||
//capisco se sono in modalità ForTriangulation
|
||||
|
||||
@@ -3038,7 +3174,7 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR
|
||||
nChunkBiggestCW = inA.nChunk ;
|
||||
bContained = false ;
|
||||
Inters inB = cCell.m_vInters[0] ;
|
||||
for( int c = 0 ; c < nInters ; ++ c){
|
||||
for ( int c = 0 ; c < nInters ; ++ c){
|
||||
inB = cCell.m_vInters[c] ;
|
||||
if ( inB.nIn == -1) {
|
||||
if ( inB != inA && inB.nChunk == inA.nChunk && inB.bCCW) {
|
||||
@@ -3297,12 +3433,12 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
int nVertToSkip = m_mTree.at(nId).m_nVertToErase ;
|
||||
// se è il primo punto della PolyLine lo aggiungo
|
||||
if ( plTrimmedPoly.GetPointNbr() == 0) {
|
||||
// se cerco di aggiungere il vertice che devo saltare, non faccio nulla
|
||||
if( ( nVertToSkip == 0 && AreSamePointXYApprox( ptToAdd, ptBL)) ||
|
||||
// se cerco di aggiungere il vertice che devo saltare, non faccio nulla
|
||||
if (( nVertToSkip == 0 && AreSamePointXYApprox( ptToAdd, ptBL)) ||
|
||||
( nVertToSkip == 1 && AreSamePointXYApprox( ptToAdd, ptBr)) ||
|
||||
( nVertToSkip == 2 && AreSamePointXYApprox( ptToAdd, ptTR)) ||
|
||||
( nVertToSkip == 3 && AreSamePointXYApprox( ptToAdd, ptTl))) {
|
||||
// aggiorno l'ultimo punto aggiunto
|
||||
// aggiorno l'ultimo punto aggiunto
|
||||
ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -3351,7 +3487,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
ptVert = ptToAdd ;
|
||||
if ( nVert != nVertToSkip) {
|
||||
plTrimmedPoly.AddUPoint( c, ptVert) ;
|
||||
if( bForTriangulation){
|
||||
if ( bForTriangulation){
|
||||
Point3d pt3d ; GetPoint( ptVert.x, ptVert.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3369,7 +3505,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
Point3d ptIntermed = vEdgeVertex[0][t] ;
|
||||
if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) {
|
||||
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
|
||||
if( bForTriangulation)
|
||||
if ( bForTriangulation)
|
||||
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ;
|
||||
++ c ;
|
||||
}
|
||||
@@ -3377,7 +3513,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
bool bVert = AreSamePointXYApprox( ptToAdd, ptTl) ;
|
||||
if ( ! ( nVertToSkip == 3 && bVert)) {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation){
|
||||
if ( bForTriangulation){
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3390,7 +3526,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
Point3d ptIntermed = vEdgeVertex[1][t] ;
|
||||
if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) {
|
||||
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
|
||||
if( bForTriangulation)
|
||||
if ( bForTriangulation)
|
||||
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ;
|
||||
++ c ;
|
||||
}
|
||||
@@ -3398,7 +3534,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
bool bVert = AreSamePointXYApprox( ptToAdd, ptBL) ;
|
||||
if ( ! ( nVertToSkip == 0 && bVert)) {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation) {
|
||||
if ( bForTriangulation) {
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3411,7 +3547,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
Point3d ptIntermed = vEdgeVertex[2][t] ;
|
||||
if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) {
|
||||
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
|
||||
if( bForTriangulation)
|
||||
if ( bForTriangulation)
|
||||
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ;
|
||||
++ c ;
|
||||
}
|
||||
@@ -3419,7 +3555,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
bool bVert = AreSamePointXYApprox( ptToAdd, ptBr) ;
|
||||
if ( ! ( nVertToSkip == 1 && bVert)) {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation){
|
||||
if ( bForTriangulation){
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3432,7 +3568,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
Point3d ptIntermed = vEdgeVertex[3][t] ;
|
||||
if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) {
|
||||
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
|
||||
if( bForTriangulation)
|
||||
if ( bForTriangulation)
|
||||
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ;
|
||||
++ c ;
|
||||
}
|
||||
@@ -3440,7 +3576,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
bool bVert = AreSamePointXYApprox( ptToAdd, ptTR) ;
|
||||
if ( ! ( nVertToSkip == 2 && bVert)) {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation) {
|
||||
if ( bForTriangulation) {
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3451,7 +3587,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
// aggiungo e basta
|
||||
else {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation) {
|
||||
if ( bForTriangulation) {
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3461,7 +3597,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
|
||||
// non su un edge, quindi aggiungo e basta
|
||||
else {
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
if( bForTriangulation) {
|
||||
if ( bForTriangulation) {
|
||||
Point3d pt3d ; GetPoint( ptToAdd.x, ptToAdd.y, pt3d) ;
|
||||
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
|
||||
}
|
||||
@@ -3659,14 +3795,14 @@ Tree::CategorizeCell( int nId)
|
||||
Point3d ptIntersIn = m_mTree[nNeigh].m_vInters[r].vpt[0] ;
|
||||
if ( (m_mTree[nNeigh].m_vInters[r].nOut == 0 || m_mTree[nNeigh].m_vInters[r].nOut == 7) &&
|
||||
( CheckIfBefore( 2, ptBr, ptIntersOut) || AreSamePointApprox( ptBr, ptIntersOut))) {
|
||||
if (ptIntersOut.x < ptLeftMostInters.x) {
|
||||
if (ptIntersOut.x <= ptLeftMostInters.x) {
|
||||
ptLeftMostInters = ptIntersOut ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
if ( (m_mTree[nNeigh].m_vInters[r].nIn == 0 || m_mTree[nNeigh].m_vInters[r].nIn == 7) &&
|
||||
( CheckIfBefore( 2, ptBr, ptIntersIn) || AreSamePointApprox( ptBr, ptIntersIn))) {
|
||||
if (ptIntersIn.x < ptLeftMostInters.x) {
|
||||
if (ptIntersIn.x <= ptLeftMostInters.x) {
|
||||
ptLeftMostInters = ptIntersIn ;
|
||||
bFound = false ;
|
||||
}
|
||||
@@ -3889,7 +4025,9 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
|
||||
Point3d ptTl ( ptBL.x, ptTR.y) ;
|
||||
Point3d ptBr ( ptTR.x, ptBL.y) ;
|
||||
|
||||
if ( AreSamePointXYApprox( ptToAssign, ptTR))
|
||||
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 ;
|
||||
else if ( AreSamePointXYApprox( ptToAssign, ptTl))
|
||||
nEdge = 4 ;
|
||||
@@ -3940,12 +4078,14 @@ Tree::GetEdges3D( vector<ICRVCOMPOPOVECTOR>& mCCEdges, POLYLINEVECTOR& vPolygons
|
||||
// scorro sui poligoni delle celle di un lato
|
||||
for ( int c = 0 ; c < int( vEdges[i].size()) ; ++c) {
|
||||
Cell& cNeigh = m_mTree.at(vEdges[i][c]) ;
|
||||
if ( cNeigh.m_vnPolyId.empty())
|
||||
continue ;
|
||||
PolyLine& plCell = vPolygons[cNeigh.m_vnPolyId[0]] ;
|
||||
Point3d pt ; plCell.GetFirstPoint( pt) ;
|
||||
Point3d pt3d ;
|
||||
// a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato
|
||||
if ( i == 0) {
|
||||
while ( ! AreSamePointXYApprox(pt, cNeigh.GetTopRight()) && plCell.GetNextPoint(pt) ) {
|
||||
while ( ! AreSamePointXYApprox(pt, cNeigh.GetTopRight()) && plCell.GetNextPoint(pt)) {
|
||||
continue ;
|
||||
}
|
||||
Point3d pt3d ; GetPoint( cNeigh.GetTopRight().x, cNeigh.GetTopRight().y, pt3d) ;
|
||||
@@ -4018,13 +4158,13 @@ Tree::GetEdges3D( vector<ICRVCOMPOPOVECTOR>& mCCEdges, POLYLINEVECTOR& vPolygons
|
||||
mCCEdges.emplace_back() ;
|
||||
INTVECTOR vId ;
|
||||
Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ;
|
||||
while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) {
|
||||
while ( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId)) {
|
||||
PtrOwner<ICurveComposite> pCC3D( CreateCurveComposite()) ;
|
||||
int nInd = abs( vId[0]) - 1 ;
|
||||
Point3d pt2D = m_vCEdge2D[i].first[nInd].first ;
|
||||
Point3d pt3D ; GetPoint( pt2D.x, pt2D.y, pt3D) ;
|
||||
pCC3D->AddPoint( pt3D) ;
|
||||
for ( int j = 1 ; j < int( vId.size()) ; ++j) {
|
||||
for ( int j = 1 ; j < ssize( vId) ; ++j) {
|
||||
nInd = abs( vId[j]) - 1 ;
|
||||
pt2D = m_vCEdge2D[i].first[nInd].second ;
|
||||
GetPoint( pt2D.x, pt2D.y, pt3D) ;
|
||||
@@ -4033,7 +4173,7 @@ Tree::GetEdges3D( vector<ICRVCOMPOPOVECTOR>& mCCEdges, POLYLINEVECTOR& vPolygons
|
||||
if ( ! pCC3D->IsValid())
|
||||
pCC3D->AddPoint( pt3D) ;
|
||||
// qui devo fare dei controlli prima di aggiungere questa polyline?
|
||||
mCCEdges[i].emplace_back( Release(pCC3D)) ;
|
||||
mCCEdges[i].emplace_back( Release( pCC3D)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4153,11 +4293,11 @@ Tree::AdjustCuts( void)
|
||||
bool
|
||||
Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
|
||||
{
|
||||
// questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli
|
||||
// questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli
|
||||
if ( m_mTree.size() > 1)
|
||||
return false ;
|
||||
int nRoot = -1 ;
|
||||
// preparo tutto per poter chiamare la createCellPolygon
|
||||
// preparo tutto per poter chiamare la createCellPolygon
|
||||
m_vnLeaves.push_back( nRoot) ;
|
||||
INTVECTOR vToCheck( m_mTree.at(nRoot).m_vInters.size()) ;
|
||||
iota( vToCheck.begin(), vToCheck.end(), 0) ;
|
||||
@@ -4182,7 +4322,7 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
|
||||
pl3d.Close() ;
|
||||
// ora posso creare il poligono della cella con i tagli
|
||||
POLYLINEMATRIX vPolygons3d ;
|
||||
while( ! vToCheck.empty()) {
|
||||
while ( ! vToCheck.empty()) {
|
||||
int nPolyBefore = nPoly ;
|
||||
CreateCellPolygons( 0, vPolygons, vPolygons3d, vToCheck, nPoly, vnParentChunk, pl, pl3d) ;
|
||||
// l'aggiunta di vPolygons3d forse è un problema in questo punto.
|
||||
@@ -4192,4 +4332,4 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
|
||||
break ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <utility>
|
||||
|
||||
struct PairHashInt64 {
|
||||
size_t operator()(const 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
|
||||
@@ -160,17 +160,23 @@ 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 :
|
||||
~Cell( void) {}
|
||||
Cell( void)
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ORIG),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -1), m_ptPbl( ORIG),
|
||||
m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
Cell( const Point3d& ptBL, const Point3d& ptTR)
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ptBL),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -1), m_ptPbl( ptBL),
|
||||
m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
bool IsSame( const Cell& cOtherCell) const
|
||||
{ return ( m_nId == cOtherCell.m_nId) ; }
|
||||
@@ -231,6 +237,7 @@ class Cell
|
||||
int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo
|
||||
// contati in senso CCW a partire dal bottom left
|
||||
INTVECTOR m_vnPolyId ; // indici dei poligoni associati a questa cella nel vettore m_vPolygons del Tree
|
||||
int m_nCollapsed ; // flag che indica se la coppia di lati verticali (1) o orizzontali(2) sono collassati
|
||||
|
||||
private :
|
||||
Point3d m_ptPbl ; // punto bottom left
|
||||
@@ -251,12 +258,12 @@ class Tree
|
||||
bool BuildTree( double dLinTol = LIN_TOL_STD,
|
||||
double dSideMin = 1, // è la minima lunghezza del lato di una cella
|
||||
double dSideMax = INFINITO) ; // è la massima dimensione di un triangolo della trimesh
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops, bool bUpdateEdges) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
// ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||
bool GetLeaves( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
||||
bool GetEdges3D ( vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
|
||||
bool GetEdges3D( std::vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) const // restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i)
|
||||
vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ;
|
||||
@@ -276,10 +283,10 @@ class Tree
|
||||
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
|
||||
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
|
||||
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
|
||||
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
|
||||
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
|
||||
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
|
||||
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
|
||||
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato top ( la coppia di double è per dare un intervallo diverso su cui limitare i vicini)
|
||||
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
|
||||
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato left
|
||||
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato right
|
||||
void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
|
||||
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
|
||||
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
|
||||
@@ -306,14 +313,14 @@ class Tree
|
||||
bool UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) ;
|
||||
bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre
|
||||
bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ;
|
||||
bool GetPoint(double dU, double dV, Point3d& pt) const ;
|
||||
bool SavePoint( double dU, double dV, Point3d& pt) ;
|
||||
bool GetPoint(double dU, double dV, Point3d& ptP) const ;
|
||||
bool SavePoint( double dU, double dV, const Point3d& ptP) ;
|
||||
|
||||
private :
|
||||
const SurfBezier* m_pSrfBz ; // superficie di bezier
|
||||
bool m_bTrimmed ; // superficie trimmata
|
||||
unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
vector<tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||
bool m_bBilinear ; // superficie bilineare
|
||||
bool m_bMulti ; // superficie multi-patch
|
||||
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
||||
@@ -323,10 +330,10 @@ class Tree
|
||||
int m_nDegV ; // grado della superficie nel parametro V
|
||||
int m_nSpanU ; // numero di span lungo il parametro U
|
||||
int m_nSpanV ; // numero di span lungo il parametro V
|
||||
unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
mutable unordered_map<pair<int64_t,int64_t>,Point3d,PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
|
||||
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
mutable std::unordered_map<std::pair<int64_t,int64_t>,Point3d,PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
|
||||
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
||||
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
|
||||
vector<pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
} ;
|
||||
+4573
File diff suppressed because it is too large
Load Diff
+231
-127
@@ -1,4 +1,4 @@
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2016
|
||||
//----------------------------------------------------------------------------
|
||||
// File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4
|
||||
@@ -133,6 +133,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
|
||||
m_nFracLin[0] = vzmSrc.m_nFracLin[0] ;
|
||||
m_nFracLin[1] = vzmSrc.m_nFracLin[1] ;
|
||||
m_nFracLin[2] = vzmSrc.m_nFracLin[2] ;
|
||||
m_nDexVoxRatio = vzmSrc.m_nDexVoxRatio ;
|
||||
m_nConnectedCompoCount = vzmSrc.m_nConnectedCompoCount ;
|
||||
|
||||
m_MapFrame = vzmSrc.m_MapFrame ;
|
||||
@@ -208,6 +209,10 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
{
|
||||
// tipo
|
||||
sOut += "Type=" + string( m_nMapNum == 1 ? "dexel" : "tridexel") + szNewLine ;
|
||||
// visualizzazione spigoli
|
||||
sOut += "ShowEdges=" + ToString( GetShowEdges()) + szNewLine ;
|
||||
// dexel per voxel (DexToVoxRatio)
|
||||
sOut += "DexVoxRat=" + ToString( m_nDexVoxRatio) + szNewLine ;
|
||||
// forma
|
||||
switch ( m_nShape) {
|
||||
default : sOut += "Shape=generic" ; break ;
|
||||
@@ -229,8 +234,6 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
// numero di blocchi
|
||||
sOut += "Blocks=" + ToString( m_nNumBlock) + " (" + ToString( m_nFracLin[0]) + "x" +
|
||||
ToString( m_nFracLin[1]) + "x" + ToString( m_nFracLin[2]) + ")" + szNewLine ;
|
||||
// dexel per voxel (DexToVoxRatio)
|
||||
sOut += "DexVoxRat=" + ToString( m_nDexVoxRatio) + szNewLine ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -504,11 +507,15 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
}
|
||||
// passo al punto successivo
|
||||
dX += m_dStep ;
|
||||
if ( m_nMapNum == N_MAPS)
|
||||
dX = min( dX, m_dMaxZ[1]) ;
|
||||
}
|
||||
// passo alla riga successiva
|
||||
dY += m_dStep ;
|
||||
if ( m_nMapNum == N_MAPS)
|
||||
dY = min( dY, m_dMaxZ[2]) ;
|
||||
}
|
||||
//
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -548,9 +555,13 @@ VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
}
|
||||
// passo al punto successivo
|
||||
dX += m_dStep ;
|
||||
if ( m_nMapNum == N_MAPS)
|
||||
dX = min( dX, m_dMaxZ[1]) ;
|
||||
}
|
||||
// passo alla riga successiva
|
||||
dY += m_dStep ;
|
||||
if ( m_nMapNum == N_MAPS)
|
||||
dY = min( dY, m_dMaxZ[2]) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -563,10 +574,10 @@ VolZmap::GetPartLocalBBox( int nPart, BBox3d& b3Loc, int nFlag) const
|
||||
// Verifico lo stato.
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
|
||||
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
|
||||
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
|
||||
return false ;
|
||||
// Se la componente richiesta non esiste, vi è un errore.
|
||||
// Se la componente richiesta non esiste, vi è un errore.
|
||||
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
|
||||
return false ;
|
||||
// Calcolo Bounding-box
|
||||
@@ -614,10 +625,10 @@ VolZmap::GetPartBBox( int nPart, const Frame3d& frRef, BBox3d& b3Ref, int nFlag)
|
||||
// Verifico lo stato.
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
|
||||
// Se una sola mappa o il numero di componenti è indefinito, vi è un errore.
|
||||
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
|
||||
return false ;
|
||||
// Se la componente richiesta non esiste, vi è un errore.
|
||||
// Se la componente richiesta non esiste, vi è un errore.
|
||||
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
|
||||
return false ;
|
||||
// Calcolo Bounding-box
|
||||
@@ -689,7 +700,7 @@ VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dell'asse di rotazione
|
||||
// verifico validità dell'asse di rotazione
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -722,7 +733,7 @@ VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del piano di specchiatura
|
||||
// verifico validità del piano di specchiatura
|
||||
if ( vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -736,7 +747,7 @@ VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei parametri
|
||||
// verifico validità dei parametri
|
||||
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -750,11 +761,11 @@ VolZmap::ToGlob( const Frame3d& frRef)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
@@ -773,11 +784,11 @@ VolZmap::ToLoc( const Frame3d& frRef)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
@@ -796,11 +807,11 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei frame
|
||||
// verifico validità dei frame
|
||||
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
|
||||
@@ -816,10 +827,10 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
int
|
||||
VolZmap::GetPartCount( void) const
|
||||
{
|
||||
// Se mono-dexel la connessione è incalcolabile.
|
||||
// Se mono-dexel la connessione è incalcolabile.
|
||||
if ( m_nMapNum == 1)
|
||||
return - 1 ;
|
||||
// Se il numero delle componenti è indefinito
|
||||
// Se il numero delle componenti è indefinito
|
||||
// lo ricalcolo e restituisco il risultato.
|
||||
if ( m_nConnectedCompoCount == - 1) {
|
||||
const_cast<VolZmap*>(this)->CheckMapConnection() ;
|
||||
@@ -870,7 +881,7 @@ VolZmap::CheckMapConnection( void)
|
||||
IntervalsToProcessStackVec.resize( nThreadMax) ;
|
||||
// Mi espando dal primo intervallo mettendo gli intervalli che intersecano nei vari thread
|
||||
FirstExpansionFromZ( nThreadMax, NewInt, IntervalsToProcessStackVec) ;
|
||||
// Lancio in parallelo più ricerche
|
||||
// Lancio in parallelo più ricerche
|
||||
int nActiveThread = 0 ;
|
||||
vector<future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
@@ -891,7 +902,7 @@ VolZmap::CheckMapConnection( void)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se l'intervallo non attraversa un nodo o ha già
|
||||
// Se l'intervallo non attraversa un nodo o ha già
|
||||
// un indice assegnato salto questa iterazione.
|
||||
else
|
||||
continue ;
|
||||
@@ -935,7 +946,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont)
|
||||
double dZmin = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMin ;
|
||||
double dZmax = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dZmin - 2 * EPS_SMALL < dZ &&
|
||||
dZmax + 2 * EPS_SMALL > dZ &&
|
||||
@@ -955,7 +966,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont)
|
||||
double dYmin = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMin ;
|
||||
double dYmax = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dYmin - 2 * EPS_SMALL < dY &&
|
||||
dYmax + 2 * EPS_SMALL > dY &&
|
||||
@@ -1006,7 +1017,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont)
|
||||
double dZmin = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMin ;
|
||||
double dZmax = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dZmin - 2 * EPS_SMALL < dZ &&
|
||||
dZmax + 2 * EPS_SMALL > dZ &&
|
||||
@@ -1026,7 +1037,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont)
|
||||
double dXmin = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMin ;
|
||||
double dXmax = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dXmin - 2 * EPS_SMALL < dX &&
|
||||
dXmax + 2 * EPS_SMALL > dX &&
|
||||
@@ -1077,7 +1088,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont)
|
||||
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
|
||||
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dXmin - 2 * EPS_SMALL < dX &&
|
||||
dXmax + 2 * EPS_SMALL > dX &&
|
||||
@@ -1097,7 +1108,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont)
|
||||
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
|
||||
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dYmin - 2 * EPS_SMALL < dY &&
|
||||
dYmax + 2 * EPS_SMALL > dY &&
|
||||
@@ -1146,7 +1157,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine
|
||||
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
|
||||
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dXmin - 2 * EPS_SMALL < dX &&
|
||||
dXmax + 2 * EPS_SMALL > dX &&
|
||||
@@ -1167,7 +1178,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine
|
||||
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
|
||||
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
|
||||
// Se i segmenti si incrociano e il nuovo trovato non
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// ha già un indice assegnato, assegno l'indice e
|
||||
// aggiungo l'intervallo trovato allo stack.
|
||||
if ( dYmin - 2 * EPS_SMALL < dY &&
|
||||
dYmax + 2 * EPS_SMALL > dY &&
|
||||
@@ -1214,13 +1225,13 @@ VolZmap::ClonePart( int nPart) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
// Se è definita una sola griglia non sono definibili le parti, errore
|
||||
// Se è definita una sola griglia non sono definibili le parti, errore
|
||||
if ( m_nMapNum == 1)
|
||||
return nullptr ;
|
||||
// Se è richiesta una componente fuori intervallo, errore
|
||||
// Se è richiesta una componente fuori intervallo, errore
|
||||
if ( nPart < 0 || nPart >= m_nConnectedCompoCount)
|
||||
return nullptr ;
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo.
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo.
|
||||
if ( m_nConnectedCompoCount == - 1)
|
||||
const_cast<VolZmap*>(this)->CheckMapConnection() ;
|
||||
// Se non vi sono componenti, errore
|
||||
@@ -1291,7 +1302,7 @@ VolZmap::ClonePart( int nPart) const
|
||||
pVolume->m_Values[nMap].resize( pVolume->m_nDim[nMap]) ;
|
||||
}
|
||||
|
||||
// Se almeno una griglia è nulla, non ha senso Zmap
|
||||
// Se almeno una griglia è nulla, non ha senso Zmap
|
||||
if ( pVolume->m_nDim[0] == 0 ||
|
||||
pVolume->m_nDim[1] == 0 ||
|
||||
pVolume->m_nDim[2] == 0)
|
||||
@@ -1343,8 +1354,8 @@ VolZmap::ClonePart( int nPart) const
|
||||
dNewOy = nMinIndJ[0] * m_dStep ;
|
||||
dNewOz = nMinIndJ[1] * m_dStep ;
|
||||
|
||||
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
|
||||
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
|
||||
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
|
||||
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
|
||||
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
|
||||
// Quote estreme Z
|
||||
switch ( nMap) {
|
||||
@@ -1407,10 +1418,10 @@ VolZmap::RemovePart( int nPart)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// Se è definita una sola griglia non sono definibili le parti, errore
|
||||
// Se è definita una sola griglia non sono definibili le parti, errore
|
||||
if ( m_nMapNum == 1)
|
||||
return false ;
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo
|
||||
if ( m_nConnectedCompoCount == - 1)
|
||||
CheckMapConnection() ;
|
||||
// Se non vi sono componenti, abbiamo finito
|
||||
@@ -1452,7 +1463,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
|
||||
// Verifico lo stato e che siano definibili le componenti connesse
|
||||
if ( m_nStatus != OK || m_nMapNum == 1)
|
||||
return - 1 ;
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo
|
||||
// Se il numero di componenti è indefinito, lo ricalcolo
|
||||
if ( m_nConnectedCompoCount == -1)
|
||||
const_cast<VolZmap*>( this)->CheckMapConnection() ;
|
||||
// Se non vi sono componenti, abbiamo finito
|
||||
@@ -1485,7 +1496,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
|
||||
swap( ptEn.y, ptEn.z) ;
|
||||
swap( ptEn.x, ptEn.z) ;
|
||||
}
|
||||
// Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima
|
||||
// Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima
|
||||
// e la corrispondente componente connessa di minima distanza con la distanza e la componente connessa correnti.
|
||||
double dDist ;
|
||||
DistPointLine DistCalc( ptPL, ptSt, ptEn) ;
|
||||
@@ -1677,107 +1688,197 @@ VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::MakeUniform( double dToler)
|
||||
VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
{
|
||||
// controllo validità dello Zmap
|
||||
// Controllo validità dello Zmap
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
// la tolleranza deve essere minore dello step
|
||||
dToler = min( dToler, 0.95 * m_dStep) ;
|
||||
|
||||
// creo lo Zmpa che andrà a sostituire il corrente
|
||||
PtrOwner<VolZmap> pOldVolZmap( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pOldVolZmap))
|
||||
// creo lo ZMap per i riferimenti degli intervalli sulle griglie
|
||||
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
|
||||
return false ;
|
||||
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
|
||||
// salvo lo Zmap prima di modificare gli spilloni
|
||||
PtrOwner<VolZmap> pVolZMapCurrGrid( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pVolZMapCurrGrid))
|
||||
// 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],
|
||||
m_dStep, IsTriDexel()))
|
||||
return false ;
|
||||
// ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
|
||||
// se il dexel corrente non ha sotto-intervalli passo al successivo
|
||||
if ( int( m_Values[nGrid][nDex].size()) == 0)
|
||||
|
||||
// Dovendo effettuare estensioni, allargo gli ingobri nelle direzioni principali
|
||||
m_dMinZ[0] -= dToler ;
|
||||
m_dMinZ[1] -= dToler ;
|
||||
m_dMinZ[2] -= dToler ;
|
||||
m_dMaxZ[0] += dToler ;
|
||||
m_dMaxZ[1] += dToler ;
|
||||
m_dMaxZ[2] += dToler ;
|
||||
|
||||
// NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente
|
||||
// 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) {
|
||||
// Se il dexel corrente non ha sotto-intervalli passo al successivo
|
||||
if ( pZMapCopy->m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// indici del dexel
|
||||
// Indici del dexel
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// salvo le informazioni dei sotto-intervalli del dexel corrente
|
||||
vector<Data> vInfo ;
|
||||
for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr)
|
||||
vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ;
|
||||
// per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza
|
||||
int nSub_intervals = int( vInfo.size()) ;
|
||||
// scorro gli intervalli
|
||||
for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
// estremo inferiore
|
||||
if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) {
|
||||
AddIntervals( nGrid, nI, nJ,
|
||||
vInfo[nInfo].dMin - dToler,
|
||||
vInfo[nInfo].dMin + dToler,
|
||||
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin,
|
||||
true) ;
|
||||
// se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due
|
||||
// direzioni nel voxel corrispondente
|
||||
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
|
||||
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
|
||||
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
|
||||
// l'intervallo corrente si è unito con il precedente...
|
||||
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler,
|
||||
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN,
|
||||
vInfo[nInfo].nToolMin) ;
|
||||
// Recupero il numero di intervalli presenti nel Dexel corrente
|
||||
int nIntervals = int( pZMapCopy->m_Values[nGrid][nDex].size()) ;
|
||||
// Scorro gli intervalli presenti
|
||||
for ( int nInfo = 0 ; nInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
// Recupero l'intervallo corrente
|
||||
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
|
||||
// --- Se richiesta prima estensione
|
||||
if ( bIsExtensionFirst) {
|
||||
// *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ]
|
||||
// Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy)
|
||||
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())) {
|
||||
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente)
|
||||
// ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
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())) {
|
||||
// Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo)
|
||||
// ( lascio invariato lo ZMapCopy)
|
||||
nIntervals = int( m_Values[nGrid][nDex].size()) ;
|
||||
pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ,
|
||||
Interval.dMax,
|
||||
pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, dToler, true,
|
||||
nToolNum, V_INVALID, V_INVALID) ;
|
||||
}
|
||||
}
|
||||
// estremo superiore
|
||||
if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) {
|
||||
AddIntervals( nGrid, nI, nJ,
|
||||
vInfo[nInfo].dMax - dToler,
|
||||
vInfo[nInfo].dMax + dToler,
|
||||
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax,
|
||||
true) ;
|
||||
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
|
||||
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
|
||||
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
|
||||
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler,
|
||||
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN,
|
||||
vInfo[nInfo].nToolMax) ;
|
||||
// --- 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) ;
|
||||
}
|
||||
// *** 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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza
|
||||
// ( NB. avendo aggiunto intervalli, il dexel può modificare la sua struttura interna )
|
||||
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
// ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra,
|
||||
// altrimenti rimuovo parti in eccesso )
|
||||
if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) {
|
||||
if ( nInfo != 0 ||
|
||||
pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid])
|
||||
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
|
||||
if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 ||
|
||||
pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid])
|
||||
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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) {
|
||||
// --- Se richiesta prima estensione
|
||||
if ( bIsExtensionFirst) {
|
||||
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
|
||||
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
|
||||
}
|
||||
// --- Se richiesta prima restrizione
|
||||
else {
|
||||
m_Values[nGrid][nDex][nInfo].dMin -= dToler ;
|
||||
m_Values[nGrid][nDex][nInfo].dMax += dToler ;
|
||||
}
|
||||
// Definisco il colore
|
||||
for ( int nOrigInfo = 0 ; nOrigInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nOrigInfo) {
|
||||
if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMin - m_Values[nGrid][nDex][nInfo].dMin < EPS_SMALL)
|
||||
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)
|
||||
m_Values[nGrid][nDex][nInfo].nToolMax = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMax ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gestisco le parti Extra ricavate
|
||||
// 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) {
|
||||
// Se l'intervallo è vuoto, non faccio nulla
|
||||
if ( pZMapExtra->m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Indici del dexel
|
||||
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) {
|
||||
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) ;
|
||||
}
|
||||
// --- Se richiesta prima restrizione
|
||||
else {
|
||||
// ... sottraggo i contributi
|
||||
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restringo gli ingombri espensi in precedenza
|
||||
m_dMinZ[0] += dToler ;
|
||||
m_dMinZ[1] += dToler ;
|
||||
m_dMinZ[2] += dToler ;
|
||||
m_dMaxZ[0] -= dToler ;
|
||||
m_dMaxZ[1] -= dToler ;
|
||||
m_dMaxZ[2] -= dToler ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
{
|
||||
// Controllo sulla validità della griglia
|
||||
// Controllo sulla validità della griglia
|
||||
if ( nGrid < 0 || nGrid > 2)
|
||||
return false ;
|
||||
// Controllo sulla validità del dexel
|
||||
// Controllo sulla validità del dexel
|
||||
if ( nDex <= - 1 || nDex >= int( m_Values[nGrid].size()))
|
||||
return false ;
|
||||
// Controllo sulla validità dell'intervallo
|
||||
// Controllo sulla validità dell'intervallo
|
||||
if ( nInt <= - 1 || nInt >= int( m_Values[nGrid][nDex].size()))
|
||||
return false ;
|
||||
|
||||
@@ -1929,8 +2030,6 @@ VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
bool
|
||||
VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ)
|
||||
{
|
||||
if ( ! m_bIsBox)
|
||||
return true ;
|
||||
dMinZ = m_dMaxZ[nMap] ;
|
||||
dMaxZ = m_dMinZ[nMap] ;
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
@@ -1959,7 +2058,8 @@ VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, do
|
||||
bool
|
||||
VolZmap::IsBox( void)
|
||||
{
|
||||
// Se non tridexel, non posso stabilire con il metodo seguente se è un box
|
||||
// Se non tridexel, non posso stabilire con il metodo seguente se è un box
|
||||
// Verifico solo che gli spilloni di una mappa o sono nulli o hanno gli stessi estremi
|
||||
if ( m_nMapNum == 1)
|
||||
return false ;
|
||||
// Numero massimo di thread per il calcolo parallelo.
|
||||
@@ -1968,13 +2068,16 @@ VolZmap::IsBox( void)
|
||||
if ( nThreadMax == 1) {
|
||||
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
|
||||
double dMinZ, dMaxZ ;
|
||||
if ( ! IsMapPartABox( nMap, 0, m_nNx[nMap], 0, m_nNy[nMap], dMinZ, dMaxZ))
|
||||
if ( ! IsMapPartABox( nMap, 0, m_nNx[nMap], 0, m_nNy[nMap], dMinZ, dMaxZ)) {
|
||||
m_bIsBox = false ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
m_bIsBox = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Caso di più thread
|
||||
// Caso di più thread
|
||||
m_bIsBox = true ;
|
||||
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
|
||||
vector< future<bool>> vRes ;
|
||||
@@ -2019,15 +2122,16 @@ VolZmap::IsBox( void)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero.
|
||||
// Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero.
|
||||
if ( ! m_bIsBox)
|
||||
return false ;
|
||||
// Controllo che gli estremi Z siano uguali.
|
||||
for ( int nT = 1 ; nT < nThreadMax ; ++ nT) {
|
||||
if ( abs( vMinZ[nT] - vMinZ[0]) > EPS_SMALL)
|
||||
return false ;
|
||||
if ( abs( vMaxZ[nT] - vMaxZ[0]) > EPS_SMALL)
|
||||
if ( abs( vMinZ[nT] - vMinZ[0]) > EPS_SMALL ||
|
||||
abs( vMaxZ[nT] - vMaxZ[0]) > EPS_SMALL) {
|
||||
m_bIsBox = false ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2055,7 +2159,7 @@ VolZmap::Cut( const Plane3d& plPlane)
|
||||
}
|
||||
// Ciclo sui dexel della mappa
|
||||
for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) {
|
||||
// Se spillone già vuoto, passo al successivo
|
||||
// Se spillone già vuoto, passo al successivo
|
||||
if ( m_Values[nMap][nD].empty())
|
||||
continue ;
|
||||
// Indici di spillone
|
||||
@@ -2071,20 +2175,20 @@ VolZmap::Cut( const Plane3d& plPlane)
|
||||
double dEnDist = DistPointPlane( ptEn, plMyPlane) ;
|
||||
// Se entrambi sotto il piano
|
||||
if ( dStDist < EPS_SMALL && dEnDist < EPS_SMALL)
|
||||
// Non devo fare alcunché
|
||||
// Non devo fare alcunché
|
||||
;
|
||||
// se altrimenti entrambi gli estremi sono oltre il piano
|
||||
else if ( dStDist > -EPS_SMALL && dEnDist > -EPS_SMALL) {
|
||||
// Si elimina tutto
|
||||
SubtractIntervals( nMap, nI, nJ, dMin, dMax, V_NULL, V_NULL, 1) ;
|
||||
}
|
||||
// se altrimenti è da tenere il punto iniziale
|
||||
// se altrimenti è da tenere il punto iniziale
|
||||
else if ( dStDist < 0) {
|
||||
// Si elimina la parte tra intersezione e punto finale
|
||||
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
|
||||
SubtractIntervals( nMap, nI, nJ, dInt, dMax, plMyPlane.GetVersN(), V_NULL, 1) ;
|
||||
}
|
||||
// se altrimenti è da tenere il punto finale
|
||||
// se altrimenti è da tenere il punto finale
|
||||
else if (dEnDist < 0) {
|
||||
// Si elimina la parte tra punto iniziale e intersezione
|
||||
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
|
||||
@@ -2174,7 +2278,7 @@ VolZmap::Compact( void)
|
||||
}
|
||||
}
|
||||
|
||||
// Se non vi è materiale
|
||||
// Se non vi è materiale
|
||||
if ( ! bNotEmptyGrid) {
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nNumBlock = 0 ;
|
||||
@@ -2196,8 +2300,8 @@ VolZmap::Compact( void)
|
||||
double dNewOy = nMinJ[0] * m_dStep ;
|
||||
double dNewOz = nMinJ[1] * m_dStep ;
|
||||
|
||||
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
|
||||
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
|
||||
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali,
|
||||
// infatti i sistemi di riferimento in gioco differiscono al più per una traslazione.
|
||||
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
|
||||
// Quote estreme Z
|
||||
switch ( nMap) {
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include <atomic>
|
||||
|
||||
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
|
||||
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
|
||||
|
||||
// ------------------------- FORWARD -------------------------------------------------------------
|
||||
class IntersParLinesSurfTm ;
|
||||
|
||||
@@ -81,9 +84,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
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 CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
@@ -97,7 +98,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{ return m_nDexVoxRatio ; }
|
||||
bool ChangeResolution( int nDexVoxRatio) override ;
|
||||
void SetShowEdges( bool bShow) override
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
m_OGrMgr.Clear() ; }
|
||||
bool GetShowEdges( void) const override
|
||||
{ return m_bShowEdges ; }
|
||||
@@ -149,7 +150,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler) override ;
|
||||
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ;
|
||||
bool Offset( double dOffs, int nType) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -170,6 +172,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
return *this ; }
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
|
||||
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) ;
|
||||
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) ;
|
||||
|
||||
private :
|
||||
enum CubeType { VOX_EXTERN = 1,
|
||||
@@ -255,17 +259,21 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool AddIntervals( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler,
|
||||
Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ;
|
||||
bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
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 ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
// Spostamenti utensile
|
||||
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
|
||||
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) ;
|
||||
bool SelectGeneralMotion( int nGrid, const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtLs, const Vector3d& vtLe, int n5AxisType) ;
|
||||
bool SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) ;
|
||||
bool InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) ;
|
||||
bool InitializeAuxPoints( Point3d ptTop1s[3], Point3d ptTop1e[3], Point3d ptTop2s[3], Point3d ptTop2e[3],
|
||||
Point3d ptBottom1s[3], Point3d ptBottom1e[3], Point3d ptBottom2s[3], Point3d ptBottom2e[3]) ;
|
||||
// SOTTRAZIONI
|
||||
// UTENSILI
|
||||
// Asse di simmetria parallelo a Z
|
||||
@@ -293,11 +301,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
// lavorazioni a 5 assi
|
||||
bool GenTool_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
bool Cyl_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, double dHeightCorr = 0, int n5AxisType = ACROSS) ;
|
||||
bool CylBall_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
bool Conus_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
|
||||
// COMPONENTI
|
||||
// Asse di simmetria diretto come l'asse Z
|
||||
@@ -316,7 +329,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realt� MillingPerp
|
||||
// Asse di simmetria con orientazione generica
|
||||
bool CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
|
||||
double dHei, double dRad, bool bTapB, bool bTapT, int nToolNum) ;
|
||||
@@ -332,7 +345,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
// lavorazioni a 5 assi
|
||||
bool Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
||||
double dHeight, double dMaxRad, double dMinRad, int nToolNum, int n5AxisType) ;
|
||||
bool CompCyl_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
||||
double dHeight, double dRadius, int nToolNum, int n5AxisType) ;
|
||||
bool CompConus_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDirS, const Vector3d& vtToolDirE, double dHei, double dMaxRad, double dMinRad,
|
||||
bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum, int n5AxisType) ;
|
||||
|
||||
// Generica traslazione sfera
|
||||
bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ;
|
||||
// Additivi
|
||||
@@ -346,7 +367,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// BBox per utensili e solidi semplici con movimenti di traslazione
|
||||
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, const Vector3d& vtV2,
|
||||
double dRad, double dTipRad, double dHei,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
|
||||
@@ -440,30 +461,54 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di superfici
|
||||
bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool UpdateVolZMapBySurfThickeningSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle, int nTool = 0) ;
|
||||
bool CreateOrientedOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs) ;
|
||||
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
int nToolMin, int nToolMax, bool bSkipSwap = false) ;
|
||||
bool CutByPlaneForOffset( const Plane3d& plCut) ;
|
||||
bool AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool) ;
|
||||
bool AddMapPartForOffset( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, int nTool, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di Zmap
|
||||
bool OffsetFillet( double dOffs) ;
|
||||
bool OffsetSharped( double dOffs, int nType) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2, OFFSET = 3} ;
|
||||
enum Move5Axis {
|
||||
ALONG_CONVEX = 0 ,
|
||||
ALONG_CONCAVE = 1 ,
|
||||
ACROSS = 2 ,
|
||||
NO_BASE_INTERS = 3} ;
|
||||
enum Status {
|
||||
ERR = 0,
|
||||
OK = 1,
|
||||
TO_VERIFY = 2} ;
|
||||
enum Shape {
|
||||
GENERIC = 0,
|
||||
BOX = 1,
|
||||
EXTRUSION = 2,
|
||||
OFFSET = 3} ;
|
||||
static const int N_MAPS = 3 ;
|
||||
static const int N_VOXBLOCK = 32 ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
|
||||
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
|
||||
@@ -497,8 +542,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable BOOLVECTOR m_BlockToUpdate ;
|
||||
mutable INTVECTOR m_BlockUpdatingCounter ;
|
||||
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto
|
||||
// Se >= 0 è il numero di componenti connesse
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto
|
||||
// Se >= 0 è il numero di componenti connesse
|
||||
|
||||
mutable std::vector<VoxelContainer> m_InterBlockVox ;
|
||||
mutable SharpTriaMatrix m_InterBlockOriginalSharpTria ;
|
||||
@@ -511,9 +556,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable std::vector<InterVoxMatter> m_SliceXY ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceXZ ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceYZ ;
|
||||
mutable std::mutex m_SliceMutex ;
|
||||
mutable std::atomic_flag m_SliceFlag ;
|
||||
|
||||
std::atomic<bool> m_bIsBox ;
|
||||
bool m_bIsBox ;
|
||||
|
||||
int m_nCurrTool ;
|
||||
std::vector<Tool> m_vTool ;
|
||||
@@ -521,6 +566,12 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
double m_dToolAngTolDeg ;
|
||||
} ;
|
||||
|
||||
// Offset
|
||||
enum {
|
||||
VOLZMAP_OFFS_FILLET = 0,
|
||||
VOLZMAP_OFFS_CHANFER = 1,
|
||||
VOLZMAP_OFFS_EXTENDED = 2
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VolZmap* CreateBasicVolZmap( void)
|
||||
|
||||
+24
-22
@@ -2294,7 +2294,7 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if( nBasInt == 1) {
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cono verso l'interno
|
||||
@@ -3080,17 +3080,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
return false ;
|
||||
// Se c'è intersezione valuto tutti i voxel interni
|
||||
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
|
||||
// Ciclo sui voxel del blocco.
|
||||
// Triangoli smooth
|
||||
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
|
||||
// ciclo sui voxel del blocco.
|
||||
for ( int nV = 0 ; nV < ssize( m_BlockSmoothTria[nB]) ; ++ nV) {
|
||||
// Box del voxel
|
||||
BBox3d b3Vox ;
|
||||
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
|
||||
continue ;
|
||||
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
|
||||
// ciclo sui triangoli del voxel
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockSmoothTria[nB][nV].vTria) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
@@ -3102,18 +3103,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// Triangoli sharp interni al blocco
|
||||
for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) {
|
||||
// ciclo sui voxel del blocco.
|
||||
for ( int nV = 0 ; nV < ssize( m_BlockSharpTria[nB]) ; ++ nV) {
|
||||
// Box del voxel
|
||||
BBox3d b3Vox ;
|
||||
GetVoxelBox( m_BlockSharpTria[nB][nV].i, m_BlockSharpTria[nB][nV].j, m_BlockSharpTria[nB][nV].k, b3Vox) ;
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
// Ciclo sulle componenti connesse
|
||||
for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
for ( int nC = 0 ; nC < ssize( m_BlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
|
||||
if (nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
// Costruisco il tratto di curva
|
||||
CurveLine cvLine ;
|
||||
if ( cvLine.Set(ptSt, ptEn))
|
||||
@@ -3123,10 +3124,10 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// Triangoli grandi del blocco
|
||||
for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockBigTria[nB][nT] ;
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockBigTria[nB]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockBigTria[nB][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
// Costruisco il tratto di curva
|
||||
CurveLine cvLine ;
|
||||
@@ -3136,11 +3137,11 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// In ogni caso valuto i triangoli sharp fra blocchi
|
||||
for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) {
|
||||
for ( int nV = 0 ; nV < ssize( m_InterBlockSharpTria[nB]) ; ++ nV) {
|
||||
// Ciclo sulle componenti connesse
|
||||
for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
for ( int nC = 0 ; nC < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
@@ -3156,9 +3157,9 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
|
||||
// Creo i loop
|
||||
ChainCurves LoopCreator ;
|
||||
LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ;
|
||||
LoopCreator.Init( false, EPS_SMALL, ssize( vLine)) ;
|
||||
// Carico le curve per concatenarle
|
||||
for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) {
|
||||
for ( int nCv = 0 ; nCv < ssize( vLine) ; ++ nCv) {
|
||||
Point3d ptSt = vLine[nCv].GetStart() ;
|
||||
Point3d ptEn = vLine[nCv].GetEnd() ;
|
||||
Vector3d vtDir; vLine[nCv].GetStartDir(vtDir) ;
|
||||
@@ -3176,6 +3177,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
if ( ! pLoop->AddCurve( vLine[i - 1], true, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
}
|
||||
pLoop->TestClosure( 10 * EPS_SMALL) ;
|
||||
pLoop->SetExtrusion( plPlane.GetVersN()) ;
|
||||
pLoop->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
||||
// Inserisco la curva composita nella raccolta da ritornare
|
||||
|
||||
+62
-47
@@ -505,6 +505,8 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
nSupJ < 0 || nSupJ > m_nNy[nMap])
|
||||
return false ;
|
||||
|
||||
double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ;
|
||||
|
||||
// Determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
@@ -552,7 +554,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
|
||||
// entro nella superficie trimesh
|
||||
if ( dCos < - EPS_SMALL) {
|
||||
if ( dCos < - dCosSmall) {
|
||||
|
||||
ptIn = IntersectionResults[k].ptI ;
|
||||
|
||||
@@ -565,7 +567,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
}
|
||||
|
||||
// esco dalla superficie trimesh
|
||||
else if ( dCos > EPS_SMALL && bInside) {
|
||||
else if ( dCos > dCosSmall && bInside) {
|
||||
|
||||
Point3d ptOut = IntersectionResults[k].ptI ;
|
||||
|
||||
@@ -804,7 +806,9 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
// quindi espandiamo il bounding box per ovviare al problema.
|
||||
if ( dExtraBox > EPS_ZERO)
|
||||
SurfBBox.Expand( dExtraBox) ;
|
||||
|
||||
else
|
||||
dExtraBox = 0 ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
|
||||
@@ -870,58 +874,69 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
// Oggetto per calcolo massivo intersezioni
|
||||
IntersParLinesSurfTm intPLSTM( frMapFrame, Surf) ;
|
||||
|
||||
// Numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// Async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
// Standarda è multithread
|
||||
constexpr bool MULTITHREAD = true ;
|
||||
if ( MULTITHREAD) {
|
||||
|
||||
// Numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// Async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
||||
else {
|
||||
CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Assegno il minimo e massimo valore di Z della mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
m_dMaxZ[0] = vtLen.z ;
|
||||
m_dMinZ[1] = 0 ;
|
||||
m_dMaxZ[1] = ( bTriDex ? vtLen.x : 0) ;
|
||||
m_dMinZ[2] = 0 ;
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
|
||||
m_dMinZ[0] = dExtraBox ;
|
||||
m_dMaxZ[0] = vtLen.z - dExtraBox ;
|
||||
m_dMinZ[1] = ( bTriDex ? dExtraBox : 0) ;
|
||||
m_dMaxZ[1] = ( bTriDex ? vtLen.x - dExtraBox : 0) ;
|
||||
m_dMinZ[2] = ( bTriDex ? dExtraBox : 0) ;
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y - dExtraBox : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = ( dExtraBox > EPS_ZERO && IsBox() ? BOX : GENERIC) ;
|
||||
// Con espansione non va considerato box (calcolo trimesh va in crash)
|
||||
m_nShape = ( dExtraBox <= EPS_ZERO && IsBox() ? BOX : GENERIC) ;
|
||||
|
||||
// Aggiornamento dello stato
|
||||
m_nStatus = OK ;
|
||||
|
||||
+57
-28
@@ -24,6 +24,7 @@
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Core"
|
||||
#include "/EgtDev/Extern/Eigen/SVD"
|
||||
#include <thread>
|
||||
@@ -950,25 +951,41 @@ VolZmap::UpdateTripleMapGraphics( void) const
|
||||
}
|
||||
}
|
||||
|
||||
// Calcolo i triangoli sui blocchi
|
||||
int nBlockUpdated = 0 ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( m_nNumBlock) ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
++ nBlockUpdated ;
|
||||
vRes[i] = async( launch::async, &VolZmap::ExtMarchingCubes, this, i, ref( vVoxContainerVec[i])) ;
|
||||
// Standard è multithread
|
||||
constexpr bool MULTITHREAD = true ;
|
||||
if ( MULTITHREAD) {
|
||||
|
||||
// Calcolo i triangoli sui blocchi
|
||||
int nBlockUpdated = 0 ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( m_nNumBlock) ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
++ nBlockUpdated ;
|
||||
vRes[i] = async( launch::async, &VolZmap::ExtMarchingCubes, this, i, ref( vVoxContainerVec[i])) ;
|
||||
}
|
||||
}
|
||||
bool bOk = true ;
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nBlockUpdated) {
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
if ( m_BlockToUpdate[i] && vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nTerminated ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOk = true ;
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nBlockUpdated) {
|
||||
else {
|
||||
// Calcolo i triangoli sui blocchi
|
||||
bool bOk = true ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
if ( m_BlockToUpdate[i] && vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nTerminated ;
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
bOk = ExtMarchingCubes( i, vVoxContainerVec[i]) && bOk ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1254,13 +1271,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceYZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 2) {
|
||||
@@ -1270,13 +1289,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 3) {
|
||||
@@ -1286,13 +1307,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXY[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1357,27 +1380,33 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceYZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 2) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 3) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXY.emplace(nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2352
-114
File diff suppressed because it is too large
Load Diff
+1832
-448
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Extern/vroni/Include/vroni_object.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
@@ -19,17 +19,17 @@
|
||||
#include "/EgtDev/Include/EGkCurveBezier.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include "/EgtDev/Extern/vroni/Include/vroni_object.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static const bool USE_VORONOI = true ;
|
||||
static const int VORONOI_STD_BOUND = 3 ;
|
||||
static const double VRONI_OFFS_TOL = 1e-9 ;
|
||||
static const double VRONI_JUNCTION_OPEN = 1.0 ;
|
||||
static const double VRONI_JUNCTION_CLOSED = 2.0 ;
|
||||
static constexpr bool USE_VORONOI = true ;
|
||||
static constexpr int VORONOI_STD_BOUND = 3 ;
|
||||
static constexpr double VRONI_OFFS_TOL = 1e-9 ;
|
||||
static constexpr double VRONI_JUNCTION_OPEN = 1.0 ;
|
||||
static constexpr double VRONI_JUNCTION_CLOSED = 2.0 ;
|
||||
|
||||
//-------------------------- Forward Definitions -------------------------------
|
||||
class ISurfFlatRegion ;
|
||||
class vroniObject ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class Voronoi
|
||||
|
||||
Reference in New Issue
Block a user