From 91ca84f77a42849265cad92a62800913574db529 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 19 Dec 2025 15:03:19 +0100 Subject: [PATCH] EgtGeomKernel : - miglioramento delle superfici di bezier. - aggiunta di una funzione per l'eliminazione delle span collassate e di una per l'inversione dei paramettri di una superficie. --- SurfBezier.cpp | 255 ++++++++++++++++++++++++++++++++++++++++++++-- SurfBezier.h | 2 + Tree.cpp | 99 +++++++++++------- VolZmapVolume.cpp | 1 - 4 files changed, 311 insertions(+), 46 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 6dbbe3f..92eed3d 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1771,6 +1771,8 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const return dLen ; } +int nSurf = 0 ; + //---------------------------------------------------------------------------- const SurfTriMesh* SurfBezier::GetAuxSurf( void) const @@ -1800,6 +1802,7 @@ SurfBezier::GetAuxSurf( void) const } // eseguo calcolo m_pSTM = GetApproxSurf( s_dAuxSurfTol, 100 * EPS_SMALL, false) ; + ++nSurf ; if ( m_pSTM != nullptr) m_pSTM->SetTempParam( s_dAuxSurfTol) ; return m_pSTM ; @@ -1859,7 +1862,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons // costruttore della superficie POLYLINEMATRIX vvPL ; POLYLINEMATRIX vvPL3d ; - //POLYLINEVECTOR vPL ; // per usare i polygon basic Tree Tree ; if ( ! Tree.SetSurf( this)) return nullptr ; @@ -1868,29 +1870,25 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons // resetto il vettore degli edge m_mCCEdge.clear() ; m_vCCLoop.clear() ; + for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = get<0>( vTrees[i]) ; Point3d ptMax = get<1>( vTrees[i]) ; Tree.SetSurf( this, ptMin, ptMax) ; - Tree.BuildTree( dTol, dSideMin) ; + if( ! Tree.BuildTree( dTol, dSideMin)) { + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface parametric space couldn't be split in cells") ; + return nullptr ; + } if ( ! Tree.GetPolygons( vvPL, vvPL3d, m_mCCEdge, m_vCCLoop, bUpdateEdges)) continue ; - //Tree.GetPolygonsBasic( vPL, true) ; // per usare i polygon basic // aggiorno la chiusura della superficie m_bClosedU = m_bClosedU || Tree.IsClosedU() ; m_bClosedV = m_bClosedV || Tree.IsClosedV() ; } - //// per usare i polygon basic////////////////////// - //for (int k = 0 ; k < (int)vPL.size(); ++k) { - // vvPL.emplace_back() ; - // vvPL.back().push_back(vPL[k]) ; - //} - //// per usare i polygon basic/////////////////// - if ( vvPL.empty()) - LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated") ; + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated") StmFromTriangleSoup stmSoup ; if ( ! stmSoup.Start()) @@ -5901,5 +5899,240 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c ++ nAddedSpan ; } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::RemoveCollapsedSpans() +{ + //controllo se ho delle span collassate e le rimuovo + if( m_nSpanU > 1 || m_nSpanV > 1) { + CalcPoles() ; + if( ! m_vbPole[2]) { + // scorro i punti della prima riga + INTVECTOR vnCollapsedSpan ; + for( int i = 0 ; i < m_nSpanU ; ++i) { + bool bSamePoint = true ; + Point3d ptFirst = m_vPtCtrl[m_nDegU * i] ; + // cerco se trovo tutti i punti in U coincidenti in una delle Span + for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { + if( ! AreSamePointExact( ptFirst, m_vPtCtrl[m_nDegU * i + j])) + bSamePoint = false ; + } + if( bSamePoint) { + // se trovo un'altra riga collassata do per scontato che tutta span sia collassata + ptFirst = m_vPtCtrl[GetInd( m_nDegU * i, 1)] ; + for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { + if( ! AreSamePointExact( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)])) + bSamePoint = false ; + } + if( bSamePoint) + vnCollapsedSpan.push_back( i) ; + } + } + int nOldSpanU = m_nSpanU ; + if( ! vnCollapsedSpan.empty()) { + // cancello le span che risultano collassate + int nNewSpanU = m_nSpanU - ssize( vnCollapsedSpan) ; + int nNewDim = ( m_nDegU * nNewSpanU + 1) * ( m_nDegV * m_nSpanV + 1) ; + PNTVECTOR vNewCtrlPnt( nNewDim) ; + DBLVECTOR vNewWeight( nNewDim) ; + int nCurrSkipInd = -1 ; + int nCurrSkip = -1 ; + for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { + nCurrSkipInd = 0 ; + nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; + for( int i = 0 ; i < m_nSpanU ; ++i) { + if( i != nCurrSkip) { + for( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { + vNewCtrlPnt[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ; + if( m_bRat) { + vNewWeight[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ; + } + } + } + else { + ++nCurrSkipInd ; + if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) + nCurrSkip = -1 ; + else + nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; + } + } + } + // aggiorno i dati della superficie + // vettori dei punti e numero di span + ISurfFlatRegion* pSFRTrim = nullptr ; + bool bTrimmed = m_bTrimmed ; + if( bTrimmed) { + pSFRTrim = GetTrimRegion() ; + m_pTrimReg = nullptr ; + } + Init( m_nDegU, m_nDegV, nNewSpanU, m_nSpanV, m_bRat) ; + m_vPtCtrl = vNewCtrlPnt ; + if( m_bRat) + m_vWeCtrl = vNewWeight ; + if( bTrimmed) { + // elimino le span di troppo dallo spazio parametrico + PtrOwner pNewTrim( pSFRTrim->Clone()) ; + for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { + int nSpan = vnCollapsedSpan[i] ; + // tolgo tutta la parte a destra della colonna da togliere + PtrOwner pSFRCut ( GetSurfFlatRegionRectangle( ( nOldSpanU - nSpan) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ; + if( nSpan != 0) { + pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ; + pNewTrim->Subtract( *pSFRCut) ; + } + if( pNewTrim->IsValid()) { + // ritaglio dal parametrico originale la parte a destra della colonna da eliminare e la incollo alla parte a sinistra + PtrOwner pRightPart( pSFRTrim->Clone()) ; + pSFRCut.Set( GetSurfFlatRegionRectangle( ( nSpan + 1) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ; + pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ; + if( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) { + if( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid()) + break ; + } + } + else + break ; + } + SetTrimRegion( *pSFRTrim) ; + } + } + } + + if( ! m_vbPole[1]) { + // scorro i punti della prima colonna + INTVECTOR vnCollapsedSpan ; + for( int i = 0 ; i < m_nSpanV ; ++i) { + bool bSamePoint = true ; + Point3d ptFirst = m_vPtCtrl[GetInd( 0, i * m_nDegV)] ; + // cerco se trovo tutti i punti in U coincidenti in una delle Span + for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { + if( ! AreSamePointExact( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)])) + bSamePoint = false ; + } + if( bSamePoint) { + // se trovo un'altra colonna collassata do per scontato che tutta span sia collassata + ptFirst = m_vPtCtrl[GetInd( 1, i * m_nDegV)] ; + for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { + if( ! AreSamePointExact( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)])) + bSamePoint = false ; + } + if( bSamePoint) + vnCollapsedSpan.push_back( i) ; + } + } + int nOldSpanV = m_nSpanV ; + if( ! vnCollapsedSpan.empty()) { + // cancello le span che risultano collassate + int nNewSpanV = m_nSpanV - ssize( vnCollapsedSpan) ; + int nNewDim = ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * nNewSpanV + 1) ; + PNTVECTOR vNewCtrlPnt( nNewDim) ; + DBLVECTOR vNewWeight( nNewDim) ; + int nCurrSkipInd = 0 ; + int nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; + for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { + if( nIndV / m_nDegV != nCurrSkip) { + for( int i = 0 ; i < m_nSpanU ; ++i) { + for( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { + vNewCtrlPnt[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ; + if( m_bRat) { + vNewWeight[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ; + } + } + } + } + else { + nIndV += m_nDegV - 1 ; + ++nCurrSkipInd ; + if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) + nCurrSkip = -1 ; + else + nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; + } + } + // aggiorno i dati della superficie + // vettori dei punti e numero di span + ISurfFlatRegion* pSFRTrim = nullptr ; + bool bTrimmed = m_bTrimmed ; + if( bTrimmed) { + pSFRTrim = GetTrimRegion() ; + m_pTrimReg = nullptr ; + } + Init( m_nDegU, m_nDegV, m_nSpanU, nNewSpanV, m_bRat) ; + m_vPtCtrl = vNewCtrlPnt ; + if( m_bRat) + m_vWeCtrl = vNewWeight ; + if( bTrimmed) { + // elimino le span di troppo dallo spazio parametrico + PtrOwner pNewTrim( pSFRTrim->Clone()) ; + for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { + int nSpan = vnCollapsedSpan[i] ; + // tolgo tutta la parte a sopra la riga da togliere + PtrOwner pSFRCut ( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nOldSpanV - nSpan) * SBZ_TREG_COEFF)) ; + if( nSpan != 0) { + pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ; + pNewTrim->Subtract( *pSFRCut) ; + } + if( pNewTrim->IsValid()) { + // ritaglio dal parametrico originale la parte sopra la riga da eliminare e la incollo alla parte sotto la riga + PtrOwner pUpperPart( pSFRTrim->Clone()) ; + pSFRCut.Set( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nSpan + 1) * SBZ_TREG_COEFF)) ; + pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ; + if( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) { + if( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid()) + break ; + } + } + else + break ; + } + SetTrimRegion( *pSFRTrim) ; + } + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::SwapParameters() +{ + // inverto il parametro U con il parametro V + // salvo i vecchi dati + int nSpanU = m_nSpanV ; + int nSpanV = m_nSpanU ; + int nDegU = m_nDegV ; + int nDegV = m_nDegU ; + bool bTrimmed = m_bTrimmed ; + PtrOwner pSFRTRim ; + if( m_bTrimmed) { + pSFRTRim.Set( GetTrimRegion()) ; + m_pTrimReg = nullptr ; + } + + // creo il vettore dei punti di controllo + PNTVECTOR vNewCtrlPt( GetDim()) ; + DBLVECTOR vNewWeight( GetDim()) ; + for( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) { + for( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) { + vNewCtrlPt[i * ( nDegU * nSpanU + 1) + j] = m_vPtCtrl[GetInd(i,j)] ; + if( m_bRat) + vNewWeight[i * ( nDegU * nSpanU + 1) + j] = m_vWeCtrl[GetInd(i,j)] ; + } + } + + Init( nDegU, nDegV, nSpanU, nSpanV, m_bRat) ; + if( bTrimmed) { + pSFRTRim->Mirror( ORIG, Vector3d(1,-1)) ; + SetTrimRegion( *pSFRTRim) ; + } + m_vPtCtrl = vNewCtrlPt ; + m_vWeCtrl = vNewWeight ; + return true ; } \ No newline at end of file diff --git a/SurfBezier.h b/SurfBezier.h index e977000..2e7b89b 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -151,6 +151,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW PNTVECTOR GetAllControlPoints( void) const ; bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ; bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const ICURVEPOVECTOR& vCrv) ; + bool RemoveCollapsedSpans() override ; + bool SwapParameters() ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/Tree.cpp b/Tree.cpp index b4a318a..f27dc6f 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -474,7 +474,8 @@ Tree::Split( int nId, double dSplitValue) GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; } - if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) + 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) { @@ -490,7 +491,8 @@ Tree::Split( int nId, double dSplitValue) GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; } - if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) + 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 ; } @@ -786,6 +788,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) nCToSplit = pcToSplit->m_nChild1 ; pcToSplit = &m_mTree[nCToSplit] ; } + else + return false ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella @@ -899,6 +903,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) nCToSplit = pcToSplit->m_nChild1 ; pcToSplit = &m_mTree[nCToSplit] ; } + else + return false ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella @@ -1435,19 +1441,20 @@ 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 nPoly = 0 ; + 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[nPoly])) ; vvPolygons3d.emplace_back() ; - vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[i])) ; + vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[nPoly])) ; } else if ( m_mTree[nId].m_nFlag == 0) 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 INTVECTOR vnParentChunk ; @@ -1461,13 +1468,14 @@ 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[nPoly], vPolygonsBasic3d[nPoly]) ; 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[nPoly], vPolygonsBasic3d[nPoly]) ; } + ++ nPoly ; } } @@ -1910,10 +1918,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 @@ -1964,12 +1971,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 ; @@ -1977,7 +1988,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 ; } @@ -1996,10 +2007,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 @@ -2011,7 +2029,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 ; @@ -2117,9 +2135,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)) { @@ -2128,6 +2147,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 @@ -2153,13 +2174,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 @@ -2783,11 +2814,10 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, //---------------------------------------------------------------------------- bool -Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, +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] ; Cell& cCell = m_mTree[nId] ; PNTMATRIX vEdgeVertex(4) ; PNTMATRIX vEdgeVertex3d(4) ; @@ -2795,7 +2825,7 @@ 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 ; + int nVertToErase = cCell.m_nVertToErase ; if ( nVertToErase != 2) vEdgeVertex[0].push_back( ptTR) ; if ( nVertToErase != 3) @@ -3116,11 +3146,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 @@ -3994,7 +4023,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 ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index c15ca17..bd28b54 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -1392,7 +1392,6 @@ IntersLineBezierSurfSet( const Point3d& ptLineStart, const Vector3d& vtLineDir, const SurfBezForInters& srf = vSurfBez[s] ; BBox3d bbox = srf.bbSurfOriented; - bool bNotValid = false ; Point3d rLoc = r ; Vector3d qLoc = q ; if ( ! bNeedToRot) {