From a2825b2b6d5bce9f416fa3f9bb8c33afd8b7a8dd Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 11 Mar 2025 11:17:30 +0100 Subject: [PATCH] EgtGeomKernel : - migliorie MarchingSquares, semplificazione funzioni per CAv. --- CAvSilhouetteSurfTm.cpp | 391 ++++++---------------------------------- CAvSilhouetteSurfTm.h | 12 +- CAvToolSurfTm.cpp | 225 ++++++++++++----------- CAvToolSurfTm.h | 13 +- 4 files changed, 195 insertions(+), 446 deletions(-) diff --git a/CAvSilhouetteSurfTm.cpp b/CAvSilhouetteSurfTm.cpp index 798f488..7869a39 100644 --- a/CAvSilhouetteSurfTm.cpp +++ b/CAvSilhouetteSurfTm.cpp @@ -305,108 +305,6 @@ ModifyPolyLineToSharped( PNTIVECTOR& vAdvPt, const CAvToolSurfTm& cavTstm, const return true ; } -//---------------------------------------------------------------------------- -static bool -TestEdgesOpenPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int nStepX, int nStepY, - const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol, - bool bAdvCorners) -{ - // se non ho polylinee, allora esco - if ( vPL.empty()) - return true ; - dAngTol = max( dAngTol, ANG_TOL_STD_DEG / 5.) ; - double dSegLen = 50 * dStep ; - - // scorro le polyLinee aperte - for ( int nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) { - // essendo aperte, se presenti meno di 3 punti, non faccio nulla - int nPts = vPL[nPol].GetPointNbr() ; - if ( nPts < 3) - continue ; - - // creo un vettore contenente tutti i punti - PNTVECTOR vPt ; vPt.reserve( nPts) ; - Point3d myPt ; - if ( ! vPL[nPol].GetFirstPoint( myPt)) - return false ; - vPt.emplace_back( myPt) ; - while ( vPL[nPol].GetNextPoint( myPt)) - vPt.emplace_back( myPt) ; - - // creazione vettore di punti avanzati ( tutti validi) - PNTIVECTOR vAdvPt ; vAdvPt.reserve( nPts) ; - vPL[nPol].GetFirstPoint( myPt) ; - vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ; - while ( vPL[nPol].GetNextPoint( myPt)) - vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ; - - // modifico la posizione dei punti - if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen)) - return false ; - - // ricostrusico la polyLine - vPL[nPol].Clear() ; - double dPar = -1 ; - for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) { - // se punto valido o sharped di angolo interno, lo aggiungo - if ( j == 0 || j == int( vAdvPt.size() - 1) || - vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT) - vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ; - // se è un punto sharped di un angolo esterno - else if ( vAdvPt[j].second == PointType::SHARPED_EXT) { - // se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto - if ( ! bAdvCorners) - vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ; - else { - // ricavo il punto a minima distanza dal materiale mediante metodo di bisezione - Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ; - vtPrev.Normalize() ; - Vector3d vtAfter = ( vAdvPt[j+1].first - vAdvPt[j].first) ; - vtAfter.Normalize() ; - Vector3d vtMove = ( vtPrev + vtAfter) ; - vtMove.Normalize() ; - Point3d ptTest = vAdvPt[j].first + ( 2 * dStep * vtMove) ; // doppio dello step griglia - const int MAX_ITER = 20 ; - int nCount = 0 ; - while ( nCount < MAX_ITER) { - double dMove ; - ptTest.z += cavTstm.GetToolHeight() ; - ptTest.ToGlob( frGrid) ; - cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dMove) ; - ptTest.ToLoc( frGrid) ; - ptTest.z -= cavTstm.GetToolHeight() ; - if ( dMove > EPS_SMALL) - ptTest = Media( ptTest, vAdvPt[j].first) ; - else - break ; - ++ nCount ; - } - // ricavo i punti a minima distanza tra i due segmenti - Point3d ptMinDistA, ptMinDistB ; - DistPointLine distPtLPrev( ptTest, vAdvPt[j-1].first, vAdvPt[j].first) ; - DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ; - distPtLPrev.GetMinDistPoint( ptMinDistA) ; - distPtLSucc.GetMinDistPoint( ptMinDistB) ; - vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ; - vPL[nPol].AddUPoint( ++ dPar, ptTest) ; - vPL[nPol].AddUPoint( ++ dPar, ptMinDistB) ; - } - } - } - // se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla - // trimesh rischio di evere Chunk distinti uniti in un unico Chunk - PtrOwner pCompo( CreateCurveComposite()) ; - if ( IsNull( pCompo)) - return false ; - pCompo->FromPolyLine( vPL[nPol]) ; - SelfIntersCurve SIC( *pCompo) ; - if ( SIC.GetCrossOrOverlapIntersCount() > 0) - continue ; - } - - return true ; -} - //---------------------------------------------------------------------------- static bool TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int nStepX, int nStepY, @@ -572,7 +470,7 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int #if ENABLE_SHARPED_EDGES_DEBUG // 5° gruppo, punti minDist A e B e ptMid - PtrOwner myPtA( CreateGeoPoint3d()) ; + /*PtrOwner myPtA( CreateGeoPoint3d()) ; myPtA->Set( ptMinDistA) ; vvpGObj[4].emplace_back( static_cast( Release( myPtA))) ; vvCol[4].emplace_back( BROWN) ; @@ -583,7 +481,7 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int PtrOwner myPtMid( CreateGeoPoint3d()) ; myPtMid->Set( ptTest) ; vvpGObj[4].emplace_back( static_cast( Release( myPtMid))) ; - vvCol[4].emplace_back( BROWN) ; + vvCol[4].emplace_back( BROWN) ;*/ #endif } } @@ -629,8 +527,7 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int static bool MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, double dRad, double dOffsR, double dLevel, const CAvToolSurfTm& cavTstm, const Frame3d &frGrid, - double dDimZ, double dCalcLevel, bool bSharpedEdges, double dSharpedTol, - bool bAvdCorners, bool bWithOffs, POLYLINEVECTOR& vPL) + double dDimZ, double dCalcLevel, bool bTool, POLYLINEVECTOR& vPL) { #if ENABLE_PROCESS_SQUARE_DEBUG || ENABLE_BISECTION_DEBUG vector VT_GO ; @@ -859,9 +756,6 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, SaveGeoObj( VT_GO, VT_CO, Bisection_Debug_File_Name) ; #endif - // definisco un vettore di polyLine temporaneo - POLYLINEVECTOR vPL_Tmp ; - // Recupero i contorni INTVECTOR vnId ; while ( chainC.GetChainFromNear( ORIG, false, vnId)) { @@ -872,68 +766,31 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, Point3d ptCurr = vBiPnt[vnId[i]-1].second ; crvCompo.AddLine( ptCurr) ; } - // la chiudo se richiesto - if ( bWithOffs) - crvCompo.Close() ; + crvCompo.Close() ; // elimino le parti allineate crvCompo.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ; - // salto i contorni orari con area inferiore al doppio del quadrato se richiesto - if ( bWithOffs) { - double dCmpArea ; - if ( ! crvCompo.GetAreaXY( dCmpArea) || ( dCmpArea < 0 && abs( dCmpArea) < 2 * dStep * dStep)) - continue ; - } - // per test mettere a 1 - #if 1 - vPL_Tmp.emplace_back( PolyLine()) ; - crvCompo.ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL_Tmp.back()) ; - #else - // eseguo offset a sinistra pari allo step - OffsetCurve offsCompo ; - offsCompo.Make( &crvCompo, -( dRad - 2 * EPS_SMALL), ICurve::OFF_CHAMFER) ; - PtrOwner pCrvOffset( offsCompo.GetLongerCurve()) ; - if ( ! IsNull( pCrvOffset)) { - vPL_Tmp.emplace_back( PolyLine()) ; - pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL.back()) ; - } - #endif + // salto i contorni orari con area inferiore al doppio del quadrato + double dCmpArea ; + if ( ! crvCompo.GetAreaXY( dCmpArea) || ( dCmpArea < 0 && abs( dCmpArea) < 2 * dStep * dStep)) + continue ; + // memorizzo i risultati ottenuti + vPL.emplace_back( PolyLine()) ; + crvCompo.ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL.back()) ; } - // se richiesto calcolo degli spigoli vivi - if ( bSharpedEdges) { - // divido le polyLines aperte dalle chiuse - POLYLINEVECTOR vPL_Closed ; - POLYLINEVECTOR vPL_Open ; - for ( int j = 0 ; j < int( vPL_Tmp.size()) ; ++ j) { - if ( vPL_Tmp[j].IsClosed()) - vPL_Closed.emplace_back( vPL_Tmp[j]) ; - else - vPL_Open.emplace_back( vPL_Tmp[j]) ; - } - // ricostruisco gli spigoli vivi delle chiuse e delle aperte - POLYLINEVECTOR vPL_copy_Closed( vPL_Closed.size()) ; - for ( int j = 0 ; j < int( vPL_Closed.size()) ; ++ j) - vPL_copy_Closed[j] = vPL_Closed[j] ; - if ( TestEdgesClosedPolyLines( vPL_copy_Closed, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, dSharpedTol, bAvdCorners)) - swap( vPL_copy_Closed, vPL_Closed) ; - POLYLINEVECTOR vPL_copy_Open( vPL_Open.size()) ; - for ( int j = 0 ; j < int( vPL_Open.size()) ; ++ j) - vPL_copy_Open[j] = vPL_Open[j] ; - if ( TestEdgesOpenPolyLines( vPL_copy_Open, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, dSharpedTol, bAvdCorners)) - swap( vPL_copy_Open, vPL_Open) ; - vPL_Tmp.clear() ; - for ( int j = 0 ; j < int( vPL_Closed.size()) ; ++ j) - vPL_Tmp.emplace_back( vPL_Closed[j]) ; - for ( int j = 0 ; j < int( vPL_Open.size()) ; ++ j) - vPL_Tmp.emplace_back( vPL_Open[j]) ; - } + // le polyline ricavate, definendo dei contorni di regioni, sono chiuse ; cerco di ricostruire gli spigoli vivi + POLYLINEVECTOR vPL_Sharped( vPL.size()) ; + for ( int i = 0 ; i < int( vPL_Sharped.size()) ; ++ i) + vPL_Sharped[i] = vPL[i] ; + if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false)) + swap( vPL_Sharped, vPL) ; - // per ogni polyLine ottenuta effettuo Offset di correzione se richiesto - if ( bWithOffs) { - vPL.clear() ; - for ( int i = 0 ; i < int( vPL_Tmp.size()) ; ++ i) { + // se non ho impostato un utensile, devo effettuare un contro-offset + if ( ! bTool) { + POLYLINEVECTOR vPL_Offs ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { CurveComposite crvCompo ; - if ( ! crvCompo.FromPolyLine( vPL_Tmp[i])) + if ( ! crvCompo.FromPolyLine( vPL[i])) return false ; OffsetCurve offsCompo ; offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ; @@ -941,13 +798,25 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, while ( ! IsNull( pCrvOffset)) { PolyLine myPolyLine ; pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ; - vPL.emplace_back( myPolyLine) ; + vPL_Offs.emplace_back( myPolyLine) ; pCrvOffset.Set( offsCompo.GetLongerCurve()) ; } } + swap( vPL_Offs, vPL) ; } - else - swap( vPL_Tmp, vPL) ; + + #if ENABLE_BISECTION_DEBUG + VT_GO.emplace_back( static_cast( cavTstm.GetvStm()[0]->Clone())) ; + VT_GO.back()->ToLoc( frGrid) ; + VT_CO.emplace_back( GRAY) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + PtrOwner pCompo( CreateCurveComposite()) ; + pCompo->FromPolyLine( vPL[i]) ; + VT_GO.emplace_back( static_cast( pCompo->Clone())) ; + VT_CO.emplace_back( WHITE) ; + } + SaveGeoObj( VT_GO, VT_CO, Bisection_Debug_File_Name) ; + #endif return true ; } @@ -1021,7 +890,7 @@ CAvSilhouetteSurfTm( const ISurfTriMesh& Stm, const Plane3d& plPlane, double dTo // calcolo della silhouette con il metodo MarchingSquares double dLevel = dLevelOffs ; - if ( ! MarchingSquares( vdGrid, nStepX, nStepY, dTol, dRad, 0., dLevel, cavTstm, frGrid, -1., -1., false, 0., false, true, vPL)) + if ( ! MarchingSquares( vdGrid, nStepX, nStepY, dTol, dRad, 0., dLevel, cavTstm, frGrid, -1., -1., false, vPL)) return false ; // riporto nella corretta posizione le curve trovate for ( auto& PL : vPL) @@ -1060,45 +929,37 @@ CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& f m_nStepY = 0 ; m_dDimZ = 0 ; m_dLevelOffs = 0 ; + m_dCornRad = 0. ; + m_dMaxMat = INFINITO ; + m_dOffsR = 0. ; + m_dSideAng = 0. ; + m_dMaxDepth = 0. ; m_bGridOk = false ; + m_bTool = false ; return true ; } //---------------------------------------------------------------------------- bool -CAvParSilhouettesSurfTm::SetDataForRegion( const CISURFTMPVECTOR& vpStm, const ISurfFlatRegion* pSfr, double dSideAng, - double dDiam, double dCornRad, double dMaxMat, double dOffsR, - double dSampleTol, double dSharpedAngTol) +CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol, + double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR, + double dMaxDepth) { - // controllo validità della regione piana - if ( pSfr == nullptr || ! pSfr->IsValid()) - return false ; - - // recupero la FlatRegion - if ( ! m_Sfr.CopyFrom( pSfr) || ! m_Sfr.IsValid()) - return false ; - - // definisco il frame intrinseco alla regione piana - Frame3d frSfr ; - Point3d ptCenter ; m_Sfr.GetCentroid( ptCenter) ; - if ( ! frSfr.Set( ptCenter, m_Sfr.GetNormVersor())) - return false ; - - m_frGrid = frSfr ; m_vpStm = vpStm ; - m_dTol = max( dSampleTol, 100 * EPS_SMALL) ; - m_dSharpedTol = dSharpedAngTol ; + m_frGrid = frPlanes ; + m_dTol = max( dTol, 100 * EPS_SMALL) ; + m_nStepX = 0 ; + m_nStepY = 0 ; + m_dDimZ = 0 ; + m_dLevelOffs = 0 ; m_dRad = dDiam / 2. ; m_dCornRad = dCornRad ; m_dMaxMat = dMaxMat ; m_dOffsR = dOffsR ; m_dSideAng = dSideAng ; - m_nStepX = 0 ; - m_nStepY = 0 ; - m_dDimZ = 0 ; - m_dLevelOffs = 0 ; + m_dMaxDepth = dMaxDepth ; m_bGridOk = false ; - + m_bTool = true ; return true ; } @@ -1117,8 +978,8 @@ CAvParSilhouettesSurfTm::Prepare( void) } // calcolo dati della griglia - const double EXTRA_XY = 1.5 * m_dTol ; - const double EXTRA_Z = 10 * m_dTol ; + const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ; + const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ; b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ; m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ; m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ; @@ -1136,84 +997,6 @@ CAvParSilhouettesSurfTm::Prepare( void) } } - // esecuzione della verifica - if ( ! m_cavTstm.SetStdTool( m_dDimZ, m_dRad, 0)) - return false ; - if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0]))) - return false ; - for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k) - m_cavTstm.AddSurfTm( *( m_vpStm[k])) ; - if ( ! m_cavTstm.TestSeries( vPntM, m_frGrid.VersZ(), m_frGrid.VersZ(), -1)) - return false ; - - // griglia degli spostamenti - m_vdGrid.clear() ; - m_vdGrid.resize( ( m_nStepX + 1) * ( m_nStepY + 1)) ; - for ( int j = 0 ; j <= m_nStepY ; ++ j) { - for ( int i = 0 ; i <= m_nStepX ; ++ i) { - int nInd = i + j * ( m_nStepX + 1) ; - m_vdGrid[nInd] = vPntM[nInd].second ; - } - } - - // disegno la griglia colorando i punti in base alle altezze trovate - #if ENABLE_COLORED_GRID_DEBUG - vector VT_GO ; - vector VT_CO ; - for ( int i = 0 ; i < int( vPntM.size()) ; ++ i) { - PtrOwner myPt( CreateGeoPoint3d()) ; - myPt->Set( vPntM[i].first) ; - double myAngle = 240 + 120 * ( vPntM[i].second / m_dDimZ) ; - VT_GO.emplace_back( static_cast( Release( myPt))) ; - VT_CO.emplace_back( Color( GetColorFromHSV( HSV( myAngle, 1., 1.)))) ; - } - SaveGeoObj( VT_GO, VT_CO, Colored_Grid_Debug_File_Name) ; - #endif - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CAvParSilhouettesSurfTm::PrepareForRegion( void) -{ - // se la regione piana non è valida, allora esco - if ( ! m_Sfr.IsValid()) - return false ; - // se la regione piana ha normale diversa dalla griglia, allora errore - if ( ! AreSameVectorApprox( m_Sfr.GetNormVersor(), m_frGrid.VersZ())) - return false ; - - // ingombro delle superfici nel riferimento dei piani - BBox3d b3All ; - Frame3d frInv = GetInvert( m_frGrid) ; - for ( auto pStm : m_vpStm) { - BBox3d b3Surf ; - if ( ! pStm->GetBBox( frInv, b3Surf, BBF_STANDARD)) - return false ; - b3All.Add( b3Surf) ; - } - - // calcolo dati della griglia - const double EXTRA_XY = m_dRad + 2 ; // per maggiore sicurezza aggiungo 2 - const double EXTRA_Z = 10 * m_dTol ; - b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ; - m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ; - m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ; - m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ; - m_dDimZ = b3All.GetDimZ() ; - m_dLevelOffs = - b3All.GetMin().z ; - - // calcolo dei punti della griglia (sul top dell'utensile) - PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ; - for ( int j = 0 ; j <= m_nStepY ; ++ j) { - for ( int i = 0 ; i <= m_nStepX ; ++ i) { - int nInd = i + j * ( m_nStepX + 1) ; - Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ; - vPntM[nInd] = { ptP, 0.} ; - } - } - // esecuzione della verifica if ( m_dSideAng < EPS_ANG_SMALL) m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ; @@ -1251,7 +1034,6 @@ CAvParSilhouettesSurfTm::PrepareForRegion( void) } } - // disegno la griglia colorando i punti in base alle altezze trovate #if ENABLE_COLORED_GRID_DEBUG vector VT_GO ; @@ -1269,7 +1051,6 @@ CAvParSilhouettesSurfTm::PrepareForRegion( void) return true ; } - //---------------------------------------------------------------------------- bool CAvParSilhouettesSurfTm::GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) @@ -1282,11 +1063,12 @@ CAvParSilhouettesSurfTm::GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) return false ; m_bGridOk = true ; - // calcolo della silhouette con il metodo MarchingSquares dLevel += m_dLevelOffs ; + // controllo se ho impostato un utensile, in caso negativo, la silhouette richiede un contro-offset double dCalcLevel = max( dLevel, 0.) ; + // calcolo della silhouette con il metodo MarchingSquare if ( ! MarchingSquares( m_vdGrid, m_nStepX, m_nStepY, m_dTol, m_dRad, m_dOffsR, dCalcLevel, m_cavTstm, m_frGrid, - m_dDimZ, dCalcLevel, true, m_dSharpedTol, false, true, vPL)) + m_dDimZ, dCalcLevel, m_bTool, vPL)) return false ; // riporto nella corretta posizione le curve trovate @@ -1296,57 +1078,4 @@ CAvParSilhouettesSurfTm::GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) PL.ToGlob( m_frGrid) ; } return true ; -} - -//---------------------------------------------------------------------------- -bool -CAvParSilhouettesSurfTm::GetSilhouetteInsideRegion( double dLevel, POLYLINEVECTOR& vPL) -{ - // reset risultato - vPL.clear() ; - - // se necessario eseguo i calcoli preparatori - if ( ! m_bGridOk && ! PrepareForRegion()) - return false ; - m_bGridOk = true ; - - // calcolo della silhouette con il metodo MarchingSquares - dLevel += m_dLevelOffs ; - double dCalcLevel = max( dLevel, 0.) ; - if ( ! MarchingSquares( m_vdGrid, m_nStepX, m_nStepY, m_dTol, m_dRad, m_dOffsR, dCalcLevel, m_cavTstm, m_frGrid, - m_dDimZ, dCalcLevel, true, m_dSharpedTol, false, false, vPL)) - return false ; - - // taglio le regioni ottenute con la superficie piana - if ( m_Sfr.IsValid()) { - POLYLINEVECTOR vPL_InsideSfr ; - for ( auto& PL : vPL) { - // riporto nella corretta posizione le curve trovate - if ( dLevel < dCalcLevel - EPS_SMALL) - PL.Translate( Vector3d{ 0, 0, dLevel - dCalcLevel}) ; - PL.ToGlob( m_frGrid) ; - // definisco una curva composita a partire dalla polyline - CurveComposite curveCompo ; - curveCompo.FromPolyLine( PL) ; - // classifico la curva con la superficie piana di riferimento - CRVCVECTOR ccClass ; - if ( ! m_Sfr.GetCurveClassification( curveCompo, EPS_SMALL, ccClass)) - return false ; - for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { - // tengo tutti i tratti classfificati come "non fuori" - if ( ccClass[i].nClass != CRVC_OUT) { - PtrOwner pCrvCompoPartIn( ConvertCurveToComposite( curveCompo.CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; - if ( ! IsNull( pCrvCompoPartIn) && pCrvCompoPartIn->IsValid()) { - vPL_InsideSfr.emplace_back( PolyLine()) ; - pCrvCompoPartIn->ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL_InsideSfr.back()) ; - } - } - } - } - swap( vPL, vPL_InsideSfr) ; - } - else - return false ; - - return true ; } \ No newline at end of file diff --git a/CAvSilhouetteSurfTm.h b/CAvSilhouetteSurfTm.h index ea29982..764d1a5 100644 --- a/CAvSilhouetteSurfTm.h +++ b/CAvSilhouetteSurfTm.h @@ -24,19 +24,16 @@ class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm public : // generica bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol) override ; + bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol, + double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR, + double dMaxDepth) override ; bool GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) override ; - // con regione piana - bool SetDataForRegion( const CISURFTMPVECTOR& vpStm, const ISurfFlatRegion* pSfr, double dSideAng, - double dDiam, double dCornRad, double dMaxMat, double dOffsR, - double dSampleTol = 10 * EPS_SMALL, double dSharpedAngTol = 15.) override ; - bool GetSilhouetteInsideRegion( double dLevel, POLYLINEVECTOR& vPL) override ; public : CAvParSilhouettesSurfTm( void) ; private : bool Prepare( void) ; - bool PrepareForRegion( void) ; private : CISURFTMPVECTOR m_vpStm ; @@ -53,7 +50,8 @@ class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm double m_dOffsR ; double m_dDimZ ; double m_dLevelOffs ; + double m_dMaxDepth ; bool m_bGridOk ; + bool m_bTool ; DBLVECTOR m_vdGrid ; - SurfFlatRegion m_Sfr ; } ; \ No newline at end of file diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp index bb25fe1..3c7d1d7 100644 --- a/CAvToolSurfTm.cpp +++ b/CAvToolSurfTm.cpp @@ -160,10 +160,10 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve //---------------------------------------------------------------------------- bool -CAvToolSurfTm::TestPointAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, - double& dTotDist, VCT3DVECTOR& vVtN) const +CAvToolSurfTm::TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, + double& dTotDist, VCT3DVECTOR& vVtN) const { - // Funzione per calcolo collisione tra utensile e superfici; + // Funzione per calcolo collisione tra utensile e superfici ; // dToTDist è la distanza di traslazione del punto ptT lungo vtDir per evitare la collisione, // vVtN è la normale del triangolo che genera collsione ( NB. Nel caso di più triangoli concorrenti, // vengono restituite tutte le normali trovate) @@ -187,77 +187,16 @@ CAvToolSurfTm::TestPointAdv( const Point3d& ptT, const Vector3d& vtDir, const Ve frMove.Set( ORIG, vtMove) ; // Se riferimenti di movimento uguali, sfrutto HashGrid 2d if ( AreSameFrame( frMove, m_frMove)) { - // calcolo box utensile nel riferimento di movimento - BBox3d b3Tool ; - Point3d ptTL = ptT ; ptTL.ToLoc( m_frMove) ; - Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ; - b3Tool.Add( ptTL) ; - b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ; - if ( vtDirL.IsX()) - b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ; - else if ( vtDirL.IsY()) - b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ; - else if ( vtDirL.IsZ()) - b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ; - else { - double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ; - double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDirL.y * vtDirL.y) ; - double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ; - b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ; - } - // ciclo sui triangoli che intersecano box in 2d - INTVECTOR vnIds ; - if ( m_HGrids.Find( b3Tool, vnIds)) { - for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { - // recupero la superficie - int nInd = vnIds[i] ; - int nSurf = GetSurfInd( nInd) ; - if ( nSurf == -1) - return false ; - // recupero il triangolo - int nT = nInd - m_vBaseInd[nSurf] ; - Triangle3d Tria ; - if ( ! m_vSTM[nSurf]->GetTriangle( nT, Tria)) - return false ; - // calcolo della collisione - double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ; - if ( dDist < - EPS_SMALL) - return false ; - // se nuova distanza circa uguale a quella massima - if ( dDist > EPS_ZERO && abs( dDist - dTotDist) < 10 * EPS_SMALL) - vVtN.push_back( Tria.GetN()) ; - else if ( dDist > dTotDist + 10 * EPS_SMALL) { - dTotDist = dDist ; - vVtN.clear() ; - vVtN.push_back( Tria.GetN()) ; - } - } - } - return true ; + // Eseguo controllo + Point3d ptCurr = ptT ; + dTotDist = MyTestPositionHGAdv( ptCurr, vtDir, vVtN) ; + return ( dTotDist > - EPS_SMALL) ; } } - // Altrimenti eseguo controllo avanzato diretto - // scorro tutte le superfici - for ( auto pStm : m_vSTM) { - Triangle3d Tria ; - // scorro tutti i trinagoli - for ( int nTria = pStm->GetFirstTriangle( Tria) ; nTria != SVT_NULL ; nTria = pStm->GetNextTriangle( nTria, Tria)) { - double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; - if ( dDist < - EPS_SMALL) - return false ; - // se nuova distanza maggiore della massima ... - if ( dDist > dTotDist) { - dTotDist = dDist ; - vVtN.clear() ; - vVtN.push_back( Tria.GetN()) ; - } - // se distanza circa uguale alla massima corrente... - else if ( dDist > EPS_SMALL && dDist > dTotDist - EPS_SMALL) - vVtN.push_back( Tria.GetN()) ; - } - } - - return true ; + // Altrimenti eseguo controllo diretto + Point3d ptCurr = ptT ; + dTotDist = MyTestPositionAdv( ptCurr, vtDir, vtMove, vVtN) ; + return ( dTotDist > - EPS_SMALL) ; } //---------------------------------------------------------------------------- @@ -463,16 +402,21 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& //---------------------------------------------------------------------------- bool -CAvToolSurfTm::TestPointsAdv( PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff) +CAvToolSurfTm::TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff) { + // NB. la posizione del punto non viene modificata : + // get<0> vPntM[i] è il punto su cui viene posizionata la testa dell'utensile ( const) + // get<1> vPntM[i] è il parametro di traslazione del punto lungo vtDir per evitare collisioni con i triangoli + // get<2> vPntM[i] è un vettore di Vector3d contenente tutte le normali di tangenza ( a meno di 10 * EPS_SMALL) + // Se utensile non definito, errore if ( m_Tool.GetType() == Tool::UNDEF) return false ; // Se direzioni non definite, errore if ( vtDir.IsSmall() || vtMove.IsSmall()) return false ; - // Se lista vuota, non devo fare alcunché - if ( lPntM.empty()) + // Se vettore vuoto, non devo fare alcunché + if ( vPntM.empty()) return true ; // Calcolo nuovo riferimento di movimento Frame3d frMove ; @@ -489,35 +433,33 @@ CAvToolSurfTm::TestPointsAdv( PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const return false ; } // Determino il numero di punti del path - m_nTotPnt = int( lPntM.size()) ; + m_nTotPnt = int( vPntM.size()) ; // Recupero il numero massimo di thread concorrenti int nThreadMax = thread::hardware_concurrency() ; bool bOk = true ; // Se un solo thread o pochi punti if ( nThreadMax <= 1 || m_nTotPnt < 500) { m_nCurrPnt = 0 ; - bOk = TestSubPointsAdv( -1, lPntM, vtDir, vtMove, dProgCoeff) ; + bOk = TestSubSeriesAdv( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ; ProcessEvents( int( 100 * dProgCoeff), 0) ; } // altrimenti else { const int MAX_PARTS = 32 ; - PNTUVVECTLIST vlPntM[MAX_PARTS] ; - // divido la lista in parti + INTINTVECTOR vFstLst( MAX_PARTS) ; + // calcolo le parti del vettore int nPartCnt = min( nThreadMax, MAX_PARTS) ; - int nPartDim = m_nTotPnt / nPartCnt ; - for ( int i = nPartCnt - 1 ; i > 0 ; -- i) { - auto itSplit = prev( lPntM.end(), nPartDim) ; - vlPntM[i].splice( vlPntM[i].end(), lPntM, itSplit, lPntM.end()) ; - vlPntM[i].push_front( lPntM.back()) ; + int nPartDim = m_nTotPnt / nPartCnt + 1 ; + for ( int i = 0 ; i < nPartCnt ; ++ i) { + vFstLst[i].first = i * nPartDim ; + vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ; } - vlPntM[0].splice( vlPntM[0].end(), lPntM) ; // processo le parti m_nCurrPnt = 0 ; m_bBreak = false ; future vRes[MAX_PARTS] ; for ( int i = 0 ; i < nPartCnt ; ++ i) - vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPointsAdv, this, i, ref( vlPntM[i]), cref( vtDir), cref( vtMove), dProgCoeff) ; + vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeriesAdv, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ; // attendo i risultati int nFin = 0 ; int nNextPE = 0 ; @@ -535,15 +477,8 @@ CAvToolSurfTm::TestPointsAdv( PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const m_bBreak = true ; } } - // unisco le liste risultati - for ( int i = 0 ; i < nPartCnt ; ++ i) { - if ( i > 0) - lPntM.pop_back() ; - lPntM.splice( lPntM.end(), vlPntM[i]) ; - } ProcessEvents( int( 100 * dProgCoeff), 0) ; } - return bOk ; } @@ -595,21 +530,18 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou //---------------------------------------------------------------------------- bool -CAvToolSurfTm::TestSubPointsAdv( int nId, PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff) +CAvToolSurfTm::TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) { - // Se lista vuota, non devo fare alcunché - if ( lPntM.empty()) + // Se vettore vuoto, non devo fare alcunché + if ( vPntM.empty()) return true ; - // Ciclo sui punti - auto itPntMPrev = lPntM.end() ; - auto itPntMCurr = lPntM.begin() ; - while ( itPntMCurr != lPntM.end()) { + // Ciclo sui punti da verificare + for ( int i = nFirst ; i <= nLast ; ++ i) { // verifico il punto - if ( ! TestPointAdv( get<0>( *itPntMCurr), vtDir, vtMove, get<1>( *itPntMCurr), get<2>( *itPntMCurr))) + Point3d ptCurr = get<0>( vPntM[i]) ; + get<1>( vPntM[i]) = MyTestPositionHGAdv( ptCurr, vtDir, get<2>( vPntM[i])) ; + if ( get<1>( vPntM[i]) < - EPS_SMALL) return false ; - // passo al successivo - itPntMPrev = itPntMCurr ; - ++ itPntMCurr ; ++ m_nCurrPnt ; // se singolo thread if ( nId == -1) { @@ -688,6 +620,34 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector return dTotDist ; } +//---------------------------------------------------------------------------- +double +CAvToolSurfTm::MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const +{ + double dTotDist = 0 ; + vVtTriaN.clear() ; + for ( auto pStm : m_vSTM) { + Triangle3d Tria ; + for ( int nTria = pStm->GetFirstTriangle( Tria) ; + nTria != SVT_NULL ; + nTria = pStm->GetNextTriangle( nTria, Tria)) { + double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; + if ( dDist < - EPS_SMALL) + return -1 ; + // se devo traslare il punto, c'è collisione + if ( dDist > EPS_SMALL) { + if ( dDist > 10 * EPS_SMALL) { + vVtTriaN.clear() ; + dTotDist += dDist ; + ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ; + } + vVtTriaN.push_back( Tria.GetN()) ; + } + } + } + return dTotDist ; +} + //---------------------------------------------------------------------------- double CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const @@ -739,6 +699,63 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& return dTotDist ; } +//---------------------------------------------------------------------------- +double +CAvToolSurfTm::MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const +{ + // calcolo box utensile nel riferimento di movimento + BBox3d b3Tool ; + Point3d ptTL = ptT ; ptTL.ToLoc( m_frMove) ; + Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ; + b3Tool.Add( ptTL) ; + b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ; + if ( vtDirL.IsX()) + b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ; + else if ( vtDirL.IsY()) + b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ; + else if ( vtDirL.IsZ()) + b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ; + else { + double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ; + double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDirL.y * vtDirL.y) ; + double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ; + b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ; + } + + // ciclo sui triangoli che intersecano box in 2d + double dTotDist = 0. ; + INTVECTOR vnIds ; + if ( m_HGrids.Find( b3Tool, vnIds)) { + for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { + // recupero la superficie + int nInd = vnIds[i] ; + int nSurf = GetSurfInd( nInd) ; + if ( nSurf == -1) + return -1 ; + // recupero il triangolo + int nT = nInd - m_vBaseInd[nSurf] ; + Triangle3d Tria ; + if ( ! m_vSTM[nSurf]->GetTriangle( nT, Tria)) + return -1 ; + // calcolo della collisione + double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ; + if ( dDist < - EPS_SMALL) + return -1 ; + // se devo traslare il punto, c'è collisione + if ( dDist > EPS_SMALL) { + if ( dDist > 10 * EPS_SMALL) { + vVtTriaN.clear() ; + dTotDist += dDist ; + ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ; + } + vVtTriaN.push_back( Tria.GetN()) ; + } + } + } + + return dTotDist ; +} + //---------------------------------------------------------------------------- bool CAvToolSurfTm::PrepareHashGrid( void) diff --git a/CAvToolSurfTm.h b/CAvToolSurfTm.h index 7b7f445..0d98b29 100644 --- a/CAvToolSurfTm.h +++ b/CAvToolSurfTm.h @@ -48,13 +48,16 @@ class CAvToolSurfTm : public ICAvToolSurfTm } const ICurveComposite& GetToolOutline( bool bApprox = false) const override { return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;} + bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ; - bool TestPointAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, - double& dTotDist, VCT3DVECTOR& vVtN) const override ; + bool TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, + double& dTotDist, VCT3DVECTOR& vVtN) const override ; + bool TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ; + bool TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ; + bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ; - bool TestPointsAdv( PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ; public : CAvToolSurfTm( void) ; @@ -62,10 +65,12 @@ class CAvToolSurfTm : public ICAvToolSurfTm private : bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ; + bool TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ; bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff) ; - bool TestSubPointsAdv( int nId, PNTUVVECTLIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff) ; double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const ; + double MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const ; double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const ; + double MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const ; bool MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr, const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ; bool PrepareHashGrid( void) ;