From f5a94ee0dde2db58a0934f3bd954010079e642c8 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 18 Dec 2023 13:10:38 +0100 Subject: [PATCH] EgtMachKernel : - lavorazione precedente. Primo test. --- Pocketing.cpp | 482 ++++++++++++++++++++++++++++++++++---------------- Pocketing.h | 15 +- 2 files changed, 330 insertions(+), 167 deletions(-) diff --git a/Pocketing.cpp b/Pocketing.cpp index c8a3e63..6933901 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -2355,7 +2355,12 @@ Pocketing::SliceVolume( const ISurfTriMesh* pStmVol, const ISurfTriMesh* pStm_Pa if ( ! GetCurvesForOptimizedPocketing( pSfrCurr, vCrvOEWithFlags[j-1])) return false ; // modifico la supericie in base alle proprietà di lato aperto/chiuso - if ( ! ModifySurfByOpenEdges( pSfrCurr, pSfrLimit)) + PtrOwner pSfrNoExtension( CloneSurfFlatRegion( pSfrCurr)) ; + if ( IsNull( pSfrNoExtension) || + ! ModifySurfByOpenEdges( pSfrCurr, pSfrLimit)) + return false ; + // controllo se la superficie deriva da una lavorazione precedente + if ( ! GetNewSfrByAnotherPocketing( pSfrCurr, pSfrNoExtension, pStmVol, pSfrLimit)) return false ; // inserisco la superficie nel vettore vSrfSliced.emplace_back( Release( pSfrCurr)) ; @@ -2365,11 +2370,6 @@ Pocketing::SliceVolume( const ISurfTriMesh* pStmVol, const ISurfTriMesh* pStm_Pa vbChangedPrec[j-1] = true ; // ... - // controllo se la superficie deriva da una lavorazione precedente - // ... W.I.P - // ... - // ... - // porto la regione limite nel piano Z = 0 if ( pSfrLimit->IsValid()) pSfrLimit->Translate( -vVtTrasl[j-1]) ; @@ -2379,6 +2379,138 @@ Pocketing::SliceVolume( const ISurfTriMesh* pStmVol, const ISurfTriMesh* pStm_Pa return true ; } +//---------------------------------------------------------------------------- +bool +Pocketing::GetNewSfrByAnotherPocketing( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrNoExtendedByOpenEdges, + const ISurfTriMesh* pStmVol, const ISurfFlatRegion* pSfrLimit) +{ + // se non ho una lavorazione precedente o non ho nulla da svuotare, esco + if ( m_dDiam_Prec < EPS_SMALL || ! pSfrPock->IsValid() || ! pSfrNoExtendedByOpenEdges->IsValid()) + return true ; + + // controllo effettivamente che il nuovo utensile possa svuotare qualcosa nella nuova lavorazione + if ( 0.5 * m_TParams.m_dDiam + GetOffsR() > 0.5 * m_dDiam_Prec + m_dOffsetR_Prec) + return true ; + + int o = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStmVol->Clone()) ; + o = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrPock->Clone()) ; + m_pGeomDB->SetMaterial( o, GREEN) ; + + // effettuo un Offset verso l'interno ( curve esterne che percorre il centro del Tool) + double dInsideOffs = - 0.5 * m_dDiam_Prec - 0.5 * m_dOffsetR_Prec - 5 * EPS_SMALL ; + PtrOwner pSfrToolPath( pSfrPock->CreateOffsetSurf( dInsideOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrToolPath)) { + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + return false ; + } + if ( ! pSfrToolPath->IsValid()) + return true ; + + // effettuo un Offset del raggio del tool precedente per ricavare la regione svuotata in precedenza + double dOutSideOffset = 0.5 * m_dDiam_Prec / 2 + 20 * EPS_SMALL ; + PtrOwner pSfrRemoved( pSfrToolPath->CreateOffsetSurf( dOutSideOffset, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrRemoved)) { + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + return false ; + } + + o = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrRemoved->Clone()) ; + m_pGeomDB->SetMaterial( o, PURPLE) ; + + // definisco la regione vera a propria da svuotare con il tool attuale + PtrOwner pSfrAct( CloneSurfFlatRegion( pSfrNoExtendedByOpenEdges)) ; + if ( IsNull( pSfrAct) || + ! pSfrAct->Subtract( *pSfrRemoved)) + return false ; + + o = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrAct->Clone()) ; + m_pGeomDB->SetMaterial( o, BLACK) ; + + // Questa superficie presenterà diversi Chunks... per ognuno di essi ricavo le properità di lato aperto o chiuso + // NB. Questa supericie non dovrebbe avere isole... + // Posso richiamare la funzione ChooseCloseOrOpenEdge() + // alzo leggermente la supericie per l'ultimi step + pSfrAct->Translate( Z_AX * 50 * EPS_SMALL) ; + if ( ! ChooseCloseOrOpenEdge( pSfrAct, pStmVol)) + return false ; + pSfrAct->Translate( - Z_AX * 50 * EPS_SMALL) ; + // Questa funzione ha modificato le TmpProp dei Loops della pSfrAct e le temp prop sono invertite ; + // I lati con tmp prop = 1 sono chiusi, mentre quelli con tmpProp = 0 sono aperti + + // modifico il Loop esterno di Ogni chunk della regione, estendendolo presso i lati aperti + // creo quindi una nuova superficie con questi Loops + SurfFlatRegionByContours sfrBC ; + for ( int c = 0 ; c < pSfrAct->GetChunkCount() ; ++ c) { + // ricavo il Loop esterno + PtrOwner pCrvEL( ConvertCurveToComposite( pSfrAct->GetLoop( c, 0))) ; + if ( IsNull( pCrvEL) || ! pCrvEL->IsValid()) + return false ; + // inverto le Tmp Props + for ( int u = 0 ; u < pCrvEL->GetCurveCount() ; ++ u) + pCrvEL->SetCurveTempProp( u, pCrvEL->GetCurve( u)->GetTempProp( 0) == 0 ? 1 : 0, 0) ; + // ricavo le isole + ICRVCOMPOPOVECTOR vCrvIsl ; + for ( int l = 1 ; l < pSfrAct->GetLoopCount( c) ; ++ l) + vCrvIsl.emplace_back( ConvertCurveToComposite( pSfrAct->GetLoop( c, l))) ; + // inverto le temp props per le isole trovate + for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) + for ( int u = 0 ; u < vCrvIsl[i]->GetCurveCount() ; ++ u) + vCrvIsl[i]->SetCurveTempProp( u, vCrvIsl[i]->GetCurve( u)->GetTempProp( 0) == 0 ? 1 : 0, 0) ; + // estendo il loop esterno presso i lati nuovi lati aperti + if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, m_TParams.m_dDiam, GetOffsR(), GetSideStep(), pSfrLimit)) { + m_pMchMgr->SetLastError( 2430, "Error in Pocketing : adjust open edges failed") ; + return false ; + } + ICRVCOMPOPOVECTOR vCrvNULL ; + for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) { + if ( ! AdjustContourWithOpenEdges( vCrvIsl[i], vCrvNULL, m_TParams.m_dDiam, GetOffsR(), GetSideStep(), pSfrLimit)) { + m_pMchMgr->SetLastError( 2430, "Error in Pocketing : adjust open edges failed") ; + return false ; + } + } + + + + for ( int u = 0 ; u < pCrvEL->GetCurveCount() ; ++ u) { + int nProp0 ; pCrvEL->GetCurveTempProp( u, nProp0, 0) ; + int nProp1 ; pCrvEL->GetCurveTempProp( u, nProp1, 1) ; + int aaa = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvEL->GetCurve( u)->Clone()) ; + m_pGeomDB->SetMaterial( aaa, nProp0 == 0 ? BLUE : RED) ; + } + for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) { + for ( int u = 0 ; u < vCrvIsl[i]->GetCurveCount() ; ++ u) { + int nProp0 ; vCrvIsl[i]->GetCurveTempProp( u, nProp0, 0) ; + int nProp1 ; vCrvIsl[i]->GetCurveTempProp( u, nProp1, 1) ; + int aaa = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvIsl[i]->GetCurve( u)->Clone()) ; + m_pGeomDB->SetMaterial( aaa, nProp0 == 0 ? BLUE : RED) ; + } + } + + + + // avendo i lati aperti, devo stare attento alle entrate... per sicurezza li imposto tutti come chiusi ( per ora..) + for ( int u = 0 ; u < pCrvEL->GetCurveCount() ; ++ u) + pCrvEL->SetCurveTempProp( u, 0, 0) ; + for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) + for ( int u = 0 ; u < vCrvIsl[i]->GetCurveCount() ; ++ u) + vCrvIsl[i]->SetCurveTempProp( u, 0, 0) ; + // aggiungo il Loop esterno e le isole + sfrBC.AddCurve( Release( pCrvEL)) ; + for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) + sfrBC.AddCurve( Release( vCrvIsl[i])) ; + } + + // ricavo la nuova superfcicie con i Loops modificati + PtrOwner pSfrFinal( sfrBC.GetSurf()) ; + if ( IsNull( pSfrFinal) || ! pSfrFinal->IsValid()) + return false ; + + // sostituisco ed esco + pSfrPock->Clear() ; + pSfrPock->CopyFrom( pSfrFinal) ; + return pSfrPock != nullptr && pSfrPock->IsValid() ; +} + //---------------------------------------------------------------------------- bool Pocketing::SewingMissingFacesOnPlanes( ISurfTriMesh* pStm, const Plane3d& plPlane) @@ -2718,6 +2850,7 @@ Pocketing::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pSt // per ogni curva dei Loop della FlatRegion vengono presi 4 punti di controllo equidistanti. // se tali punti risultano TUTTI non interni alla Part, allora il lato viene considerato aperto + // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO NON SONO DENTRO AL FINITO " // NB. Aggiungendo delle aree proiettando le parti aperte del volume di Pocketing, alcuni tratti possono risultare // in parte interni ed in parte esterni alla Part... ( questi lati rimangono chiusi, infatti lasciandoli aperti // rischierei di rovinare la part al di fuori del volume di svuotatura. @@ -2810,6 +2943,10 @@ Pocketing::ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const ISurfFlatRegion* // I lati aperti vanno estesi seguendo lo geometria dei lati chiusi adiacenti e tenendo conto delle isole chiuse // vicine ad essi + // NB. Se ho una lavorazione precedente, allora estendo i lati aperti delle quantità relative alla lavorazione + // precedente ( l'attuale infatti svuoterà quello che rimane da svuotare proprio da questa lavorazione) + // Vedi GetNewSfrByAnotherPocketing() + // creo la superifcie da restituire... ( questa superficie sarà estesa presso i lati aperti) PtrOwner pSrfFinal( CreateSurfFlatRegion()) ; if ( IsNull( pSrfFinal)) @@ -2865,7 +3002,7 @@ Pocketing::ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const ISurfFlatRegion* bSomeOpen = true ; } if ( bSomeOpen) { // se trovo dei lati aperti ... - // 4.1) se l'isola è tutta aperta e "trascurabile" la talgo + // 4.1) se l'isola è tutta aperta e "trascurabile" la tolgo bool bRemove = false ; if ( ! CheckForRemovingIsland( pCrvIsl, m_dDiam_Prec > 0 ? m_dDiam_Prec + m_dOffsetR_Prec : m_TParams.m_dDiam, bRemove)) @@ -2935,126 +3072,129 @@ bool Pocketing::CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double& dElev) const { - // inizializzo l'elevazione - dElev = 0 ; - // affondamento come vettore - Vector3d vtDepth = vtTool * dDepth ; - // Offsetto la curva della quantità stabvilità per la ricerca di proiezioni - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCompo, m_dMaxLenRawProj, ICurve::OFF_FILLET)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; - return false ; - } - PtrOwner pCompoExtended( ConvertCurveToComposite( OffsCrv.GetLongerCurve())) ; - if ( IsNull( pCompoExtended) || ! pCompoExtended->IsValid()) - return false ; + // DA ADATTARE ! - // Campiono il contorno - int nMaxInd = pCompoExtended->GetCurveCount() - 1 ; - for ( int i = 0 ; i <= nMaxInd ; ++ i) { - // curva corrente - const ICurve* pCrvC = pCompoExtended->GetCurve( i) ; - Point3d ptStart ; pCrvC->GetStartPoint( ptStart) ; - Point3d ptMid ; pCrvC->GetMidPoint( ptMid) ; - Point3d ptEnd ; pCrvC->GetEndPoint( ptEnd) ; - // elevazione della curva - double dCurrElev ; - if ( GetElevation( m_nPhase, ptStart - vtDepth, ptMid - vtDepth, ptEnd - vtDepth, vtTool, dCurrElev)) { - if ( dCurrElev > dElev) - dElev = dCurrElev ; - } - else { - m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; - return false ; - } - } + //// inizializzo l'elevazione + // dElev = 0 ; + //// affondamento come vettore + // Vector3d vtDepth = vtTool * dDepth ; - // Campiono l'interno con una griglia (uso linee parallele a X) - // determino il riferimento di base - Frame3d frPocket ; - Point3d ptCen ; pCompoExtended->GetCentroid( ptCen) ; - frPocket.Set( ptCen, vtTool) ; - // copio il contorno e lo porto nel riferimento - PtrOwner pCompoL( pCompoExtended->Clone()) ; - if ( IsNull( pCompoL) || ! pCompoL->ToLoc( frPocket)) { - m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; - return false ; - } - // ingombro del contorno in locale - BBox3d b3Pocket ; - pCompoL->GetLocalBBox( b3Pocket) ; - Point3d ptMin ; double dDimX, dDimY, dDimZ ; - b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; + //// Offsetto la curva della quantità stabvilità per la ricerca di proiezioni + // OffsetCurve OffsCrv ; + // if ( ! OffsCrv.Make( pCompo, m_dMaxLenRawProj, ICurve::OFF_FILLET)) { + // m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + // return false ; + // } + // PtrOwner pCompoExtended( ConvertCurveToComposite( OffsCrv.GetLongerCurve())) ; + // if ( IsNull( pCompoExtended) || ! pCompoExtended->IsValid()) + // return false ; - // passi in Y - const double STEP = m_TParams.m_dDiam ; - int nYStep = max( int( ceil( ( dDimY - 20 * EPS_SMALL) / STEP)), 2) ; - double dYStep = ( nYStep > 0 ? ( dDimY - 20 * EPS_SMALL) / nYStep : 0) ; - // calcolo le linee di svuotatura - for ( int i = 1 ; i < nYStep ; ++ i) { - // definisco la linea - PtrOwner pLine( CreateCurveLine()) ; - const double EXP_LEN = 1.0 ; - Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + 10 * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ; - if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) { - m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; - return false ; - } + //// Campiono il contorno + // int nMaxInd = pCompoExtended->GetCurveCount() - 1 ; + // for ( int i = 0 ; i <= nMaxInd ; ++ i) { + // // curva corrente + // const ICurve* pCrvC = pCompoExtended->GetCurve( i) ; + // Point3d ptStart ; pCrvC->GetStartPoint( ptStart) ; + // Point3d ptMid ; pCrvC->GetMidPoint( ptMid) ; + // Point3d ptEnd ; pCrvC->GetEndPoint( ptEnd) ; + // // elevazione della curva + // double dCurrElev ; + // if ( GetElevation( m_nPhase, ptStart - vtDepth, ptMid - vtDepth, ptEnd - vtDepth, vtTool, dCurrElev)) { + // if ( dCurrElev > dElev) + // dElev = dCurrElev ; + // } + // else { + // m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; + // return false ; + // } + // } - // calcolo la classificazione della curva rispetto al contorno - IntersCurveCurve intCC( *pLine, *pCompoL) ; - CRVCVECTOR ccClass ; - if ( intCC.GetCurveClassification( 0, EPS_SMALL, ccClass)) { - // determino gli intervalli di curva interni - Intervals inOk ; - for ( auto& ccOne : ccClass) { - if ( ccOne.nClass == CRVC_IN) { - // ricavo punto iniziale e finale - Point3d ptStart ; - pLine->GetPointD1D2( ccOne.dParS, ICurve::FROM_PLUS, ptStart) ; - Point3d ptEnd ; - pLine->GetPointD1D2( ccOne.dParE, ICurve::FROM_MINUS, ptEnd) ; - // calcolo la distanza tra questi due punti - double dDist = Dist( ptStart, ptEnd) ; - // il tratto interno lo campiono rispetto ad X - for ( int j = 0 ; j <= int( dDist / STEP) + 1 ; ++ j) { - Point3d ptCurr ; - pLine->GetPointD1D2( ccOne.dParS + j * ( ccOne.dParE - ccOne.dParS) / ( dDist / STEP + 1), ICurve::FROM_PLUS, ptCurr) ; - ptCurr.ToGlob( frPocket) ; - double dCurrElev ; - if ( GetElevation( m_nPhase, ptCurr - vtDepth, vtTool, dCurrElev)) { - if ( dCurrElev > dElev) - dElev = dCurrElev ; - } - else { - m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; - return false ; - } - } - } - } - } - // altrimenti uso tutta la curva - else { - Point3d ptStart ; - pLine->GetStartPoint( ptStart) ; - ptStart.ToGlob( frPocket) ; - Point3d ptEnd ; - pLine->GetEndPoint( ptEnd) ; - ptEnd.ToGlob( frPocket) ; - // elevazione della curva - double dCurrElev ; - if ( GetElevation( m_nPhase, ptStart - vtDepth, ptEnd - vtDepth, vtTool, dCurrElev)) { - if ( dCurrElev > dElev) - dElev = dCurrElev ; - } - else { - m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; - return false ; - } - } - } + //// Campiono l'interno con una griglia (uso linee parallele a X) + //// determino il riferimento di base + // Frame3d frPocket ; + // Point3d ptCen ; pCompoExtended->GetCentroid( ptCen) ; + // frPocket.Set( ptCen, vtTool) ; + //// copio il contorno e lo porto nel riferimento + // PtrOwner pCompoL( pCompoExtended->Clone()) ; + // if ( IsNull( pCompoL) || ! pCompoL->ToLoc( frPocket)) { + // m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; + // return false ; + // } + //// ingombro del contorno in locale + // BBox3d b3Pocket ; + // pCompoL->GetLocalBBox( b3Pocket) ; + // Point3d ptMin ; double dDimX, dDimY, dDimZ ; + // b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; + + //// passi in Y + // const double STEP = m_TParams.m_dDiam ; + // int nYStep = max( int( ceil( ( dDimY - 20 * EPS_SMALL) / STEP)), 2) ; + // double dYStep = ( nYStep > 0 ? ( dDimY - 20 * EPS_SMALL) / nYStep : 0) ; + //// calcolo le linee di svuotatura + // for ( int i = 1 ; i < nYStep ; ++ i) { + // // definisco la linea + // PtrOwner pLine( CreateCurveLine()) ; + // const double EXP_LEN = 1.0 ; + // Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + 10 * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ; + // if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) { + // m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; + // return false ; + // } + + // // calcolo la classificazione della curva rispetto al contorno + // IntersCurveCurve intCC( *pLine, *pCompoL) ; + // CRVCVECTOR ccClass ; + // if ( intCC.GetCurveClassification( 0, EPS_SMALL, ccClass)) { + // // determino gli intervalli di curva interni + // Intervals inOk ; + // for ( auto& ccOne : ccClass) { + // if ( ccOne.nClass == CRVC_IN) { + // // ricavo punto iniziale e finale + // Point3d ptStart ; + // pLine->GetPointD1D2( ccOne.dParS, ICurve::FROM_PLUS, ptStart) ; + // Point3d ptEnd ; + // pLine->GetPointD1D2( ccOne.dParE, ICurve::FROM_MINUS, ptEnd) ; + // // calcolo la distanza tra questi due punti + // double dDist = Dist( ptStart, ptEnd) ; + // // il tratto interno lo campiono rispetto ad X + // for ( int j = 0 ; j <= int( dDist / STEP) + 1 ; ++ j) { + // Point3d ptCurr ; + // pLine->GetPointD1D2( ccOne.dParS + j * ( ccOne.dParE - ccOne.dParS) / ( dDist / STEP + 1), ICurve::FROM_PLUS, ptCurr) ; + // ptCurr.ToGlob( frPocket) ; + // double dCurrElev ; + // if ( GetElevation( m_nPhase, ptCurr - vtDepth, vtTool, dCurrElev)) { + // if ( dCurrElev > dElev) + // dElev = dCurrElev ; + // } + // else { + // m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; + // return false ; + // } + // } + // } + // } + // } + // // altrimenti uso tutta la curva + // else { + // Point3d ptStart ; + // pLine->GetStartPoint( ptStart) ; + // ptStart.ToGlob( frPocket) ; + // Point3d ptEnd ; + // pLine->GetEndPoint( ptEnd) ; + // ptEnd.ToGlob( frPocket) ; + // // elevazione della curva + // double dCurrElev ; + // if ( GetElevation( m_nPhase, ptStart - vtDepth, ptEnd - vtDepth, vtTool, dCurrElev)) { + // if ( dCurrElev > dElev) + // dElev = dCurrElev ; + // } + // else { + // m_pMchMgr->SetLastError( 2408, "Error in Pocketing : Entity GetElevation") ; + // return false ; + // } + // } + // } return true ; } @@ -4355,7 +4495,7 @@ Pocketing::CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, ICurv PtrOwner pCrv_Seg1_Isl( CreateCurveComposite()) ; // curva unione di pSeg1 e pCrvLink smussata pCrv_Seg1_Isl->AddCurve( pCrvH1->Clone()) ; pCrv_Seg1_Isl->AddCurve( pCrvTempLink->Clone()) ; - ModifyCurveToSmoothed( pCrv_Seg1_Isl, dTollLeft, dTollRight) ; + ModifyCurveToSmoothed( pCrv_Seg1_Isl, dTollLeft, dTollRight, true) ; // raccordo questa curva con pSeg2 double dUS_1IH, dUE_1IH, dToTLen ; @@ -4366,7 +4506,7 @@ Pocketing::CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, ICurv PtrOwner pCrv_smoothed( CreateCurveComposite()) ; // curva unione del primo smusso con pSeg2 pCrv_smoothed->AddCurve( pCrv_Seg1_Isl->Clone()) ; pCrv_smoothed->AddCurve( pCrvH2->Clone()) ; - ModifyCurveToSmoothed( pCrv_smoothed, dTollLeft, dTollRight) ; + ModifyCurveToSmoothed( pCrv_smoothed, dTollLeft, dTollRight, true) ; // recupero i parametri del nuovo collegamento che si è creato dallo smusso pCrvH1->Clear() ; @@ -4515,11 +4655,11 @@ Pocketing::OptimizedZigZag( ISurfFlatRegion* pSrf, const Vector3d& vtTool, doubl } // Offset per i bordi e percorsi a ZigZag - if ( ! pSfrZigZag->Offset( - dMyOffs, ICurve::OFF_FILLET)) { + if ( ! pSfrZigZag->Offset( - dMyOffs, ICurve::OFF_FILLET)) { m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; return false ; } - if ( ! pSfrForCrv->Offset( - dMyOffs , ICurve::OFF_FILLET)) { + if ( ! pSfrForCrv->Offset( - dMyOffs , ICurve::OFF_FILLET)) { m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; return false ; } @@ -6282,14 +6422,14 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt for ( int i = 0 ; i < int( vOffs.size()) ; ++i ) { if ( i != 0) - ModifyCurveToSmoothed( vOffs[i], 0.01, 0.01) ; + ModifyCurveToSmoothed( vOffs[i], m_TParams.m_dDiam / 16, m_TParams.m_dDiam / 16, false) ; vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ; } for ( int i = 0 ; i < int( vOffsFirstCurve.size()) ; ++ i) { if ( i != 0) - ModifyCurveToSmoothed( vOffsFirstCurve[i], 0.01, 0.01) ; + ModifyCurveToSmoothed( vOffsFirstCurve[i], m_TParams.m_dDiam / 16, m_TParams.m_dDiam / 16, false) ; vOffsFirstCurve[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; } @@ -6353,7 +6493,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt PtrOwner pOff_i1( CloneCurveComposite( vOffs[i + 1])) ; // cerco di tagliare le curve, ottenendo il collegamento // NB. se la curva di offset è la prima, non devo tagliarla, accorcio solo le successive ... - if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest, i == 0 ? 0 : 0.01)) { + if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest, i == 0 ? 0 : 0.01, 0.01, 2)) { // se non sono riuscito, ritorno alla configurazione iniziale PtrOwner pCrvLink( CreateCurveComposite()) ; Vector3d vS, vE ; @@ -6478,11 +6618,11 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt //---------------------------------------------------------------------------- bool -Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightPer, double dLeftPer) +Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, bool bAsParam) { // controllo parametri - if ( pCrv == nullptr) + if ( pCrv == nullptr || dLeftLen < EPS_SMALL || dRightLen < EPS_SMALL) return false ; ICURVEPOVECTOR vCrvStepsToFill ; // vettore delle Curve da raccordare (curve della composita) @@ -6501,6 +6641,8 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightPer, doubl // controllo se la curva è chiusa (nel caso inserisco nel vettore la prima curva due volte, all'inizio e alla fine) if ( pCrv->IsClosed()) { const ICurve* pMyCrvFirst = pCrv->GetFirstCurve() ; + if ( pMyCrvFirst == nullptr) + return false ; vCrvStepsToFill.emplace_back( pMyCrvFirst->Clone()) ; } @@ -6518,14 +6660,25 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightPer, doubl continue ; } - // cerco i paramentri al dRightPer% e dLeftPer% della lunghezza della prima e della seconda curva ( per raccordarli ) - double dU_cm_S = 0 ; double dULast1 = 1 ; double dULast2 = 1 ; - - vCrvStepsToFill[i]->GetDomain( dU_cm_S, dULast1) ; - dUE_ref = ( 1 - dRightPer) * dULast1 ; + // ricavo i valori parametrici associati + double dLen_act ; vCrvStepsToFill[i]->GetLength( dLen_act) ; + double dLen_succ ; vCrvStepsToFill[i+1]->GetLength( dLen_succ) ; + double dUE_ref = 1. ; + if ( dLen_act > dLeftLen) + dUE_ref -= dLeftLen / dLen_act ; + double dUS_ref = 0. ; + if ( dLen_succ > dRightLen) + dUS_ref = dRightLen / dLen_succ ; - vCrvStepsToFill[i+1]->GetDomain( dU_cm_S, dULast2) ; - dUS_ref = dLeftPer * dULast2 ; + // se valori trattati come parametri... + if ( bAsParam) { + // ... cerco i parametri corrispondenti sulle due curve + double dU_cm_S = 0 ; double dULast1 = 1 ; double dULast2 = 1 ; + vCrvStepsToFill[i]->GetDomain( dU_cm_S, dULast1) ; + dUE_ref = ( 1 - dRightLen) * dULast1 ; + vCrvStepsToFill[i+1]->GetDomain( dU_cm_S, dULast2) ; + dUS_ref = dLeftLen * dULast2 ; + } // prendo i punti sulle due curve rispetto a tali parametri Point3d ptS, ptE ; @@ -6559,11 +6712,11 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightPer, doubl // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti while (( IsNull( pCrvArc) || IntersBTWArcs) && nIterForArcs < nMaxTestForArcs) { - dUE_ref = ( dULast1 + dUE_ref ) * 0.5 ; + dUE_ref = ( 1 + dUE_ref ) * 0.5 ; dUS_ref = dUS_ref * 0.5 ; - if ( ! vCrvStepsToFill[i]->GetPointD1D2( dUE_ref, ICurve::FROM_PLUS, ptS) - || ! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE)) + if ( ! vCrvStepsToFill[i]->GetPointD1D2( dUE_ref, ICurve::FROM_PLUS, ptS) || + ! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE)) return false ; dRadius = Dist( ptS, ptE) ; @@ -6695,8 +6848,10 @@ Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, IC return false ; // Prendo i punti, i vettori tangenti e i parametri di essi per le curve - Point3d ptSS, ptSE, ptES, ptEE ; Vector3d vS, vE ; double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; - dUSS = 0; dUSE = 0; + Point3d ptSS, ptSE, ptES, ptEE ; + Vector3d vS, vE ; + double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; + dUSS = 0 ; dUSE = 0 ; pCrvS->GetEndPoint( ptSE) ; pCrvS->GetStartPoint( ptSS); @@ -6712,13 +6867,12 @@ Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, IC // se ho una curva di primo Offset allora non devo accorciarla ... for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) { if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE)) - dLenPercS = 0 ; + dLenPercS = EPS_SMALL * 0.5 ; if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE)) - dLenPercE = 0 ; + dLenPercE = EPS_SMALL * 0.5 ; } - - double dLStepS = dLenPercS * dLenS ; - double dLStepE = dLenPercE * dLenE ; + double dLStepS = dLenPercS < EPS_SMALL ? 0. : m_TParams.m_dDiam * 0.5 ; + double dLStepE = dLenPercE < EPS_SMALL ? 0. : m_TParams.m_dDiam * 0.5 ; dLenE = 0 ; // calcolo i possibili BiArchi tra le due curve @@ -6735,7 +6889,7 @@ Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, IC ptCrvFinal->Clear() ; ptCrvFinal.Set( ptBiArc->Clone()) ; - if ( dLenPercE == 0 && dLenPercS == 0 ) + if ( dLenPercE < EPS_SMALL && dLenPercS < EPS_SMALL) break ; // se il BiArco creato interseca le altre curve di Offset allora mi fermo... @@ -7193,7 +7347,7 @@ Pocketing::GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurve return false ; double dUCrvS ; - ModifyCurveToSmoothed( pPath1, 0.075, 0.075) ; + ModifyCurveToSmoothed( pPath1, 0.075, 0.075, true) ; if ( pPath1->IsClosed()) { pPath1->GetParamAtPoint( ptCrvS, dUCrvS) ; pPath1->ChangeStartPoint( dUCrvS) ; @@ -7421,7 +7575,7 @@ Pocketing::ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pC ! pCrvTwoSeg->AddCurve( pLine1->Clone())) return false ; - ModifyCurveToSmoothed( pCrvTwoSeg, 0.2, 0.2) ; + ModifyCurveToSmoothed( pCrvTwoSeg, 0.2, 0.2, true) ; PtrOwner ptNewCrv( CreateCurveComposite()) ; if ( ptNewCrv->AddCurve( pPath1->Clone()) && @@ -7622,7 +7776,7 @@ Pocketing::RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRV } // smusso la curva - ModifyCurveToSmoothed( pCrvMedAx, 0.025, 0.025) ; + ModifyCurveToSmoothed( pCrvMedAx, 0.025, 0.025, true) ; // se curva valida la inserisco nel vettore, altrimenti forzo il centroide if ( pCrvMedAx->IsValid()) vCrvCoMedAxi.emplace_back( pCrvMedAx->Clone()) ; @@ -7956,7 +8110,7 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta } } - ModifyCurveToSmoothed( pCompo, 0.05, 0.05) ; + ModifyCurveToSmoothed( pCompo, 0.05, 0.05, true) ; pCrvLink->AddCurve( Release( pCompo)) ; return true ; @@ -9098,6 +9252,13 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE return false ; } + // controllo se la curva è un'isola + bool bIsIsland = false ; + double dArea ; Plane3d plCheck ; + if ( ! pCrvCompo->GetArea( plCheck, dArea)) + return false ; + bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ; + // recupero la curva di bordo del lato aperto corrente PtrOwner pCrvNewBorder( ConvertCurveToComposite( pSfrInc->GetLoop( 0, 0))) ; if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid()) @@ -9106,17 +9267,26 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u) pCrvNewBorder->SetCurveTempProp( u, 1, 0) ; - // se la curva originale era tutta aperta, allora tengo solo il nuovo loop esterno della regione di incidenza + // se la curva originale era tutta aperta... if ( bIsAllOpen) { // pulisco la curva originale pCrvBorder->Clear() ; + if ( bIsIsland) { // se isola inserisco il loop interno della regione + pCrvNewBorder.Set( ConvertCurveToComposite( pSfrInc->GetLoop( 0, 1))) ; + if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid()) + return false ; + // imposto la curva come tutta aperta ( gira come girava già l'isola) + for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u) + pCrvNewBorder->SetCurveTempProp( u, 1, 0) ; + } + // se bordo esterno inserisco il bordo esterno return pCrvBorder->AddCurve( Release( pCrvNewBorder)) ; } // altrimenti la spezzo il loop della regione di incidenza nei punti iniziali e finali della curva aperta originale Point3d ptStart ; pCrvBorder->GetStartPoint( ptStart) ; Point3d ptEnd ; pCrvBorder->GetEndPoint( ptEnd) ; - double dUTrimS, dUTrimE ;; + double dUTrimS, dUTrimE ; pCrvNewBorder->GetParamAtPoint( ptStart, dUTrimS, 300 * EPS_SMALL) ; pCrvNewBorder->GetParamAtPoint( ptEnd, dUTrimE, 300 * EPS_SMALL) ; // pulisco la curva originale @@ -9143,7 +9313,7 @@ Pocketing::CreateSurfFrIncidence( const ICurveComposite* pCrv, const double dRad PtrOwner pSfrInc_tmp( GetSurfFlatRegionFromFatCurve( pCrv->Clone(), dRad + EPS_SMALL, false, false)) ; if ( IsNull( pSfrInc_tmp) || ! pSfrInc_tmp->IsValid()) return false ; - pSfrInc->CopyFrom( pSfrInc_tmp) ; + pSfrInc->CopyFrom( pSfrInc_tmp) ; // pSfrInc ha sempre normale Z_AX ! // La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto // per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp diff --git a/Pocketing.h b/Pocketing.h index 31db19c..b9f2780 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -107,8 +107,10 @@ class Pocketing : public Machining bool GetProjectionOfStmToNotPocket( const ISurfTriMesh* pStmPart, const ISurfTriMesh* pStmVol, ISurfFlatRegion* pSfrProj) ; bool CreateSurfFrIncidence( const ICurveComposite* pCrv, const double dRad, const ISurfFlatRegion* pSfrLimit, ISurfFlatRegion* pSfrInc) ; + bool GetNewSfrByAnotherPocketing( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrNoExtendedByOpenEdges, + const ISurfTriMesh* pStmVol, const ISurfFlatRegion* pSfrLimit) ; bool GetHomogeneousParts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCrvs) ; - bool ModifyCurveToSmoothed( ICurveComposite* pCrvOffset, double dRightPer, double dleftPer) ; + bool ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, bool bAsParam) ; bool OrderCurvesByLastPntOfPath( ICRVCOMPOPOVECTOR& vCrv, Point3d ptEnd, PNTVECTOR& vPtStart, VCT3DVECTOR& vVtOut, BOOLVECTOR& vbMidOut) ; bool SetBetterPtStartForSubChunks( ICurveComposite* pCrv0, const ISurfFlatRegion* pSrfToWork, Point3d& ptStart, @@ -303,19 +305,10 @@ class Pocketing : public Machining AggrBottom m_AggrBottom ; // dati eventuale aggregato da sotto bool m_bOpenOutRaw ; // flag forzatura lati aperti sempre fuori dal grezzo double m_dOpenMinSafe ; // minima distanza di sicurezza di attacco su lato aperto - - PtrOwner m_pStmVolPocket ; // volume delle svuotatura - - - bool m_bIntersRaw = true ; // flag per intersezione con grezzo - bool m_bProjectRaw = true ; // flag di proiezione del grezzo - bool m_bHasShape = true ; // flag per presenza di geometria voluta - PtrOwner m_pStmShape ; // puntatore alla superficie TriMesh da seguire - double m_dMaxLenRawProj = 100 ; // lunghezza massima per contatto di proiezione bool m_bOptOffset = true ; // flag per ottimizzazione numero di Offset necessari bool m_bOptOffsetCM = false ; // flag per ottimizzazione numero di Offset necessari con centroidi e medial Axis bool m_bAssignFeed = false ; // flag per controllo della Feed - double m_dDiam_Prec = 0.0 ; // diametro utensile per precedente svuotatura + double m_dDiam_Prec = 50.0 ; // diametro utensile per precedente svuotatura double m_dOffsetR_Prec = 0.0 ; // offset radiale della svuotatura precedente double m_dSideStep_Prec = 0.0 ; // side Step della svuotatura precedente