EgtGeomKernel :

- passaggio da mutex a shared_mutex nelle Bezier.
This commit is contained in:
Daniele Bariletti
2025-04-02 12:52:55 +02:00
parent 8f13d8d198
commit 5fc04c2791
2 changed files with 548 additions and 546 deletions
+175 -174
View File
@@ -33,6 +33,7 @@
#include <atomic>
#include <execution>
#include <future>
#include <shared_mutex>
using namespace std ;
@@ -41,7 +42,7 @@ atomic<int> CellCounter( 0) ;
//----------------------------------------------------------------------------
Tree::Tree( void)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
m_bSplitPatches( true), m_bTestMode( false)
{
Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
Cell cRoot( ptBl, ptTr) ;
@@ -56,7 +57,7 @@ Tree::~Tree( void)
//----------------------------------------------------------------------------
Tree::Tree( const Point3d ptBl, const Point3d ptTr)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
m_bSplitPatches( true), m_bTestMode( false)
{
Cell cRoot( ptBl, ptTr) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
@@ -106,7 +107,7 @@ Tree::AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation)
return true ;
}
mutex map3DMutex ;
shared_mutex map3DMutex ;
//----------------------------------------------------------------------------
bool
@@ -116,19 +117,19 @@ Tree::GetPoint( double dU, double dV, Point3d& pt) const
bool bOk = true ;
bool bCalculated = false ;
{
lock_guard<mutex> lock( map3DMutex) ;
shared_lock<shared_mutex> lock( map3DMutex) ;
bCalculated = m_mPt3d.find( key) != m_mPt3d.end() ;
}
if ( ! bCalculated) {
bOk = bOk && m_pSrfBz->GetPoint( dU / SBZ_TREG_COEFF, dV / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt) ;
{
lock_guard<mutex> lock( map3DMutex) ;
unique_lock<shared_mutex> lock( map3DMutex) ;
m_mPt3d[key] = pt ;
}
}
{
lock_guard<mutex> lock( map3DMutex) ;
pt = m_mPt3d[key] ;
shared_lock<shared_mutex> lock( map3DMutex) ;
pt = m_mPt3d.at( key) ;
}
return bOk ;
}
@@ -140,11 +141,11 @@ Tree::SavePoint( double dU, double dV, Point3d& pt)
pair<int64_t, int64_t> key (static_cast<int64_t>(dU * pow(2,15)), static_cast<int64_t>(dV * pow(2,15))) ;
bool bCalculated = true ;
{
lock_guard<mutex> lock( map3DMutex) ;
shared_lock<shared_mutex> lock( map3DMutex) ;
bCalculated = m_mPt3d.find( key) != m_mPt3d.end() ;
}
if ( ! bCalculated){
lock_guard<mutex> lock( map3DMutex) ;
unique_lock<shared_mutex> lock( map3DMutex) ;
m_mPt3d[key] = pt ;
}
return true ;
@@ -156,7 +157,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
{
if ( pSrfBz == nullptr || ! pSrfBz->IsValid())
return false ;
// pulisco i vettori membri
// pulisco i vettori membri
m_mTree.clear() ;
m_vnLeaves.clear() ;
m_vnParents.clear() ;
@@ -168,7 +169,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_pSrfBz = pSrfBz ;
m_bSplitPatches = bSplitPatches ;
// le coordinate delle celle sono nello spazio parametrico
// le coordinate delle celle sono nello spazio parametrico
int nDegU, nDegV, nSpanU, nSpanV ;
bool bIsRat, bTrimmed ;
m_pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bIsRat, bTrimmed) ;
@@ -181,7 +182,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_bBilinear = true ;
if ( nSpanU * nSpanV != 1)
m_bMulti = true ;
// creo la cella Root
// creo la cella Root
Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ;
bool bLimited = false ;
if ( ! AreSamePointXYExact( ptMax,ORIG)) {
@@ -191,27 +192,27 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
}
Cell cRoot( ptMin, ptTop) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
// recupero i loop di trim e li divido per chunk
// recupero i loop di trim e li divido per chunk
if ( m_bTrimmed) {
int nLoop = 0 ;
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
double dAngTolDeg = 5 ;
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) {
// i chunk della falt region sono ancora flat region composte da 1 chunk
// i chunk della falt region sono ancora flat region composte da 1 chunk
// rimuovo i difetti dei loop prima di salvarli
PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ;
pLoop->MergeCurves( dLinTol, dAngTolDeg) ;
pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ;
// approssimo i loop di trim con delle spezzate
// approssimo i loop di trim con delle spezzate
PolyLine plApprox ;
int nType = 0 ;
pLoop->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ;
// calcolo se il loop è CCW o CW
// calcolo se il loop è CCW o CW
double dArea ;
Plane3d plExtPlane ;
bool bCCW ;
@@ -229,13 +230,13 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
nLoop = int ( m_vPlApprox.size()) ;
for ( int k = 0 ; k < int( vPlAdjusted.size()) ; ++k )
m_vPlApprox.push_back( tuple<PolyLine,bool>(vPlAdjusted[k], vbOrientation[k])) ;
// aggiorno la mappa del chunk di appartenenza per tutti i loop aggiunti // do per scontato che siano tutti dello stesso chunk anche se li ho separati
// aggiorno la mappa del chunk di appartenenza per tutti i loop aggiunti // do per scontato che siano tutti dello stesso chunk anche se li ho separati
for ( int k = nLoop ; k < int( m_vPlApprox.size()); ++k)
m_mChunk[k] = i ;
}
}
}
// salvo i vertici 3d della cella root
// salvo i vertici 3d della cella root
Point3d ptP00, ptP10, ptP11, ptP01 ;
bool bOk = false ;
if ( ! bLimited) {
@@ -254,7 +255,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
GetPoint( ptMax.x, ptMax.y, ptP11) ;
GetPoint( ptMin.x, ptMax.y, ptP01) ;
}
// se richiesto divido preliminarmente le patches
// se richiesto divido preliminarmente le patches
m_vnParents.clear() ;
bool bIsPlanar = m_pSrfBz->IsPlanar() ;
if( ! bIsPlanar || m_bMulti) {
@@ -307,13 +308,13 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
}
vLeaves.clear() ;
}
// controllo se la superficie è chiusa.
// se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa
// e sistemo le adiacenze
// controllo se la superficie è chiusa.
// se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa
// e sistemo le adiacenze
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) ||
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11))) {
////questo in teoria non serve più perché lo faccio appena sopra
if( int( m_mTree.size()) == 1) {
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
@@ -326,13 +327,13 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
}
////////
// qui devo fare il controllo capped ( chiusura a semisfera)
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
// qui devo fare il controllo capped ( chiusura a semisfera)
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bPole0 = true, bPole1 = true ;
Point3d ptU0, ptU1 ;
// controllo se tutti i punti di controllo sull'isoparametrica sono uguali
// controllo se tutti i punti di controllo sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ;
@@ -348,9 +349,9 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
Split( 1, m_mTree) ;
}
}
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) {
//// questo in teoria non serve più perché lo faccio sopra
if ( m_mTree.size() == 1) {
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) {
@@ -383,7 +384,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_mTree[1].SetSplitDirVert( false) ;
Split( 1, m_mTree) ;
}
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
if ( int( m_mTree.size() == 3) && ! m_mTree.at(-1).IsSplitVert()) {
m_mTree[0].m_nLeft = -1 ;
m_mTree[0].m_nRight = -1 ;
@@ -401,8 +402,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
INTVECTOR vLeaves ;
GetHeightLeaves( -1, vLeaves) ;
m_vnParents = vLeaves ;
// calcolo e salvo la lunghezza reale delle curve di bezier di bordo
// calcolo e salvo la lunghezza reale delle curve di bezier di bordo
PtrOwner<CurveComposite> pCrvV0( m_pSrfBz->GetCurveOnU( 0)) ;
PtrOwner<CurveComposite> pCrvV1( m_pSrfBz->GetCurveOnU( double(nSpanV))) ;
PtrOwner<CurveComposite> pCrvU0( m_pSrfBz->GetCurveOnV( 0)) ;
@@ -449,15 +450,15 @@ AddOrMergeBBox( const BBox3d& bBox3dA, vector<BBox3d>& vBBox, bool bAdd = true,
for ( int b = 0 ; b < (int)vBBox.size() ; ++b) {
BBox3d bBox3dB = vBBox[b] ;
BBox3d b3Int ;
// se sono celle diverse e ho un'intersezione faccio il merge
// se sono celle diverse e ho un'intersezione faccio il merge
if ( ! ( AreSamePointXYExact( ptMin, bBox3dB.GetMin()) && AreSamePointXYExact( ptMax, bBox3dB.GetMax())) &&
bBox3dA.FindIntersectionXY( bBox3dB, b3Int)) {
bBox3dA.FindIntersectionXY( bBox3dB, b3Int)) {
vBBox[b].Add( bBox3dA) ;
if ( ! bAdd ) {
vBBox.erase( vBBox.begin() + nInd) ;
-- b ;
}
// se ho fatto un merge devo controllare se ora la nuova bbox ha delle intersezioni
// se ho fatto un merge devo controllare se ora la nuova bbox ha delle intersezioni
AddOrMergeBBox( vBBox[b], vBBox, false, b) ;
bAdded = true ;
break ;
@@ -476,21 +477,21 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees)
vTrees.emplace_back( ORIG, ORIG) ;
}
else {
// se ho dei loop di trim trovo le loro BBox3d per costruire l'albero solo all'interno di queste BBox
// se ho dei loop di trim trovo le loro BBox3d per costruire l'albero solo all'interno di queste BBox
BOXVECTOR vBBox ;
for ( int i = 0 ; i < int( m_vPlApprox.size()) ; ++ i) {
PolyLine& plLoop = get<0>( m_vPlApprox[i]) ;
// calcolo la BBox3d
// calcolo la BBox3d
Point3d ptP ;
plLoop.GetFirstPoint( ptP) ;
BBox3d bBox3dA( ptP) ;
while ( plLoop.GetNextPoint( ptP))
bBox3dA.Add( ptP) ;
// controllo se ho intersezioni con altre bbox
// se ho intersezioni unisco le bbox, altrimenti le lascio indipendenti
// controllo se ho intersezioni con altre bbox
// se ho intersezioni unisco le bbox, altrimenti le lascio indipendenti
AddOrMergeBBox( bBox3dA, vBBox) ;
}
// controllo se dopo aver unito le bbox ho ottenuto Root
// controllo se dopo aver unito le bbox ho ottenuto Root
bool bIsRoot = false ;
Point3d ptTR( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF) ;
for ( int i = 0 ; i < int( vBBox.size()) ; ++ i) {
@@ -500,7 +501,7 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees)
break ;
}
}
// restituisco le celle parent di partenza a partire dalle bbox che ho ottenuto
// restituisco le celle parent di partenza a partire dalle bbox che ho ottenuto
if ( ! bIsRoot) {
for ( int i = 0 ; i < int( vBBox.size()) ; ++ i) {
Point3d ptMin = vBBox[i].GetMin() ;
@@ -519,12 +520,12 @@ bool
Tree::Split( int nId, double dSplitValue, unordered_map<int, Cell>& mBranch)
{
Cell& cToSplit = mBranch.at(nId) ;
// controllo che lo split non venga fatto sul lato della cella
// 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!!!!!!!!!!!!!!!!!!!
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!!!!!!!!!!!!!!!!!!!
cToSplit.m_dSplit = dSplitValue ;
Cell cChild1, cChild2 ;
cChild1.m_nDepth = cToSplit.m_nDepth + 1 ;
@@ -701,7 +702,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
condition_variable cv ;
vector<unordered_map<int, Cell>> vBranches( nStartingLeaves) ;
INTVECTOR vFirstCells ;
// creo la coda dei task
queue<function<void()>> qTasks ;
bool done = false ;
@@ -714,7 +715,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
qTasks.emplace([this, i, &vBranches, dLinTol, dSideMin, dSideMax, nFirst]
{Tree::BuildBranch( nFirst, vBranches[i], dLinTol, dSideMin, dSideMax) ;} ) ;
}
// Create worker threads
vector<thread> workers ;
for (int i = 0 ; i < nThreadMax ; ++i)
@@ -757,7 +758,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
[&](auto& map) {
size_t index = &map - &vBranches[0]; // Get the index of the current map
vectorBranches[index].assign( make_move_iterator(map.begin()),
make_move_iterator(map.end()));
make_move_iterator(map.end()));
}) ;
// Step 2: Precompute total size and allocate final vector
@@ -819,7 +820,7 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
GetPoint(pcToSplit->GetTopRight().x, pcToSplit->GetTopRight().y, ptP11) ;
GetPoint(pcToSplit->GetBottomLeft().x, pcToSplit->GetTopRight().y, ptP01) ;
if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU || Dist(ptP00, ptP11) < dSideMin * 2
|| Dist(ptP10, ptP01) < dSideMin * 2) {
|| Dist(ptP10, ptP01) < dSideMin * 2) {
double dU = ( pcToSplit->GetTopRight().x + pcToSplit->GetBottomLeft().x) / 2 ;
double dV = ( pcToSplit->GetTopRight().y + pcToSplit->GetBottomLeft().y) / 2 ;
double dULoc = 0.5, dVLoc = 0.5 ;
@@ -977,7 +978,7 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
}
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
// se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
bool bSplit = false ;
// dSideMinVal potrebbe essere zero se entrambi i lati che dovrei splittare sono collassati in un punto, ma questo non vuol
@@ -1003,7 +1004,7 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
double dU = double ( u) / double ( nStepsU - 1) ;
double dULoc = ( ( 1 - dU) * pcToSplit->GetBottomLeft().x + dU * pcToSplit->GetTopRight().x) ;
if ( ! GetPoint( dULoc, pcToSplit->GetBottomLeft().y, ptBz0) ||
! GetPoint( dULoc, pcToSplit->GetTopRight().y, ptBz1))
! GetPoint( dULoc, pcToSplit->GetTopRight().y, ptBz1))
return false ;
// verifico che la cella non sia uno spicchio in verticale, cioè con ptP00 == ptP01 && ptP10 == ptP11
// ( vedi disegno sotto per uno spicchio verticale)
@@ -1032,15 +1033,15 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
double dDist ;
dpc.GetDist( dDist) ;
// se la cella è uno spicchio, quindi con due lati collassati, devo calcolare in modo diverso dist
// ptP00 == ptP01
// / \
// / \
// ptP00 == ptP01
// / \
// / \
// / \
// ( )
// \ /
// \ /
// \ /
// ptP10 == ptP11
// \ /
// \ /
// \ /
// ptP10 == ptP11
if ( ! clV.IsValid() && AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
DistPointCurve dpcSlice( ptBzV, cl0010) ;
dpcSlice.GetDist( dDist) ;
@@ -1078,9 +1079,9 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
pcToSplit->SetProcessed() ;
// risalgo i parent finché non trovo il primo Child2 da processare
nCToSplit = pcToSplit->m_nParent ;
pcToSplit = &mBranch[nCToSplit] ;
if ( nCToSplit == nBranchRoot)
return true ;
pcToSplit = &mBranch.at(nCToSplit) ;
if ( mBranch[pcToSplit->m_nChild1].IsProcessed() && mBranch[pcToSplit->m_nChild2].IsProcessed())
pcToSplit->SetProcessed() ;
while ( mBranch[pcToSplit->m_nChild2].IsProcessed()) {
@@ -1093,7 +1094,7 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
if ( mBranch[pcToSplit->m_nChild1].IsProcessed() && mBranch[pcToSplit->m_nChild2].IsProcessed())
pcToSplit->SetProcessed() ;
if ( nCToSplit == -1 && mBranch[pcToSplit->m_nChild2].IsProcessed())
break ;
break ;
}
nCToSplit = pcToSplit->m_nChild2 ;
pcToSplit = &mBranch[nCToSplit] ;
@@ -1121,7 +1122,7 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
double dLen1 = Dist( ptP10, ptP11) ;
double dLen2 = Dist( ptP01, ptP11) ;
double dLen3 = Dist( ptP00, ptP01) ;
bool bVert = false ;
///per capire in quale direzione splittare devo guardare quale coppia di lati opposti è più sghemba
Vector3d vtU0 = ptP01 - ptP00 ;
@@ -1140,12 +1141,12 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
bVert = false ;
else
bVert = true ;
// verifico che la cella sia abbastanza grande da poter essere splittata
// verifico che la cella sia abbastanza grande da poter essere splittata
double dSideMinVal = ( bVert ? max( dLen0, dLen2) : max( dLen1, dLen3)) ;
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
double dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
double dErr = 0 ;
if ( m_bMulti) {
Point3d ptPSrf ;
@@ -1190,9 +1191,9 @@ Tree::BuildBranch( int nFirstCell, unordered_map<int, Cell>& mBranch, double dLi
pcToSplit->SetProcessed() ;
// risalgo i parent finché non trovo il primo Child2 da processare
nCToSplit = pcToSplit->m_nParent ;
pcToSplit = &mBranch[nCToSplit] ;
if ( nCToSplit == nBranchRoot)
return true ;
pcToSplit = &mBranch[nCToSplit] ;
if ( mBranch[pcToSplit->m_nChild1].IsProcessed() && mBranch[pcToSplit->m_nChild2].IsProcessed())
pcToSplit->SetProcessed() ;
while ( mBranch[pcToSplit->m_nChild2].IsProcessed()) {
@@ -1246,16 +1247,16 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
vTopNeighs.push_back( cell.m_nTop) ;
else {
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
// 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) {
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à
// 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 )
m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x )
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ;
else
vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild1) ;
@@ -1271,7 +1272,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
bAllLeaves = false ;
}
if ( ! bAllLeaves)
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
GetTopNeigh( nId, vTopNeighs) ;
}
else {
@@ -1280,17 +1281,17 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
if ( m_mTree.at( i).IsLeaf())
continue ;
else {
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
vTopNeighs.erase( remove( vTopNeighs.begin(),vTopNeighs.end(),i)) ;
-- j ;
if ( m_mTree.at( i).IsSplitVert()) {
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
// 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) {
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à
// 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 )
@@ -1329,13 +1330,13 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
vBottomNeighs.push_back( cell.m_nBottom) ;
else {
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
// 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) {
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à
// 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 )
@@ -1354,7 +1355,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
bAllLeaves = false ;
}
if ( ! bAllLeaves)
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
GetBottomNeigh( nId, vBottomNeighs) ;
}
else {
@@ -1363,17 +1364,17 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
if ( m_mTree.at( i).IsLeaf())
continue ;
else {
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
vBottomNeighs.erase( remove( vBottomNeighs.begin(),vBottomNeighs.end(),i)) ;
-- j ;
if ( m_mTree.at( i).IsSplitVert()) {
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
// 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) {
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à
// 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)
@@ -1410,25 +1411,25 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
if ( m_mTree.at( cell.m_nLeft).IsLeaf())
vLeftNeighs.push_back( cell.m_nLeft) ;
else {
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) {
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)
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ;
else
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ;
}
}
else {
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) {
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)
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ;
else
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ;
}
}
else {
vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ;
}
}
bool bAllLeaves = true ;
for ( int i : vLeftNeighs) {
@@ -1436,7 +1437,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
bAllLeaves = false ;
}
if ( ! bAllLeaves)
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
GetLeftNeigh( nId, vLeftNeighs) ;
}
else {
@@ -1445,20 +1446,20 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
if ( m_mTree.at( i).IsLeaf())
continue ;
else {
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
vLeftNeighs.erase( remove( vLeftNeighs.begin(),vLeftNeighs.end(),i)) ;
-- j ;
if ( ! m_mTree.at( i).IsSplitVert()) {
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
// 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) {
cell.GetTopRight().y - cell.GetBottomLeft().y) {
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à
// 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)
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
vLeftNeighs.push_back( m_mTree.at( i).m_nChild2) ;
else
vLeftNeighs.push_back( m_mTree.at( i).m_nChild1) ;
@@ -1493,16 +1494,16 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
vRightNeighs.push_back( cell.m_nRight) ;
else {
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
// 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) {
cell.GetTopRight().y - cell.GetBottomLeft().y) {
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à
// 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)
m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild2) ;
else
vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ;
@@ -1518,7 +1519,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
bAllLeaves = false ;
}
if ( ! bAllLeaves)
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
GetRightNeigh( nId, vRightNeighs) ;
}
else {
@@ -1527,20 +1528,20 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
if ( m_mTree.at( i).IsLeaf())
continue ;
else {
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
vRightNeighs.erase( remove( vRightNeighs.begin(),vRightNeighs.end(), i)) ;
-- j ;
if ( ! m_mTree.at( i).IsSplitVert()) {
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
// 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) {
cell.GetTopRight().y - cell.GetBottomLeft().y) {
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à
// 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)
m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y)
vRightNeighs.push_back( m_mTree.at( i).m_nChild2) ;
else
vRightNeighs.push_back( m_mTree.at( i).m_nChild1) ;
@@ -1622,7 +1623,7 @@ Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const
vnLeaves.push_back( m_mTree.at( nId).m_nChild1) ;
vnLeaves.push_back( m_mTree.at( nId).m_nChild2) ;
if ( ! m_mTree.at( m_mTree.at( nId).m_nChild1).IsLeaf() || ! m_mTree.at( m_mTree.at( nId).m_nChild2).IsLeaf())
// almeno un child non è leaf quindi devo richiamare ricorsivamente questa funzione sui child in questione
// almeno un child non è leaf quindi devo richiamare ricorsivamente questa funzione sui child in questione
d = GetHeightLeaves( nId, vnLeaves, m_mTree.at( m_mTree.at( nId).m_nChild1).m_nDepth) ;
}
}
@@ -1633,7 +1634,7 @@ Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const
continue ;
}
else {
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
vnLeaves.erase( remove( vnLeaves.begin(),vnLeaves.end(),i)) ;
-- j ;
vnLeaves.push_back( m_mTree.at( i).m_nChild1) ;
@@ -1669,7 +1670,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
POLYLINEVECTOR vPolygonsBasic3d ;
if ( ! m_bTrimmed) {
vvPolygons.clear() ;
GetPolygonsBasic( vPolygonsBasic, vPolygonsCorrected, vPolygonsBasic3d) ;
if (vPolygonsBasic.empty())
return false ;
@@ -2106,11 +2107,11 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
// verifico che il punto sia all'interno dello spazio parametrico
// allargo i bordi in modo da tenere anche i punti sul bordo dello spazio parametrico
if ( ptToAssign.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptToAssign.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL||
ptToAssign.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssign.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) {
ptToAssign.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssign.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) {
//nCells.push_back( - 2) ;
return nCells ;
}
// se ho diviso preliminarmente le patches e in uno dei due parametri ho un numero dispari di patches devo individuare a mano la cella parent
// in cui individuare la foglia giusta
if ( (m_bSplitPatches && ( m_nSpanU > 1 || m_nSpanV > 1)) || m_bTestMode) {
@@ -2151,7 +2152,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
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)
abs( ptToAssign.y - ptTl.y) < EPS_SMALL || abs( ptToAssign.y - ptBr.y) < EPS_SMALL)
{
Vector3d vtDir ;
clTrim.GetStartDir( vtDir) ;
@@ -2445,8 +2446,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
else if ( nId == nFirstCell) {
int nOut = pCell->m_vInters[nPass].nOut ;
pCell->m_vInters.back().vpt.insert( pCell->m_vInters.back().vpt.end(),
pCell->m_vInters[nPass].vpt.begin(),
pCell->m_vInters[nPass].vpt.end()) ;
pCell->m_vInters[nPass].vpt.begin(),
pCell->m_vInters[nPass].vpt.end()) ;
pCell->m_vInters[nPass] = pCell->m_vInters.back() ;
pCell->m_vInters.pop_back() ;
// sistemo il lato d'uscita
@@ -2502,7 +2503,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
m_mTree[nCell].m_nFlag2 = 1 ;
CategorizeCell( nCell) ;
}
if ( ! m_mTree[nCell].IsProcessed()) {
// guardo i vicini a destra per passare alla prossima cella
vNeigh.clear() ;
@@ -3015,7 +3016,7 @@ 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)
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] ;
@@ -3093,7 +3094,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
plCell3d.GetNextPoint( pt3d) ;
}
}
// comincio a costruire il poligono
INTVECTOR vToCheckNow = vToCheck ;
// costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps
@@ -3142,37 +3143,37 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
if ( (nEdge == 0 || nEdge == 7) && nEdge == nEdgeLast) {
vEdge.Set( 1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 0 ;
bNotEquiverseOverlap = true ;
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 0 ;
bNotEquiverseOverlap = true ;
}
}
else if ( ( nEdge == 1 || nEdge == 4 ) && nEdge == nEdgeLast) {
vEdge.Set( 0,-1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 1 ;
bNotEquiverseOverlap = true ;
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 1 ;
bNotEquiverseOverlap = true ;
}
}
else if ( ( nEdge == 2 || nEdge == 5) && nEdge == nEdgeLast) {
vEdge.Set( -1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 2 ;
bNotEquiverseOverlap = true ;
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 2 ;
bNotEquiverseOverlap = true ;
}
}
else if ( ( nEdge == 3 || nEdge == 6) && nEdge == nEdgeLast) {
vEdge.Set( 0,1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 3 ;
bNotEquiverseOverlap = true ;
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 3 ;
bNotEquiverseOverlap = true ;
}
}
@@ -3251,7 +3252,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ;
for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) {
if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], cCell.m_vInters[vToCheckNow[nNext]].vpt[0]) &&
CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) {
CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) {
plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ;
++ c ;
@@ -3350,7 +3351,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
//----------------------------------------------------------------------------
bool
Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d)
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d)
{
// costruisco i poligoni partendo dal vettore delle intersezioni
int nId = m_vnLeaves[nLeafId] ;
@@ -3565,8 +3566,8 @@ Tree::CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d&
bool
Tree::CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2) const
{
// i punti devono essere sullo stesso lato nEdge
// nEdge2 è di backup, in caso nEdge sia un vertice, per capire di quale lato si tratta
// i punti devono essere sullo stesso lato nEdge
// nEdge2 è di backup, in caso nEdge sia un vertice, per capire di quale lato si tratta
int nEdgeRef = -1 ;
if ( nEdge != nEdge2 && nEdge2 != -1) {
if ( min( nEdge, nEdge2) < 4)
@@ -3582,8 +3583,8 @@ Tree::CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nE
}
else
nEdgeRef = nEdge ;
// sul lato nEdge controllo se ptP1 viene prima di ptP2.
// i lati vengono percorsi in senso antiorario
// sul lato nEdge controllo se ptP1 viene prima di ptP2.
// i lati vengono percorsi in senso antiorario
if ( AreSameEdge( nEdgeRef, 0)) {
return ( ptP1.x > ptP2.x) ;
}
@@ -3626,20 +3627,20 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const
//----------------------------------------------------------------------------
bool
Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c,
const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation, Point3d& ptLast) const
const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation, Point3d& ptLast) const
{
Point3d ptBr = m_mTree.at(nId).GetBottomRight() ;
Point3d ptTR = m_mTree.at(nId).GetTopRight() ;
Point3d ptTl = m_mTree.at(nId).GetTopLeft() ;
Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ;
int nVertToSkip = m_mTree.at(nId).m_nVertToErase ;
// se è il primo punto della PolyLine lo aggiungo
// 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)) ||
( nVertToSkip == 1 && AreSamePointXYApprox( ptToAdd, ptBr)) ||
( nVertToSkip == 2 && AreSamePointXYApprox( ptToAdd, ptTR)) ||
( nVertToSkip == 3 && AreSamePointXYApprox( ptToAdd, ptTl))) {
( nVertToSkip == 1 && AreSamePointXYApprox( ptToAdd, ptBr)) ||
( nVertToSkip == 2 && AreSamePointXYApprox( ptToAdd, ptTR)) ||
( nVertToSkip == 3 && AreSamePointXYApprox( ptToAdd, ptTl))) {
// aggiorno l'ultimo punto aggiunto
ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ;
return true ;
@@ -3657,13 +3658,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
return true ;
}
// verifico di essere allineato con un lato, sennò aggiungo e basta
// verifico di essere allineato con un lato, sennò aggiungo e basta
Vector3d vDir ;
if ( ! AreSamePointXYApprox( ptToAdd, ptLast))
vDir = ptToAdd - ptLast ;
else
return false ;
// se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice
// se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice
if ( ! vDir.Normalize()) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
@@ -3700,8 +3701,8 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
return true ;
}
if ( abs( vDir.x) > 1 - EPS_SMALL || abs( vDir.y) > 1 - EPS_SMALL) {
// se su un edge devo fare dei controlli
// edge 0
// se su un edge devo fare dei controlli
// edge 0
if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptTR.y && abs( vDir.x) > 1 - EPS_SMALL) {
for ( int t = nVertToSkip == 2 ? 0 : 1 ; t < (int)vEdgeVertex[0].size() ; ++ t) {
Point3d ptIntermed = vEdgeVertex[0][t] ;
@@ -3722,7 +3723,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
++ c ;
}
}
// edge 1
// edge 1
else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptBL.x && abs( vDir.y) > 1 - EPS_SMALL) {
for ( int t = nVertToSkip == 3 ? 0 : 1 ; t < (int)vEdgeVertex[1].size() ; ++ t) {
Point3d ptIntermed = vEdgeVertex[1][t] ;
@@ -3743,7 +3744,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
++ c ;
}
}
// edge 2
// edge 2
else if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptBL.y && abs( vDir.x) > 1 - EPS_SMALL) {
for ( int t = nVertToSkip == 0 ? 0 : 1 ; t < (int)vEdgeVertex[2].size() ; ++ t) {
Point3d ptIntermed = vEdgeVertex[2][t] ;
@@ -3764,7 +3765,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
++ c ;
}
}
// edge 3
// edge 3
else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptTR.x && abs( vDir.y) > 1 - EPS_SMALL) {
for ( int t = nVertToSkip == 1 ? 0 : 1 ; t < (int)vEdgeVertex[3].size() ; ++ t) {
Point3d ptIntermed = vEdgeVertex[3][t] ;
@@ -3785,8 +3786,8 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
++ c ;
}
}
// sono allineato con un lato, ma NON sono su un lato
// aggiungo e basta
// sono allineato con un lato, ma NON sono su un lato
// aggiungo e basta
else {
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
if( bForTriangulation) {
@@ -3796,7 +3797,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
++ c ;
}
}
// non su un edge, quindi aggiungo e basta
// non su un edge, quindi aggiungo e basta
else {
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
if( bForTriangulation) {
@@ -3816,15 +3817,15 @@ bool
Tree::SetRightEdgeIn( int nId)
{
Cell& cCell = m_mTree[nId] ;
// categorizzo la cella in base a quanta parte del lato destro è contenuta all'interno delle curve di trim
// RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto
// categorizzo la cella in base a quanta parte del lato destro è contenuta all'interno delle curve di trim
// RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto
int nPass = (int) cCell.m_vInters.size() ;
if ( nPass == 0) {
cCell.m_nRightEdgeIn = -1 ;
return true ;
}
bool bDone = false ;
// se ho solo loop interni devo controllare se il più esterno è CCW ( lato destro esterno) o CW ( lato destro interno)
// se ho solo loop interni devo controllare se il più esterno è CCW ( lato destro esterno) o CW ( lato destro interno)
if ( cCell.m_nFlag == 2) {
bool bAllContained = true ;
bool bContained = false ;
@@ -3893,9 +3894,9 @@ Tree::SetRightEdgeIn( int nId)
if ( cCell.m_vInters[k].nIn != -1) {
// trovo il loop che ha l'ingresso o l'uscita più a destra
if ( CheckIfBefore( cCell.m_vInters[k].nIn, cCell.m_vInters[k].vpt[0], nEdgeUp, ptUp) ||
CheckIfBefore( cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back(), nEdgeUp, ptUp) ||
CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nIn, cCell.m_vInters[k].vpt[0]) ||
CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back())) {
CheckIfBefore( cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back(), nEdgeUp, ptUp) ||
CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nIn, cCell.m_vInters[k].vpt[0]) ||
CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back())) {
nLoop = k ;
if ( CheckIfBefore( cCell.m_vInters[k])) {
ptUp = cCell.m_vInters[k].vpt[0] ;
@@ -3996,14 +3997,14 @@ Tree::CategorizeCell( int nId)
Point3d ptIntersOut = m_mTree[nNeigh].m_vInters[r].vpt.back() ;
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))) {
( CheckIfBefore( 2, ptBr, ptIntersOut) || AreSamePointApprox( ptBr, ptIntersOut))) {
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))) {
( CheckIfBefore( 2, ptBr, ptIntersIn) || AreSamePointApprox( ptBr, ptIntersIn))) {
if (ptIntersIn.x < ptLeftMostInters.x) {
ptLeftMostInters = ptIntersIn ;
bFound = false ;
@@ -4050,7 +4051,7 @@ Tree::CategorizeCell( int nId)
}
}
}
// se non ho vicini bottom devo per forza guardare il vicino a sinistra
// se non ho vicini bottom devo per forza guardare il vicino a sinistra
else {
Point3d ptInters = m_mTree[vNeigh[0]].GetTopRight() ;
int nEdge = 3 ;
@@ -4214,7 +4215,7 @@ Tree::GetLeaves( vector<Cell>& vLeaves) const
Cell cToAdd = m_mTree.at( k) ;
vLeaves.push_back( cToAdd) ;
}
return true ;
}
@@ -4270,7 +4271,7 @@ Tree::GetEdges3D( vector<ICRVCOMPOPOVECTOR>& mCCEdges, POLYLINEVECTOR& vPolygons
GetRootNeigh( 2, vEdges[2]) ;
vEdges.emplace_back() ;
GetRootNeigh( 3, vEdges[3]) ;
// scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato
for ( int i = 0 ; i < int( vEdges.size()) ; ++i) {
mCCEdges.emplace_back() ;