diff --git a/SurfRoughing.cpp b/SurfRoughing.cpp index 4fb4751..47c4c23 100644 --- a/SurfRoughing.cpp +++ b/SurfRoughing.cpp @@ -75,11 +75,16 @@ using namespace std ; // 3026 = "Error in SurfRoughing : Detecting open edges failed" // 3027 = "Error in SurfRoughing : Slicing Raw failed" // 3028 = "Error in SurfRoughing : Error in CalcPocketing" +// 3029 = "Error in SurfRoughing : Simplify Chunks for SubSteps failed" // 3051 = "Warning in SurfRoughing : Skipped entity (xx)" // 3052 = "Warning in SurfRoughing : No machinable path" // 3053 = "Warning in SurfRoughing : Tool name changed (xx)" // 3054 = "Warning in SurfRoughing : Tool data changed (xx)" +//---------------------------------------------------------------------------- +static string KEY_SURF_POCK = "SurfPock_" ; +static string KEY_SURF_LIMIT = "SurfLimit_" ; + //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_SURFROUGHING), SurfRoughing) ; @@ -227,6 +232,7 @@ SurfRoughing::SurfRoughing( void) m_nStatus = MCH_ST_TO_VERIFY ; m_nPaths = 0 ; m_dMaxHelixRad = INFINITO ; + m_dSubStepToler = 2000 * EPS_SMALL ; // proporzionale al raggio utensile o come parametro ??? } //---------------------------------------------------------------------------- @@ -1241,8 +1247,8 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) if ( IsNull( pCavParSilh) || ! pCavParSilh->SetData( vpStm, frPlanes, SILH_TOL)) return false ; - // calcolo le regioni di svuotatura alle varie quote come differenza tra regioni da lavorare e regioni di silhouette - INTVECTOR vPocket ; + // vettore Id salvati nel gruppo Temp + INTINTVECTOR vPocket ; // definisco la dimensione dello step ( base ) e il numero di passate double dOkStep = min( m_Params.m_dStep, m_TParams.m_dMaxMat + EPS_SMALL) ; @@ -1315,6 +1321,7 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) // creo la regione piana di confronto // su tutti gli step ricavati, calcolo le PolyLine delle Silhouette + int nPocket = 0 ; // numero effettivo di Pocketing calcolate for ( auto it = vStepInfo.begin() ; it != vStepInfo.end() ; ++ it) { /* ******************** Regione estesa di lavoro ******************** */ @@ -1366,7 +1373,6 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) } if ( ! pSfr->IsValid() || pSfr->GetChunkCount() == 0) // se superficie non valida continue ; // passo allo step successivo ( la silhouette coincide con il grezzo ) - // salvo la superficie rimossa ( it->second).pSfrRemoved = pSfr->Clone() ; @@ -1400,12 +1406,31 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) // se regione risultante non vuota if ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) { + // se si tratta di un SottoStep, rimuovo tutti i chunk troppo snelli + if ( ( it->second).bSubStep) { + if ( ! RemoveChunksUnderTolerance( pSfr)) { + m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ; + return false ; + } + // se dopo la semplificazione non rimane nulla, allora passo allo step successivo + if ( ! pSfr->IsValid() || pSfr->GetChunkCount() == 0) + continue ; + } + // determino i lati aperti ( mediante vicinanza dei tratti di curva al volume progressivo non svuotato) if ( ! ChooseCloseOrOpenEdge( pSfr, pSfrOpenClose)) { m_pMchMgr->SetLastError( 3026, "Error in SurfRoughing : Detecting open edges failed") ; return false ; } + // se si tratta di un SottoStep, chiudo tutti i lati aperti troppo corti + if ( ( it->second).bSubStep) { + if ( ! CloseOpenEdgesUnderTolerance( pSfr, m_TParams.m_dDiam - 200 * EPS_SMALL)) { + m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ; + return false ; + } + } + // salvo nella temp Prop della FlatRegion se si tratta di uno step base o intermedio // Step Base -> 0 | Step intermedio -> 1 pSfr->SetTempProp( ( it->second).bSubStep ? 1 : 0, 0) ; @@ -1414,12 +1439,29 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) pSfr->SetTempParam( ( it->second).dDepth, 0) ; // la salvo nel gruppo temporaneo - int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nTempId, Release( pSfr)) ; - if ( nNewId == GDB_ID_NULL) { + int nNew_SfrPock_Id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nTempId, Release( pSfr)) ; + if ( nNew_SfrPock_Id == GDB_ID_NULL) { m_pMchMgr->SetLastError( 3024, "Error in SurfRoughing : region not computable") ; return false ; } - vPocket.emplace_back( nNewId) ; + m_pGeomDB->SetMaterial( nNew_SfrPock_Id, GREEN) ; + m_pGeomDB->SetName( nNew_SfrPock_Id, KEY_SURF_POCK + ToString( nPocket)) ; + + // nel gruppo temporaneo salvo anche la Shilouette ( per superficie Limite) + int nNew_SfrLimit_Id = GDB_ID_NULL ; + if ( ! IsNull( pSfrSil) && pSfrSil->IsValid()) { + nNew_SfrLimit_Id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nTempId, Release( pSfrSil)) ; + if ( nNew_SfrLimit_Id == GDB_ID_NULL) { + m_pMchMgr->SetLastError( 3024, "Error in SurfRoughing : region not computable") ; + return false ; + } + m_pGeomDB->SetMaterial( nNew_SfrLimit_Id, ORANGE) ; + m_pGeomDB->SetName( nNew_SfrLimit_Id, KEY_SURF_LIMIT + ToString( nPocket)) ; + } + + ++ nPocket ; + vPocket.emplace_back( make_pair( nNew_SfrPock_Id, nNew_SfrLimit_Id)) ; + } } @@ -1625,7 +1667,7 @@ SurfRoughing::GetActiveSurfaces( INTVECTOR& vSurfId) const //---------------------------------------------------------------------------- bool -SurfRoughing::AddPocket( const INTVECTOR& vPocket, const Vector3d& vtTool, const Vector3d& vtExtr, +SurfRoughing::AddPocket( const INTINTVECTOR& vPocket, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dStep, bool bSplitArcs) { // recupero distanze di sicurezza @@ -1637,34 +1679,42 @@ SurfRoughing::AddPocket( const INTVECTOR& vPocket, const Vector3d& vtTool, const // ciclo sulle regioni bool bStart = true ; - for ( int nPockId : vPocket) { + for ( auto& vId : vPocket) { - // recupero la superficie da lavorare - const ISurfFlatRegion* pSfr = GetSurfFlatRegion( m_pGeomDB->GetGeoObj( nPockId)) ; + // recupero la superficie da lavorare ( è il primo indice ) + const ISurfFlatRegion* pSfrPock = GetSurfFlatRegion( m_pGeomDB->GetGeoObj( vId.first)) ; // controllo se la regione è relativa ad uno step base o ad uno step intermedio - bool bIsSubStep = ( pSfr->GetTempProp( 0) == 1) ; + bool bIsSubStep = ( pSfrPock->GetTempProp( 0) == 1) ; + // recupero la superficie limite se presente + PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; + if ( vId.second != GDB_ID_NULL) { + const ISurfFlatRegion* pSfrL = GetSurfFlatRegion( m_pGeomDB->GetGeoObj( vId.second)) ; + if ( pSfrL == nullptr) + return false ; + pSfrLimit.Set( pSfrL->Clone()) ; + } // se il tipo è SPIRAL_OUT e sto gestendo uno step intermedio, lo lavoro come SPIRAL_IN if ( nSubType == SURFROU_SUB_SPIRALOUT && bIsSubStep) nSubType = SURFROU_SUB_SPIRALIN ; ICRVCOMPOPOVECTOR vpCrvs ; // percorso di svuotatura // se si tratta di uno step base, allora lavoro l'intera superficie - if ( ! CalcPocketing( pSfr, m_TParams.m_dDiam / 2, 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, - nSubType, true, vpCrvs)) { + if ( ! CalcPocketing( pSfrPock, m_TParams.m_dDiam / 2, 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, + nSubType, true, pSfrLimit, vpCrvs)) { m_pMchMgr->SetLastError( 3028, "Error in SurfRoughing : Error in CalcPocketing") ; return false ; } // recupero la Depth della regione - double dDepth = pSfr->GetTempParam( 0) ; + double dDepth = pSfrPock->GetTempParam( 0) ; // sistemo gli archi per massimo angolo al centro for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) VerifyArcs( vpCrvs[i]) ; // salvo i loop esterni della superficie corrente come Polylinee ( per LeadIn/LeadOut) - ICURVEPOVECTOR vLoops ; vLoops.resize( pSfr->GetChunkCount()) ; + ICURVEPOVECTOR vLoops ; vLoops.resize( pSfrPock->GetChunkCount()) ; for ( int c = 0 ; c < int( vLoops.size()) ; ++ c) - vLoops[c].Set( pSfr->GetLoop( c, 0)) ; + vLoops[c].Set( pSfrPock->GetLoop( c, 0)) ; // ciclo sui percorsi for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) { @@ -1738,7 +1788,7 @@ SurfRoughing::AddPocket( const INTVECTOR& vPocket, const Vector3d& vtTool, const nInd = idx ; } } - PtrOwner pCompo( ConvertCurveToComposite( pSfr->GetLoop( nInd, 0))) ; + PtrOwner pCompo( ConvertCurveToComposite( pSfrPock->GetLoop( nInd, 0))) ; if ( IsNull( pCompo)) return false ; if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, @@ -2238,7 +2288,191 @@ SurfRoughing::SimplyfySfr( ISurfFlatRegion* pSfr) const //---------------------------------------------------------------------------- bool -SurfRoughing::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrRef) +SurfRoughing::RemoveChunksUnderTolerance( ISurfFlatRegion* pSfr) const +{ + /* + quando si lavorano dei SubSteps, può capitare che la superfice da rimuovere sia molto snella; + questo succede quando lo step eseguito in precedenza rimuove gran parte del materiale utile per il + piano di lavoro attuale. Si creano dunque delle regioni formate da più Chunk molto sottili che + creano sia problemi di distinzione dei lati aperti che problemi poi ad essere svuotate ( si pensi + all'estensione dei lati aperti e al loro raccordo con i chiusi, oltre al fatto che i chunk in + questa operazione potrebbero mergiarsi tra loro creando ambiguità. + Data la superficie *pSfr, vengono rimossi tutti i Chunks che si annullano mediante il contro-Offset + definito dalla tolleranza + NB. Il Contro-Offset è possibile farlo solo sul Loop esterno, non c'è bisogno di + fare conti aggiuntivi per le isole interne + */ + + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + if ( m_dSubStepToler < EPS_SMALL) // se tolleranza non presente, non faccio nulla + return true ; + + // inizializzo la superficie da restituire + PtrOwner pSfrBeauty( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrBeauty)) + return false ; + + // scorro tutti i chunk della superficie + bool bSameSurf = true ; + for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++ c) { + // recupero il loop esterno + PtrOwner pCrvExtLoop( pSfr->GetLoop( c, 0)) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) + return false ; + // effettuo l'offset della tolleranza richiesta + OffsetCurve OffsCrv ; + if ( OffsCrv.Make( pCrvExtLoop, - m_dSubStepToler, ICurve::OFF_FILLET)) { + // recupero la curva di Offset + PtrOwner pCrvOffs( ConvertCurveToComposite( OffsCrv.GetLongerCurve())) ; + if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) { + // se valida, allora conservo il chunk + // inserisco la curva esterna + if ( ! pSfrBeauty->AddExtLoop( Release( pCrvExtLoop))) + return false ; + // inserisco le isole del Chunk corrente + for ( int l = 1 ; l < pSfr->GetLoopCount( c) ; ++ l) { + PtrOwner pCrvIsl( pSfr->GetLoop( c, l)) ; + if ( IsNull( pCrvIsl) || + ! pCrvIsl->IsValid() || + ! pSfrBeauty->AddIntLoop( *pCrvIsl)) + return false ; + } + continue ; // passo al Chunk successico + } + } + bSameSurf = false ; + } + + // se ho fatto modifiche, sostituisco la superficie con quella nuova + if ( ! bSameSurf) + pSfr->CopyFrom( pSfrBeauty) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfRoughing::CloseOpenEdgesUnderTolerance( ISurfFlatRegion* pSfr, double dToler) +{ + /* + Nei SubSteps capita spesso che ci siano dei lati aperti molto piccoli o delle sequenze di lati + Aperti-Chiusi alternati tutti molto corti ( es. Laurana50K). + Chiudo tutti i lati aperti piccoli + */ + + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + if ( dToler < 10 * EPS_SMALL) // se tolleranza non presente, non faccio nulla + return true ; + + // inizializzo la superficie da restituire + PtrOwner pSfrRegular( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrRegular)) + return false ; + + // scorro tutti i chunk della superficie + for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++ c) { + // scorro tutti i loop + for ( int l = 0 ; l < pSfr->GetLoopCount( c) ; ++ l) { + // recupero il loop come curva composita + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // ------------- ricavo tratti di proprietà uniformi ------------- + ICRVCOMPOPOVECTOR vpCrvs ; // vettore tratti aperti e chiusi alternati tra gli indici + int nCurrTempProp ; + int nParStart = 0 ; + for ( int i = 0 ; i < pCrvLoop->GetCurveCount() ; ++ i) { // per ogni curva del loop + int nTempProp ; + pCrvLoop->GetCurveTempProp( i, nTempProp) ; + if ( i == 0) { + nCurrTempProp = nTempProp ; + nParStart = i ; + } + else if ( nCurrTempProp != nTempProp) { // se TempProp0 differente dalla curva precedente + // ricavo il tratto di curva + PtrOwner pCrv( ConvertCurveToComposite( pCrvLoop->CopyParamRange( nParStart, i))) ; + if ( IsNull( pCrv)) + return false ; + pCrv->SetTempProp( nCurrTempProp) ; + vpCrvs.emplace_back( Release( pCrv)) ; + nCurrTempProp = nTempProp ; + nParStart = i ; + } + } + // ultima curva ( se esiste) + if ( nParStart < pCrvLoop->GetCurveCount()) { + PtrOwner pCrvLast( ConvertCurveToComposite( pCrvLoop->CopyParamRange( nParStart, pCrvLoop->GetCurveCount()))) ; + if ( IsNull( pCrvLast) || ! pCrvLast->IsValid()) + return false ; + pCrvLast->SetTempProp( nCurrTempProp) ; + if ( vpCrvs.empty()) + vpCrvs.emplace_back( Release( pCrvLast)) ; // la curva originale aveva tutte propietà uniformi + else { + if ( vpCrvs[0]->GetTempProp( 0) == nCurrTempProp) + vpCrvs[0]->AddCurve( Release( pCrvLast), false) ; + else + vpCrvs.emplace_back( Release( pCrvLast)) ; + } + } + // -------------------------------------------------------------------- + + //for ( int u = 0 ; u < int( vpCrvs.size()) ; ++ u) { + // if ( vpCrvs[u]->GetTempProp() == 0) + // DrawSimpleCompleteCurve( vpCrvs[u], AQUA) ; + // else if ( vpCrvs[u]->GetTempProp() == 1) + // DrawSimpleCompleteCurve( vpCrvs[u], ORANGE) ; + // else + // DrawSimpleCompleteCurve( vpCrvs[u], GREEN) ; + //} + + // scorro tutti i tratti aperti e riconcateno il loop + PtrOwner pCrvNewLoop( CreateCurveComposite()) ; + if ( IsNull( pCrvNewLoop)) + return false ; + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == 1 && int( vpCrvs.size()) != 1) { // se tratto aperto e non coincidente a tutta la curva + // semplifico il loop per avere curve più uniformi + SimplifyCurve( vpCrvs[i]) ; + // riporto le proprietà + vpCrvs[i]->SetTempProp( 1) ; + for ( int j = 0 ; j < vpCrvs[i]->GetCurveCount() ; ++ j) + vpCrvs[i]->SetCurveTempProp( j, 1, 0) ; + // controllo la lunghezza delle curve + double dLen = EPS_SMALL ; + vpCrvs[i]->GetLength( dLen) ; + if ( dLen < dToler) { // e più corto della tolleranza + vpCrvs[i]->SetTempProp( 0, 0) ; + for ( int j = 0 ; j < vpCrvs[i]->GetCurveCount() ; ++ j) + vpCrvs[i]->SetCurveTempProp( j, 0, 0) ; + } + } + pCrvNewLoop->AddCurve( Release( vpCrvs[i])) ; + } + + // inserisco i nuovi loop nella superficie regolare + if ( l == 0) { + if ( ! pSfrRegular->AddExtLoop( Release( pCrvNewLoop))) + return false ; + } + else { + if ( ! pSfrRegular->AddIntLoop( Release( pCrvNewLoop))) + return false ; + } + } + } + + // resituisco la superficie + pSfr->CopyFrom( pSfrRegular) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfRoughing::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrRef) const { // controllo parametri : @@ -2254,8 +2488,8 @@ SurfRoughing::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfFlatRegio pSfrRef_Offs->Offset( - 50 * EPS_SMALL, ICurve::OFF_FILLET) ; // per ogni curva dei Loop della FlatRegion vengono presi 4 punti di controllo equidistanti. - // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO NON SONO DENTRO AL GREZZO " ( bOnIsClosed = T) - // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO DISTANO MENO DI 25 * EPS_SMALL DALLE FACCE ( bOnIsClosed = F) + // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO NON SONO DENTRO AL GREZZO " + // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO DISTANO MENO DI 25 * EPS_SMALL DALLE FACCE " const int NUM_POINTS = 4 ; // scorro tutti i loop diff --git a/SurfRoughing.h b/SurfRoughing.h index b145d24..6b643a5 100644 --- a/SurfRoughing.h +++ b/SurfRoughing.h @@ -76,7 +76,7 @@ class SurfRoughing : public Machining bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ; bool Chain( int nGrpDestId) ; bool ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) ; - bool AddPocket( const INTVECTOR& vPocket, const Vector3d& vtTool, const Vector3d& vtExtr, + bool AddPocket( const INTINTVECTOR& vPocket, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dStep, bool bSplitArcs) ; bool AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; bool AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; @@ -96,7 +96,9 @@ class SurfRoughing : public Machining double GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) const ; double GetRadiusForStartEndElevation( void) const ; bool ResetCurveAllTempProp( ICurve* pCurve) const ; - bool ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrRef) ; + bool RemoveChunksUnderTolerance( ISurfFlatRegion* pSfr) const ; + bool CloseOpenEdgesUnderTolerance( ISurfFlatRegion* pSfr, double dToler) ; + bool ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrRef) const ; bool SimplifyCurve( ICurveComposite* pCompo) const ; bool SimplyfySfr( ISurfFlatRegion* pSfr) const ; bool CalcRetCrv( const ICurveComposite* pCompo, const Point3d& ptRef, bool bOutStart, @@ -144,4 +146,5 @@ class SurfRoughing : public Machining int m_nStatus ; // stato di aggiornamento della lavorazione int m_nPaths ; // numero di percorsi di lavoro generati double m_dMaxHelixRad ; // raggio massimo attacco ad elica nel caso di cerchi + double m_dSubStepToler ; // tolleranza di rimozione chunk per SubSteps } ; \ No newline at end of file