diff --git a/EgtMachKernel.rc b/EgtMachKernel.rc index 82463e7..71a1b91 100644 Binary files a/EgtMachKernel.rc and b/EgtMachKernel.rc differ diff --git a/SurfRoughing.cpp b/SurfRoughing.cpp index f1142a1..6f27f34 100644 --- a/SurfRoughing.cpp +++ b/SurfRoughing.cpp @@ -93,6 +93,7 @@ using namespace std ; // 3054 = "Warning in SurfRoughing : Tool data changed (xx)" // 3055 = "Warning in SurfRoughing : CalcPocketing failed with substep (xx)" // 3056 = "Warning in SurfRoughing : invalid Conformal ZigZag at substep (xx)" +// 3057 = "Warning in SurfRoughing : Depth reduced at (xx)" //---------------------------------------------------------------------------- static string KEY_SURF_POCK = "SurfPock_" ; @@ -107,15 +108,20 @@ static string KEY_SUBSTEP = "SUBSTEP" ; #define ENABLE_DEBUG_SFR 0 #define ENABLE_DEBUG_STM_NORMAL_SHADER 0 +#define ENABLE_DEBUG_REMOVED_REGION 0 #define ENABLE_DEBUG_FEEDS 0 #define ENABLE_DEBUG_SFR_BOOLEANS 0 +#define ENABLE_DEBUG_SFR_COLLISION 0 #define ENABLE_DEBUG_ZPLANE 0 #define ENBALE_DEBUG_LINK 0 #define ENABLE_DEBUG_ORDER_ZCHUNK 0 -#if ENABLE_DEBUG_SFR_BOOLEANS || ENBALE_DEBUG_LINK +#if ENABLE_DEBUG_SFR || ENABLE_DEBUG_STM_NORMAL_SHADER || ENABLE_DEBUG_REMOVED_REGION || \ + ENABLE_DEBUG_FEEDS || ENABLE_DEBUG_SFR_BOOLEANS || ENABLE_DEBUG_SFR_COLLISION || ENABLE_DEBUG_ZPLANE || \ + ENBALE_DEBUG_LINK || ENABLE_DEBUG_ORDER_ZCHUNK #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EgtPerfCounter.h" + #include "/EgtDev/Include/EGkExtText.h" string sPathSrfBool = "C:\\Temp\\" ; #endif @@ -123,6 +129,8 @@ const double STEP_TOL = 10. * EPS_SMALL ; const double SIL_DEPTH_TOL = 100. * EPS_SMALL ; const double OFFS_CORR_OPEN_EDGES = 25. * EPS_SMALL ; const double SUPP_SURF_RADIAL_OFFS = 5. ; +const double TOL_OFFS_CORNER_COLL = 50. * EPS_SMALL ; +const double DIST_TABLE = 5. * EPS_SMALL ; //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_SURFROUGHING), SurfRoughing) ; @@ -893,7 +901,7 @@ SurfRoughing::GetToolData( void) const //---------------------------------------------------------------------------- bool -SurfRoughing::UpdateToolData( void) +SurfRoughing::UpdateToolData() { // recupero il gestore DB utensili della macchina corrente ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ; @@ -1523,6 +1531,14 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) if ( IsNull( pStmLimit)) return false ; + // determino la regione piana di tavola e ventose per evitare collisioni + // NB. creo una regione piana perchè questa è statica per ogni step, non si adatta + PtrOwner pSfrColl( CreateSurfFlatRegion()) ; + PtrOwner pSfrSearchCorners( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrColl) || IsNull( pSfrSearchCorners) || + ! GetToolCollisionRegion( pSfrSgro, dDepth, pSfrColl, pSfrSearchCorners)) + return false ; + // inizializzo la classe di intersezione tra la superficie trimesh limite e piani paralleli ( quelli di lavoro) IntersParPlanesSurfTm IPPStm1( frSfr, *pStmLimit) ; @@ -1644,12 +1660,12 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) // inserimento degli step ( ed eventuali PlaneZ se SubSteps non presenti) for ( int i = 0 ; i < nStep ; ++ i) { - vStepInfo.emplace_back( -1, - ( i + 1) * dStep, false, false, 1., nullptr, nullptr) ; + vStepInfo.emplace_back( -1, - ( i + 1) * dStep, false, false, 1., nullptr, nullptr, nullptr) ; // se non ho SubStep ma PlaneZ, inserisco i PlaneZ if ( nSubStep == -1) { for ( int j = 0 ; j < int( vPlaneZ.size()) ; ++ j) { if ( vPlaneZ[j].second > - ( i + 1) * dStep + STEP_TOL && vPlaneZ[j].second < - i * dStep - STEP_TOL) { - vStepInfo.emplace_back( i, vPlaneZ[j].second, false, true, -1., nullptr, nullptr) ; + vStepInfo.emplace_back( i, vPlaneZ[j].second, false, true, -1., nullptr, nullptr, nullptr) ; vStepInfo.back().pSfrPlaneZ = Release( vPlaneZ[j].first) ; } } @@ -1676,7 +1692,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) int nMyInd = ( j == i - 1 ? nIndRef : int( vStepInfo.size()) - 1) ; bool bSS = ( vExtraStep[j].first == -1) ; vStepInfo.emplace_back( nMyInd, vExtraStep[j].second, bSS, ! bSS, - -1. , nullptr, nullptr) ; + -1. , nullptr, nullptr, nullptr) ; if ( ! bSS) vStepInfo.back().pSfrPlaneZ = Release( vPlaneZ[vExtraStep[j].first].first) ; } @@ -1685,7 +1701,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) } } - // definisco il vettore per salvataggio delle regione e dei loro parametri nel GromDB + // definisco il vettore per salvataggio delle regione e dei loro parametri nel GeomDB SFRGEODBINFOVECTOR vInfoSfrGeomDB ; vInfoSfrGeomDB.reserve( vStepInfo.size()) ; @@ -1733,6 +1749,8 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) return false ; /* ***************** Regione piana esterna ai contorni ****************** */ + // regione definita dalla parte di grezzo al di fuori della curva di sgrossatura + // unita ad eventuale regione di collisione PtrOwner pSfrOutCompo( CreateSurfFlatRegion()) ; if ( IsNull( pSfrOutCompo)) return false ; @@ -1743,9 +1761,19 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) return false ; } } + if ( ! IsNull( pSfrColl) && pSfrColl->IsValid()) { + PtrOwner pSfrCollTransl( CloneSurfFlatRegion( pSfrColl)) ; + if ( IsNull( pSfrCollTransl) || ! pSfrCollTransl->IsValid()) + return false ; + pSfrCollTransl->Translate( ( dSfrDepth + GetOffsL()) * vtTool) ; + if ( IsNull( pSfrOutCompo) || ! pSfrOutCompo->IsValid()) + pSfrOutCompo.Set( CloneSurfFlatRegion( pSfrCollTransl)) ; + else + pSfrOutCompo->Add( *pSfrCollTransl) ; + } /* *************************** Silhouette **************************** */ - // determino la regione da non lavorare e la sottraggo + // determino la regione da non lavorare ( dalle geometrie selezionate) e la sottraggo double dSilDepth = dSfrDepth - ( it->bPlaneZStep ? SIL_DEPTH_TOL : 0.) ; bool bOkSil = false ; PtrOwner pSfrSil_Hypothetical( CreateSurfFlatRegion()) ; @@ -1782,6 +1810,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) continue ; // passo allo step successivo ( la silhouette coincide con il grezzo ) /* ************************** Superfici di supporto ************************ */ + // sottraggo i contributi dovuti a regioni di supporto ( mediante Offset in 2d) if ( ! vSurfL_supp.empty()) { bool bOkSil_supp = false ; PtrOwner pSfrSil_supp( GetSfrSilhouette( pCavParSilh_supp, dSilDepth, SILH_TOL, bOkSil_supp)) ; @@ -1819,7 +1848,6 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) return false ; /* *************************** Gestione StepExtra **************************** */ - // piccolo Offset di correzione per booleane SurfFlatRegion if ( it->bSubStep) { // recupero l'indice nel vettore dello step di riferimento int nIndRef = it->nIndRef ; @@ -1829,18 +1857,34 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) } // recupero la superficie progressiva dello step di riferimento - PtrOwner pSfrRef( CloneSurfFlatRegion( vStepInfo[nIndRef].pSfrRemoved)) ; - if ( ! IsNull( pSfrRef) && pSfrRef->IsValid()) { // se valida - pSfrRef->Offset( OFFS_CORR_OPEN_EDGES, ICurve::OFF_FILLET) ; // correzione - if ( ! pSfr->Subtract( *pSfrRef)) { // sottraggo la regione svuotata in precedenza + PtrOwner pSfrRemovedRef( CloneSurfFlatRegion( vStepInfo[nIndRef].pSfrRemoved)) ; + if ( ! IsNull( pSfrRemovedRef) && pSfrRemovedRef->IsValid()) { // se valida + pSfrRemovedRef->Offset( OFFS_CORR_OPEN_EDGES, ICurve::OFF_FILLET) ; // correzione per booleane + if ( ! pSfr->Subtract( *pSfrRemovedRef)) { // sottraggo la regione svuotata in precedenza #if ENABLE_DEBUG_SFR_BOOLEANS SaveSfrBooleans( pSfr, pSfrRef, sPathSrfBool + "Sub_" + to_string( it->dDepth) + ".nge") ; #endif // NB. In attesa di una versione più robusta per le booleane tra regioni piane, il substep viene scartato continue ; - }// aggiorno Regione piana per gestione lati aperti - pSfrOpenClose->Subtract( *pSfrRef) ; + } + // aggiorno Regione piana per gestione lati aperti + pSfrOpenClose->Subtract( *pSfrRemovedRef) ; } + + /* ******************** Regione di Corner ******************************** */ + // se presente una regione di Corner la aggiungo alla regione attuale da lavorare + // ( estendo quindi la regione ) + if ( vStepInfo[nIndRef].pSfrCorn != nullptr && vStepInfo[nIndRef].pSfrCorn->IsValid()) { + pSfr->Add( *vStepInfo[nIndRef].pSfrCorn) ; + // verifico sempre di non rovinare la regione di Silhouette e la regione al di fuori + // della curva di bordo di sgrossatura + if ( ! IsNull( pSfrOutCompo) && pSfrOutCompo->IsValid()) + pSfr->Subtract( *pSfrOutCompo) ; + if ( ! IsNull( pSfrSil) && pSfrSil->IsValid()) + pSfr->Subtract( *pSfrSil) ; + } + + } else if ( it->bPlaneZStep && ! IsNull( pSfrSil) && pSfrSil->IsValid()) { PtrOwner pSfrRef( CloneSurfFlatRegion( it->pSfrRemoved)) ; @@ -1905,10 +1949,11 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) pSfrOpenClose->Subtract( *pSfrRef) ; } - // se regione risultante non vuota + // se regione risultante non vuota if ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) { // *************************** Regione Limite *************************** + // la regione limite definisce le aree dove l'utensile non deve passare PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; if ( IsNull( pSfrLimit)) return false ; @@ -1921,7 +1966,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) pSfrLimit.Set( pSfrSil) ; } - // se si tratta di un SottoStep, rimuovo tutti i chunk troppo snelli + // rimuovo tutti i chunk troppo snelli if ( it->bSubStep) { if ( ! RemoveChunksUnderTolerance( pSfr, m_dSubStepToler, pSfrLimit, it->pSfrRemoved)) { m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ; @@ -1940,7 +1985,8 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) m_pMchMgr->SetLastError( 3026, "Error in SurfRoughing : Detecting open edges failed") ; return false ; } - // se step base + + // se step base, rimuovo i Chunk sotto una certa tolleranza if ( ! it->bSubStep && ! it->bPlaneZStep) { RemoveChunksUnderTolerance( pSfr, m_dStepToler, pSfrLimit) ; // se dopo la semplificazione non rimane nulla, allora passo allo step successivo @@ -1955,7 +2001,9 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) if ( ! CloseOpenEdgesUnderTolerance( pSfr, m_TParams.m_dDiam - 200 * EPS_SMALL)) { m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ; return false ; - } + } + + // rimuovo i Chunk troppo snelli ( la regione è cambiata rispetto a prima) if ( it->bSubStep) { // rimuovo tutti i Chunk snelli RemoveChunksUnderTolerance( pSfr, m_dSubStepToler, pSfrLimit) ; @@ -1967,6 +2015,17 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) } } + // se rischiesto, calcolo la regione di Corner allo/al Step/SubStep corrente + bool bSfrCorner = ( ! IsNull( pSfrColl) && pSfrColl->IsValid() && + ! IsNull( pSfrSearchCorners) && pSfrSearchCorners->IsValid()) ; + if ( bSfrCorner) { + PtrOwner pSfrCorner( GetSfrCornerColl( pSfr, pSfrLimit, pSfrColl, pSfrSearchCorners)) ; + if ( ! IsNull( pSfrCorner) && pSfrCorner->IsValid()) { + it->pSfrCorn = CreateSurfFlatRegion() ; + it->pSfrCorn->CopyFrom( pSfrCorner) ; + } + } + #if ENABLE_DEBUG_SFR DrawLoopsSurf( pSfr, false, Color( .0, 1., 0., .5), it->bSubStep, ToString( it->dDepth)) ; #endif @@ -2035,7 +2094,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) int nNew_SfrLimit_Id = GDB_ID_NULL ; if ( ! IsNull( vInfoSfrGeomDB[i].pSfrLimit) && vInfoSfrGeomDB[i].pSfrLimit->IsValid()) { #if ENABLE_DEBUG_SFR - DrawLoopsSurf( vInfoSfrGeomDB[i].pSfrLimit, true, Color( .5, .5, .5, .5), vInfoSfrGeomDB[i].bSubStep, ToString( dDepth)) ; + DrawLoopsSurf( vInfoSfrGeomDB[i].pSfrLimit, true, Color( .5, .5, .5, .5), vInfoSfrGeomDB[i].bSubStep, ToString( vInfoSfrGeomDB[i].dDepth)) ; #endif nNew_SfrLimit_Id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nTempId, Release( vInfoSfrGeomDB[i].pSfrLimit)) ; if ( nNew_SfrLimit_Id == GDB_ID_NULL) { @@ -2260,6 +2319,278 @@ SurfRoughing::GetStmOutSideSfr( const ISurfFlatRegion* pSfr, double dDepth, cons return ( bOk ? Release( pStmLimit) : nullptr) ; } +//---------------------------------------------------------------------------- +bool +SurfRoughing::GetToolCollisionRegion( const ISurfFlatRegion* pSfrSgro, double& dDepth, + ISurfFlatRegion* pSfrColl, ISurfFlatRegion* pSfrSearchCorners) const +{ + // la collisione viene calcolata mediante tavola e ventose + + // se la superficie di sgrossatura non è valida, non faccio nulla + if ( pSfrSgro == nullptr || ! pSfrSgro->IsValid()) + return false ; + // le supercici risultante deve essere vuota + if ( pSfrColl == nullptr || pSfrSearchCorners == nullptr) + return false ; + pSfrColl->Clear() ; + pSfrSearchCorners->Clear() ; + + // dalla superficie definisco il riferimento locale ( vista come ZTool) + Frame3d frLoc ; + Point3d ptCen ; pSfrSgro->GetCentroid( ptCen) ; + if ( ! frLoc.Set( ptCen, pSfrSgro->GetNormVersor())) + return false ; + + // definisco la distanza di sicurezza + double const SAFE_TOL = 5. * EPS_SMALL ; + + // --- tavola + BBox3d b3Area ; // z = 0 + if ( m_pMchMgr->GetTableArea( 1, b3Area) && ! b3Area.IsEmpty()) { + // caso sgrossatura in Z + if ( AreSameVectorApprox( pSfrSgro->GetNormVersor(), Z_AX)) { + // controllo se limitare la Depth della tavola + double dTabDist = abs( ( ptCen - b3Area.GetMax()) * pSfrSgro->GetNormVersor()) ; + if ( dDepth > dTabDist - DIST_TABLE) { + dDepth = dTabDist - DIST_TABLE ; + string sWarn = "Warning in SurfRoughing : Depth reduced at " + ToString( dDepth, 3) ; + m_pMchMgr->SetWarning( 3057, sWarn) ; + } + } + // se orientamento diverso dalla tavola + else { + // recupero la TriMesh di espansione per evitare collisioni + double dTmpTabThick = 0.1 * ( min( b3Area.GetDimX(), b3Area.GetDimY())) ; + b3Area.Expand( SAFE_TOL, SAFE_TOL, 0.) ; + PtrOwner pCompoTab( CreateCurveComposite()) ; + if ( IsNull( pCompoTab)) + return false ; + pCompoTab->AddPoint( b3Area.GetMin()) ; + pCompoTab->AddLine( b3Area.GetMin() + X_AX * b3Area.GetDimX()) ; + pCompoTab->AddLine( b3Area.GetMax() - Z_AX * b3Area.GetDimZ()) ; + pCompoTab->AddLine( b3Area.GetMin() + Y_AX * b3Area.GetDimY()) ; + pCompoTab->Close() ; + pCompoTab->Translate( - Z_AX * ( dTmpTabThick + SAFE_TOL)) ; + #if ENABLE_DEBUG_SFR_COLLISION + ICurveComposite* _pCompoBox = CloneCurveComposite( pCompoTab) ; + _pCompoBox->SetExtrusion( Z_AX) ; + _pCompoBox->SetThickness( dTmpTabThick + 2. * SAFE_TOL) ; + int _nTbId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pCompoBox) ; + m_pGeomDB->SetMaterial( _nTbId, RED) ; + #endif + CICURVEPVECTOR vpCrvs ; + vpCrvs.emplace_back( pCompoTab) ; + PtrOwner pStmCollTab( GetSurfTriMeshByRegionExtrusion( vpCrvs, Z_AX * ( dTmpTabThick + 2. * SAFE_TOL))) ; + if ( IsNull( pStmCollTab) || ! pStmCollTab->IsValid() || pStmCollTab->GetTriangleCount() == 0) + return false ; + // recupero la sua proiezione nel piano di sgrossatura come regione piana + Plane3d plProj ; + if ( ! plProj.Set( frLoc.Orig() - dDepth * frLoc.VersZ(), frLoc.VersZ())) + return false ; + POLYLINEVECTOR vPL ; + if ( ! pStmCollTab->GetSilhouette( plProj, EPS_SMALL, vPL)) // proiezione di 6 triangoli, veloce + return false ; + // se completamente dietro al piano, non influenza la sgrossatura attuale + if ( ! vPL.empty()) { + SurfFlatRegionByContours SfrByC ; + for ( const PolyLine& PL : vPL) { + PtrOwner pCompoLoop( CreateCurveComposite()) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->FromPolyLine( PL) || + ! SfrByC.AddCurve( Release( pCompoLoop))) + return false ; + } + PtrOwner pSfrTabColl( SfrByC.GetSurf()) ; + if ( IsNull( pSfrTabColl) || ! pSfrTabColl->IsValid()) + return false ; + // aggiorno la regione di collissione per l'utensile + if ( ! pSfrColl->CopyFrom( pSfrTabColl)) + return false ; + if ( AreOppositeVectorApprox( pSfrColl->GetNormVersor(), frLoc.VersZ())) + pSfrColl->Invert() ; + #if ENABLE_DEBUG_SFR_COLLISION + ISurfFlatRegion* _pSfrTab = CreateSurfFlatRegion() ; + _pSfrTab->CopyFrom( pSfrColl) ; + int _nSrfTbId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pSfrTab) ; + m_pGeomDB->SetMaterial( _nSrfTbId, Color( 255, 0, 0, 50)) ; + #endif + } + } + } + + // --- ventose + INTVECTOR vFxtId ; + int nFxtId = m_pMchMgr->GetFirstFixture() ; + while ( nFxtId != GDB_ID_NULL) { + vFxtId.emplace_back( nFxtId) ; + nFxtId = m_pMchMgr->GetNextFixture( nFxtId) ; + } + for ( const int& nFxtId : vFxtId) { + // recupero il Box della ventosa + BBox3d bFxtBox ; + if ( m_pGeomDB->GetGlobalBBox( nFxtId, bFxtBox) && ! bFxtBox.IsEmpty()) { + // espando il Box per evitare la collisione con l'utensile + bFxtBox.Expand( SAFE_TOL) ; + #if ENABLE_DEBUG_SFR_COLLISION + ICurveComposite* _pCompoFxt = CreateCurveComposite() ; + _pCompoFxt->AddPoint( bFxtBox.GetMin()) ; + _pCompoFxt->AddLine( bFxtBox.GetMin() + X_AX * bFxtBox.GetDimX()) ; + _pCompoFxt->AddLine( bFxtBox.GetMax() - Z_AX * bFxtBox.GetDimZ()) ; + _pCompoFxt->AddLine( bFxtBox.GetMin() + Y_AX * bFxtBox.GetDimY()) ; + _pCompoFxt->Close() ; + _pCompoFxt->SetExtrusion( Z_AX) ; + _pCompoFxt->SetThickness( bFxtBox.GetDimZ()) ; + int nFxtId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pCompoFxt) ; + m_pGeomDB->SetMaterial( nFxtId, YELLOW) ; + #endif + // recupero la TriMesh del Box + PtrOwner pCompoFxt( CreateCurveComposite()) ; + if ( IsNull( pCompoFxt)) + return false ; + pCompoFxt->AddPoint( bFxtBox.GetMin()) ; + pCompoFxt->AddLine( bFxtBox.GetMin() + X_AX * bFxtBox.GetDimX()) ; + pCompoFxt->AddLine( bFxtBox.GetMax() - Z_AX * bFxtBox.GetDimZ()) ; + pCompoFxt->AddLine( bFxtBox.GetMin() + Y_AX * bFxtBox.GetDimY()) ; + pCompoFxt->Close() ; + CICURVEPVECTOR vpCrvs ; + vpCrvs.emplace_back( pCompoFxt) ; + PtrOwner pStmCollFxt( GetSurfTriMeshByRegionExtrusion( vpCrvs, Z_AX * bFxtBox.GetDimZ())) ; + if ( IsNull( pStmCollFxt) || ! pStmCollFxt->IsValid() || pStmCollFxt->GetTriangleCount() == 0) + return false ; + // recupero la sua proiezione nel piano di sgrossatura come regione piana + Plane3d plProj ; + if ( ! plProj.Set( frLoc.Orig() - dDepth * frLoc.VersZ(), frLoc.VersZ())) + return false ; + POLYLINEVECTOR vPL ; + if ( ! pStmCollFxt->GetSilhouette( plProj, EPS_SMALL, vPL)) // proiezione di 6 triangoli, veloce + return false ; + // se completamente dietro al piano, non influenza la sgrossatura attuale + if ( vPL.empty()) + continue ; + SurfFlatRegionByContours SfrByC ; + for ( const PolyLine& PL : vPL) { + PtrOwner pCompoLoop( CreateCurveComposite()) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->FromPolyLine( PL) || + ! SfrByC.AddCurve( Release( pCompoLoop))) + return false ; + } + PtrOwner pSfrFxtColl( SfrByC.GetSurf()) ; + if ( IsNull( pSfrFxtColl) || ! pSfrFxtColl->IsValid()) + return false ; + if ( AreOppositeVectorApprox( pSfrFxtColl->GetNormVersor(), frLoc.VersZ())) + pSfrFxtColl->Invert() ; + // aggiorno la regione di collissione per l'utensile + if ( ! pSfrColl->IsValid()) { + if ( ! pSfrColl->CopyFrom( pSfrFxtColl)) + return false ; + } + else { + if ( ! pSfrColl->Add( *pSfrFxtColl)) + return false ; + } + #if ENABLE_DEBUG_SFR_COLLISION + ISurfFlatRegion* _pSfrFxt = CreateSurfFlatRegion() ; + _pSfrFxt->CopyFrom( pSfrFxtColl) ; + int _nSfrFxtId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pSfrFxt) ; + m_pGeomDB->SetMaterial( _nSfrFxtId, Color( 255, 255, 0, 50)) ; + #endif + } + } + + // se ho una regione di collisione valida + if ( pSfrColl->IsValid()) { + PtrOwner pSfrBlock( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrBlock)) + return false ; + // scorro le curve della regione di sgrossatura e definisco delle superfici di blocco + for ( int nC = 0 ; nC < pSfrSgro->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrSgro->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfrSgro->GetLoop( nC, nL))) ; + if ( ! IsNull( pCompoLoop) && pCompoLoop->IsValid()) { + pCompoLoop->Translate( - pSfrSgro->GetNormVersor() * dDepth) ; + for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) { + const ICurve* pSubCrvLoop = pCompoLoop->GetCurve( nU) ; + if ( pSubCrvLoop == nullptr || ! pSubCrvLoop->IsValid()) + return false ; + CRVCVECTOR ccClass ; + if ( ! pSfrColl->GetCurveClassification( *pSubCrvLoop, EPS_SMALL, ccClass)) + return false ; + bool bBlock = false ; + for ( int i = 0 ; ! bBlock && i < ssize( ccClass) ; ++ i) { + if ( ccClass[i].nClass == CRVC_OUT) + continue ; + PtrOwner pCrvColl( pSubCrvLoop->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ; + if ( IsNull( pCrvColl) || ! pCrvColl->IsValid()) + continue ; + double dLen = 0. ; + pCrvColl->GetLength( dLen) ; + bBlock = ( dLen > 2. * SAFE_TOL) ; + } + if ( bBlock) { + PtrOwner pCompoBlock( CreateCurveComposite()) ; + if ( IsNull( pCompoBlock)) + return false ; + pCompoBlock->AddCurve( pSubCrvLoop->Clone()) ; + pCompoBlock->SetExtrusion( pSfrSgro->GetNormVersor()) ; + OffsetCurve OffsCrv ; // ... rappresentativo + OffsCrv.Make( pCompoBlock, m_TParams.m_dDiam, ICurve::OFF_FILLET) ; + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid()) + return false ; + pCompoBlock->Invert() ; + Point3d ptA ; pCrvOffs->GetStartPoint( ptA) ; + Point3d ptC ; pCompoBlock->GetStartPoint( ptC) ; + pCompoBlock->AddLine( ptA) ; + pCompoBlock->AddCurve( Release( pCrvOffs)) ; + pCompoBlock->AddLine( ptC) ; + #if ENABLE_DEBUG_SFR_COLLISION + int _nCrvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoBlock->Clone()) ; + m_pGeomDB->SetMaterial( _nCrvId, PURPLE) ; + #endif + PtrOwner pSfrCurrBlock( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrCurrBlock)) + return false ; + if ( ! pSfrCurrBlock->AddExtLoop( Release( pCompoBlock))) + return false ; + if ( ! pSfrBlock->IsValid()) { + if ( ! pSfrBlock.Set( Release( pSfrCurrBlock))) + return false ; + } + else { + if ( ! pSfrBlock->Add( *pSfrCurrBlock)) + return false ; + } + } + } + } + } + } + + // determino la superficie di collisione + pSfrColl->Clear() ; + pSfrColl->CopyFrom( pSfrBlock) ; + // per essere sufficientemente distanti + pSfrColl->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ; + // riporto la superficie alla stessa quota della regione di sgrossatura + pSfrColl->Translate( pSfrSgro->GetNormVersor() * dDepth) ; + + // determino la superficie di ricerca per la pulizia dei corners + pSfrSearchCorners->Clear() ; + pSfrSearchCorners->CopyFrom( pSfrColl) ; + pSfrSearchCorners->Offset( m_TParams.m_dDiam + TOL_OFFS_CORNER_COLL, ICurve::OFF_FILLET) ; + if ( ! pSfrSearchCorners->Intersect( *pSfrSgro)) + return false ; + } + + #if ENABLE_DEBUG_SFR_COLLISION + int _nSfrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrColl->Clone()) ; + m_pGeomDB->SetMaterial( _nSfrId, Color( 128, 0, 128, 50)) ; + _nSfrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSearchCorners->Clone()) ; + m_pGeomDB->SetMaterial( _nSfrId, Color( 128, 128, 0, 50)) ; + #endif + + return true ; +} + //---------------------------------------------------------------------------- ISurfFlatRegion* SurfRoughing::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs) const @@ -2381,6 +2712,146 @@ SurfRoughing::GetSfrSilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dD return ( SfrMaker.GetSurf()) ; } +//---------------------------------------------------------------------------- +ISurfFlatRegion* +SurfRoughing::GetSfrCornerColl( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrLimit, + const ISurfFlatRegion* pSfrColl, const ISurfFlatRegion* pSfrSearchCorners) const +{ + /* + se ho la presenza di tavole o ventose, la superficie di collissione ricavata genera dei nuovi + lati chiusi nella geometria attuale ( pSfr deve già avere impostati i lati OPEN/CLOSE) + i nuovi lati chiusi possono generare regioni i cui spigoli non si possono svuotare ( nei punti + di unione dei lati aperti originali con i nuovi chiusi). + questa funzione aggiunge delle piccole parti di regione in questi punti, evitando quindi la presenza + di colonne di materiale non rimosso + NB. questa parti non riguardano nè le regioni nons vuotate, nè le regioni si silhouette ipotetica + */ + + // se la superficie di collissione non è valida non faccio nulla + if ( pSfrColl == nullptr || ! pSfrColl->IsValid() || + pSfrSearchCorners == nullptr || ! pSfrSearchCorners->IsValid()) + return nullptr ; + if ( pSfr == nullptr) + return nullptr ; + + #if ENABLE_DEBUG_REMOVED_REGION + int _nIdSfrSearch = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSearchCorners->Clone()) ; + m_pGeomDB->SetMaterial( _nIdSfrSearch, YELLOW) ; + int _nIdSfrLimit = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrLimit->Clone()) ; + m_pGeomDB->SetMaterial( _nIdSfrLimit, GRAY) ; + DrawLoopsSurf( pSfr, false, Color( 0., 1., 0.), false, "") ; + #endif + + // recupero tutti i lati aperti della superficie attuale + ICURVEPOVECTOR vCrvOpenInSearch ; + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return nullptr ; + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCompoLoop, vpCrvs) ; + for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + CRVCVECTOR ccClass ; + if ( ! pSfrSearchCorners->GetCurveClassification( *vpCrvs[i], EPS_SMALL, ccClass)) + return nullptr ; + for ( int j = 0 ; j < ssize( ccClass) ; ++ j) { + if ( ccClass[j].nClass != CRVC_OUT) { + PtrOwner pCrvIn( vpCrvs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + if ( ! IsNull( pCrvIn) && pCrvIn->IsValid()) { + if ( ! vCrvOpenInSearch.emplace_back( Release( pCrvIn))) + return nullptr ; + } + } + } + } + } + } + } + + #if ENABLE_DEBUG_REMOVED_REGION + for ( int _i = 0 ; _i < ssize( vCrvOpenInSearch) ; ++ _i) { + int _nIdCrvOpen = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvOpenInSearch[_i]->Clone()) ; + m_pGeomDB->SetMaterial( _nIdCrvOpen, ORANGE) ; + } + #endif + + // determino la regione complessiva di ricerca + PtrOwner pSfrExtra( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrExtra)) + return nullptr ; + double dOffs = m_TParams.m_dDiam + 50. * EPS_SMALL ; // deve passare l'utensile per tale regione + for ( int i = 0 ; i < ssize( vCrvOpenInSearch) ; ++ i) { + // recupero la curva come composita + PtrOwner pCrvCompo( ConvertCurveToComposite( vCrvOpenInSearch[i]->Clone())) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->IsValid()) + return nullptr ; + // calcolo il semi-offset + pCrvCompo->SetExtrusion( pSfr->GetNormVersor()) ; + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pCrvCompo, dOffs / 2., ICurve::OFF_FILLET)) + return nullptr ; + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid()) + return nullptr ; + // determino la regione da aggiungere + if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid()) + pSfrExtra.Set( GetSurfFlatRegionFromFatCurve( pCrvOffs->Clone(), dOffs / 2. + 50. * EPS_SMALL, false, false)) ; + else { + PtrOwner pSfrToAdd( GetSurfFlatRegionFromFatCurve( pCrvOffs->Clone(), dOffs / 2 + 50. * EPS_SMALL, false, false)) ; + if ( IsNull( pSfrToAdd) || ! pSfrToAdd->IsValid()) + return nullptr ; + pSfrExtra->Add( *pSfrToAdd) ; + } + if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid()) + return nullptr ; + } + if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid()) + return nullptr ; + if ( ! pSfrExtra->Intersect( *pSfrSearchCorners)) + return nullptr ; + // rimuovo i Chunk che non sono attaccati alle curve aperte ricavate + for ( int nC = 0 ; nC < pSfrExtra->GetChunkCount() ; ++ nC) { + PtrOwner pSfrExtraChunk( pSfrExtra->CloneChunk( nC)) ; + if ( IsNull( pSfrExtraChunk) || ! pSfrExtraChunk->IsValid()) + return nullptr ; + bool bSave = false ; + for ( int i = 0 ; ! bSave && i < ssize( vCrvOpenInSearch) ; ++ i) { + CRVCVECTOR ccClass ; + if ( pSfrExtraChunk->GetCurveClassification( *vCrvOpenInSearch[i], 10. * EPS_SMALL, ccClass)) { + for ( int j = 0 ; ! bSave && j < ssize( ccClass) ; ++ j) + bSave = ( ccClass[j].nClass != CRVC_OUT) ; + } + } + if ( ! bSave) { + pSfrExtra->EraseChunk( nC) ; + -- nC ; + } + } + + // se superficie non valida, ho finito + if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid()) + return nullptr ; + + // rimuovo la regione da non rovinare, ho esteso i lati aperti mediante Offset semplice, + // devo controllare di non rovinare altre regioni + // regolarizzo la superficie + pSfrExtra->Offset( - m_TParams.m_dDiam / 8., ICurve::OFF_FILLET) ; + pSfrExtra->Offset( m_TParams.m_dDiam / 8., ICurve::OFF_FILLET) ; + if ( ! pSfrExtra->Subtract( *pSfrLimit)) + return nullptr ; + #if ENABLE_DEBUG_REMOVED_REGION + int _nIdExtraSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrExtra->Clone()) ; + m_pGeomDB->SetMaterial( _nIdExtraSfr, FUCHSIA) ; + #endif + + // bisogna ricalcolare i lati aperti/chiusi in base alle nuove modifica della superficie + + + return ( Release( pSfrExtra)) ; +} + //---------------------------------------------------------------------------- bool SurfRoughing::GetActiveSurfaces( INTVECTOR& vSurfId, INTVECTOR& vSurfSuppId) const @@ -3933,7 +4404,7 @@ SurfRoughing::RemoveChunksUnderTolerance( ISurfFlatRegion* pSfr, double dTol, if ( pSfrToUpdate != nullptr && pSfrToUpdate->IsValid()) { PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; if ( ! IsNull( pSfrChunk) || pSfrChunk->IsValid()) { - pSfrChunk->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; // si prova... + pSfrChunk->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ; // si prova... pSfrToUpdate->Subtract( *pSfrChunk) ; // si prova... } } @@ -4218,7 +4689,7 @@ SurfRoughing::GetRadiusForStartEndElevation( void) const } //---------------------------------------------------------------------------- -bool +bool SurfRoughing::CheckSafetyLinearLink( const Point3d& ptCurr, const Point3d& ptDest, const ISurfFlatRegion* pSfrCheck, const Vector3d& vtTool, bool& bSafe) const { diff --git a/SurfRoughing.h b/SurfRoughing.h index 8433666..7a6c173 100644 --- a/SurfRoughing.h +++ b/SurfRoughing.h @@ -41,13 +41,14 @@ typedef std::vector PATHINFOSRVECTOR ; struct StepInfoSRTmp { StepInfoSRTmp( void) : nIndRef( -1), dDepth( 0), bSubStep( false), bPlaneZStep( false), dPercFeed( 0.), - pSfrRemoved( nullptr), pSfrPlaneZ( nullptr) {} - StepInfoSRTmp( int nIR, double dD, bool bSS, bool bPZ, double dPF, ISurfFlatRegion* pSR, ISurfFlatRegion* pSPZ) + pSfrRemoved( nullptr), pSfrPlaneZ( nullptr), pSfrCorn( nullptr) {} + StepInfoSRTmp( int nIR, double dD, bool bSS, bool bPZ, double dPF, ISurfFlatRegion* pSR, ISurfFlatRegion* pSPZ, ISurfFlatRegion* pSC) : nIndRef( nIR), dDepth( dD), bSubStep( bSS), bPlaneZStep( bPZ), dPercFeed( dPF), - pSfrRemoved( pSR), pSfrPlaneZ( pSPZ) {} + pSfrRemoved( pSR), pSfrPlaneZ( pSPZ), pSfrCorn( pSC) {} ~StepInfoSRTmp() { delete( pSfrRemoved) ; delete( pSfrPlaneZ) ; + delete( pSfrCorn) ; } int nIndRef ; // ( usato solo per step intermedi ) posizione step precedente double dDepth ; // profondità posizione piano di svuotatura ( in negativo) @@ -56,6 +57,7 @@ struct StepInfoSRTmp { double dPercFeed ; // percentuale degli extra steps relativa agli step base ( per Feed ZLoc) ISurfFlatRegion* pSfrRemoved ; // regione PROGRESSIVA rimossa attuale ISurfFlatRegion* pSfrPlaneZ ; // regione individuata da PlaneZDetection + ISurfFlatRegion* pSfrCorn ; // regione non svutata per presenza di lati chiusi definiti da tavola/ventose } ; // vettore associato typedef std::vector STEPINFOTMPSRVECTOR ; @@ -209,6 +211,10 @@ class SurfRoughing : public Machining ISurfTriMesh* GetStmOutSideSfr( const ISurfFlatRegion* pSfr, double dDepth, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const ; ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) const ; ISurfFlatRegion* GetSfrSilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dDepth, double Sil_tol, bool& bOk) const ; + ISurfFlatRegion* GetSfrCornerColl( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrLimit, + const ISurfFlatRegion* pSfrColl, const ISurfFlatRegion* pSfrSearchCorners) const ; + bool GetToolCollisionRegion( const ISurfFlatRegion* pSfrSgro, double& dDepth, ISurfFlatRegion* pSfrColl, + ISurfFlatRegion* pSfrSearchCorners) const ; bool GetActiveSurfaces( INTVECTOR& vSurfId, INTVECTOR& vSurfSuppId) const ; double GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) const ; double GetRadiusForStartEndElevation( void) const ;