diff --git a/Operation.cpp b/Operation.cpp index 695381f..d2d1df9 100644 --- a/Operation.cpp +++ b/Operation.cpp @@ -637,26 +637,38 @@ Operation::GetMinDistanceFromRawSide( int nPhase, const Point3d& ptP, double dEx //---------------------------------------------------------------------------- bool -Operation::GetDistanceFromRawBottom( int nPhase, int nPathId, double dToler, double& dRbDist, double& dAllRbDist) const +Operation::GetDistanceFromRawBottom(int nPhase, int nPathId, double dToler, double& dRbDist, double& dAllRbDist) const { - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + if (m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false; + + // ricerco grezzi interessati dal percorso + BBox3d b3Compo; + if (!m_pGeomDB->GetGlobalBBox(nPathId, b3Compo)) + return false; + return GetDistanceFromRawBottom(nPhase, b3Compo, dToler, dRbDist, dAllRbDist); + +} + +//---------------------------------------------------------------------------- +bool +Operation::GetDistanceFromRawBottom(int nPhase, BBox3d& b3Test, double dToler, double& dRbDist, double& dAllRbDist) const +{ + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // recupero distanza da fondo dei grezzi interessati o no dal percorso dRbDist = 0 ; dAllRbDist = 0 ; - BBox3d b3Compo ; - if ( ! m_pGeomDB->GetGlobalBBox( nPathId, b3Compo)) - return false ; - b3Compo.Expand( dToler, dToler, 0) ; + b3Test.Expand(dToler, dToler, 0) ; int nRawId = m_pMchMgr->GetFirstRawPart() ; while ( nRawId != GDB_ID_NULL) { // verifico che il grezzo compaia nella fase if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) { BBox3d b3Raw ; int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; - if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw)) { - double dDist = b3Compo.GetMax().z - b3Raw.GetMin().z ; - if ( b3Compo.OverlapsXY( b3Raw) && dDist > dRbDist) + if (m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw)) { + double dDist = b3Test.GetMax().z - b3Raw.GetMin().z ; + if ( b3Test.OverlapsXY( b3Raw) && dDist > dRbDist) dRbDist = dDist ; if ( dDist > dAllRbDist) dAllRbDist = dDist ; diff --git a/Operation.h b/Operation.h index 7fd7d90..00f6678 100644 --- a/Operation.h +++ b/Operation.h @@ -89,6 +89,7 @@ class Operation : public IUserObj { double dDummy ; return GetDistanceFromRawBottom( nPhase, nPathId, dToler, dRbDist, dDummy) ; } bool GetDistanceFromRawBottom( int nPhase, int nPathId, double dToler, double& dRbDist, double& dAllRbDist) const ; + bool GetDistanceFromRawBottom( int nPhase, BBox3d& b3Test, double dToler, double& dRbDist, double& dAllRbDist) const; bool GetRawGlobBox( int nPhase, int nPathId, double dToler, BBox3d& b3Raw) const ; bool GetRawGlobBox( int nPhase, const BBox3d& b3Test, double dToler, BBox3d& b3Raw) const ; diff --git a/Pocketing.cpp b/Pocketing.cpp index d1d14a0..c09acd7 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2017-2022 //---------------------------------------------------------------------------- // File : Pocketing.cpp Data : 24.08.22 Versione : 2.4h2 @@ -38,6 +38,15 @@ #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkLinePntMinDistCurve.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkMedialAxis.h" +#include "/EgtDev/Include/EGkFilletChamfer.h" +#include "/EgtDev/Include/EGkCurveBezier.h" +#include "/EgtDev/Include/EGkGeoPoint3d.h" +#include "/EgtDev/Include/EGkIntersCurves.h" +#include "/EgtDev/Include/EGkLinePntTgCurve.h" +#include "/EgtDev/Include/EGkSfrCreate.h" #include using namespace std ; @@ -85,7 +94,10 @@ using namespace std ; //---------------------------------------------------------------------------- static string KEY_OPEN = "OPEN" ; static int LINK_CURVE_PROP = -3 ; - +bool GetClosestOffsetToAPoint( ICRVCOMPOPOVECTOR& vCurves, Point3d& ptFocus, Point3d& ptCL, ICurveComposite* pCrv1, ICurveComposite* pCrv2, int& nIndex, bool bFirst = true) ; +bool GetClosestLinkToAPoint( ICURVEPOVECTOR& vCurves, ICRVCOMPOPOVECTOR& vOffs, Point3d& ptFocus, Point3d& ptCL, ICurveComposite* pCrv1, ICurveComposite* pCrv2, bool& bfound, int& nIndex) ; +bool RemoveFirstLoopFromSrfFlatRgn( ISurfFlatRegion* pSrfOrig, ISurfFlatRegion* pSrfRes) ; +bool RemoveSmallParts( ICURVEPOVECTOR& vCurve, double dToll) ; //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_POCKETING), Pocketing) ; @@ -490,15 +502,15 @@ Pocketing::SetParam( int nType, const string& sVal) bool Pocketing::SetGeometry( const SELVECTOR& vIds) { - // verifico validità gestore DB geometrico + // verifico validità gestore DB geometrico if ( m_pGeomDB == nullptr) return false ; // reset della geometria corrente m_vId.clear() ; - // verifico che gli identificativi rappresentino delle entità ammissibili (tutte curve o tutte facce) + // verifico che gli identificativi rappresentino delle entità ammissibili (tutte curve o tutte facce) int nType = GEO_NONE ; for ( const auto& Id : vIds) { - // test sull'entità + // test sull'entità int nSubs ; if ( ! VerifyGeometry( Id, nSubs, nType)) { string sInfo = "Warning in Pocketing : Skipped entity " + ToString( Id) ; @@ -521,14 +533,14 @@ Pocketing::Preview( bool bRecalc) // reset numero percorsi di svuotatura generati m_nPockets = 0 ; - // verifico validità gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; - // se non c'è, lo aggiungo + // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) @@ -571,7 +583,7 @@ Pocketing::Preview( bool bRecalc) // recupero gruppo per geometria di Preview int nPvId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_PV) ; - // se non c'è, lo aggiungo + // se non c'è, lo aggiungo if ( nPvId == GDB_ID_NULL) { nPvId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nPvId == GDB_ID_NULL) @@ -604,7 +616,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // reset raggio massimo attacco ad elica nel caso di cerchi m_dMaxHelixRad = INFINITO ; - // verifico validità gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -616,8 +628,8 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) } // verifico se necessario continuare nell'aggiornamento - if ( ! bRecalc && ! bToolChanged && - ( m_nStatus == MCH_ST_OK || ( ! bPostApply && m_nStatus == MCH_ST_NO_POSTAPPL))) { + if ( !bRecalc && !bToolChanged && + ( m_nStatus == MCH_ST_OK || ( !bPostApply && m_nStatus == MCH_ST_NO_POSTAPPL))) { // confermo i percorsi di lavorazione m_nPockets = nCurrPockets ; LOG_DBG_INFO( GetEMkLogger(), "Pocketing apply skipped : status already ok") ; @@ -633,7 +645,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; - // se non c'è, lo aggiungo + // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) @@ -670,7 +682,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; - // se non c'è, lo aggiungo + // se non c'è, lo aggiungo if ( nClId == GDB_ID_NULL) { nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nClId == GDB_ID_NULL) @@ -684,11 +696,11 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // lavoro ogni singola catena bool bOk = true ; int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; - while ( nPathId != GDB_ID_NULL) { - if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId)) - bOk = false ; - nPathId = m_pGeomDB->GetNextGroup( nPathId) ; - } + //while ( nPathId != GDB_ID_NULL) { + if ( ! ProcessPath( nAuxId, GDB_ID_NULL, nClId)) //nPathId + bOk = false ; + // nPathId = m_pGeomDB->GetNextGroup( nPathId) ; + //} if ( ! bOk) return false ; @@ -713,7 +725,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) bool Pocketing::Update( bool bPostApply) { - // verifico validità gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -947,7 +959,7 @@ Pocketing::UpdateToolData( bool* pbChanged) bool Pocketing::GetGeometry( SELVECTOR& vIds) const { - // restituisco l'elenco delle entità + // restituisco l'elenco delle entità vIds = m_vId ; return true ; } @@ -960,7 +972,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; if ( pGObj == nullptr) return false ; - // se ammesse curve ed è tale + // se ammesse curve ed è tale if ( ( nType == GEO_NONE || nType == GEO_CURVE) && ( pGObj->GetType() & GEO_CURVE) != 0) { nType = GEO_CURVE ; const ICurve* pCurve = nullptr ; @@ -984,7 +996,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) } return true ; } - // se altrimenti ammessi testi ed è tale + // se altrimenti ammessi testi ed è tale else if ( ( nType == GEO_NONE || nType == EXT_TEXT) && pGObj->GetType() == EXT_TEXT) { nType = EXT_TEXT ; const IExtText* pText = ::GetExtText( pGObj) ; @@ -993,7 +1005,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) nSubs = 0 ; return true ; } - // se altrimenti ammesse superfici trimesh ed è tale + // se altrimenti ammesse superfici trimesh ed è tale else if ( ( nType == GEO_NONE || nType == SRF_TRIMESH) && pGObj->GetType() == SRF_TRIMESH) { nType = SRF_TRIMESH ; const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; @@ -1015,7 +1027,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) } return true ; } - // se altrimenti ammesse regioni ed è tale + // se altrimenti ammesse regioni ed è tale else if ( ( nType == GEO_NONE || nType == SRF_FLATRGN) && pGObj->GetType() == SRF_FLATRGN) { nType = SRF_FLATRGN ; const ISurfFlatRegion* pReg = ::GetSurfFlatRegion( pGObj) ; @@ -1082,7 +1094,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) return false ; // la duplico pCurve.Set( pOriCurve->Clone()) ; - // reset proprietà temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCurve) ; // recupero estrusione e spessore Vector3d vtExtr ; @@ -1110,7 +1122,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) // recupero l'outline del testo if ( ! pText->GetOutline( lstPC)) return false ; - // reset proprietà temporanee + // reset proprietà temporanee for ( auto pCrv : lstPC) ResetCurveAllTempProp( pCrv) ; // porto le curve in globale @@ -1132,21 +1144,72 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) pSurf->GetFacetLoops( nFacet, vPL) ; if ( vPL.empty()) return false ; + // recupero la normale esterna della faccia + Vector3d vtN ; + if ( ! pSurf->GetFacetNormal( nFacet, vtN)) + return false ; + // creo la curva a partire dei loop + for ( int i = 0 ; i < vPL.size() ; i++) { + PtrOwner pCrvCompo( CreateCurveComposite()) ; + pCrvCompo->FromPolyLine( vPL[i]) ; + if ( ! pCrvCompo->IsValid()) + return false ; + // reset delle proprietà temporanee + ResetCurveAllTempProp( pCrvCompo) ; + // determino eventuali lati aperti e aggiorno proprietà del contorno + int nInd = 0 ; + double dPar ; + bool bFound = vPL[i].GetFirstU( dPar, true) ; + while ( bFound) { + // recupero il flag + int nFlag = int( dPar) ; + // se non c'è nulla di adiacente, lato aperto + if (nFlag == SVT_NULL) + pCrvCompo->SetCurveTempProp( nInd, 1) ; + // altrimenti verifico se la faccia adiacente forma diedro convesso o concavo + else { + bool bAdjac ; + Point3d ptP1, ptP2 ; + double dAng ; + if ( ! pSurf->GetFacetsContact( nFacet, nFlag, bAdjac, ptP1, ptP2, dAng)) + dAng = - ANG_RIGHT ; + if ( dAng > - EPS_ANG_SMALL) + pCrvCompo->SetCurveTempProp( nInd, 1) ; + } + // passo al successivo + ++nInd ; + bFound = vPL[i].GetNextU( dPar, true) ; + } + // assegno l'estrusione dalla normale alla faccia + pCrvCompo->SetExtrusion( vtN) ; + // unisco le eventuali parti allineate + pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + // la porto in globale + pCrvCompo->ToGlob( frGlob) ; + // sistemazioni varie + AdjustCurveFromSurf( pCrvCompo, TOOL_ORTHO, FACE_CONT, 0) ; + // la restituisco + lstPC.emplace_back( Release( pCrvCompo)) ; + } + + return true ; + + /* // creo la curva a partire da quello esterno PtrOwner pCrvCompo( CreateCurveComposite()) ; pCrvCompo->FromPolyLine( vPL[0]) ; if ( ! pCrvCompo->IsValid()) return false ; - // reset proprietà temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCrvCompo) ; - // determino eventuali lati aperti e aggiorno proprietà del contorno + // determino eventuali lati aperti e aggiorno proprietà del contorno int nInd = 0 ; double dPar ; bool bFound = vPL[0].GetFirstU( dPar, true) ; while ( bFound) { // recupero il flag int nFlag = int( dPar) ; - // se non c'è nulla di adiacente, lato aperto + // se non c'è nulla di adiacente, lato aperto if ( nFlag == SVT_NULL) pCrvCompo->SetCurveTempProp( nInd, 1) ; // altrimenti verifico se la faccia adiacente forma diedro convesso o concavo @@ -1178,6 +1241,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) // la restituisco lstPC.emplace_back( Release( pCrvCompo)) ; return true ; + */ } // se altrimenti regione else if ( pGObj->GetType() == SRF_FLATRGN) { @@ -1201,9 +1265,9 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) // recupero i contorni del chunk for ( int nL = 0 ; nL < pReg->GetLoopCount( nC) ; ++ nL) { PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( pReg->GetLoop( nC, nL))) + if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( pReg->GetLoop( nC, nL))) return false ; - // reset proprietà temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCrvCompo) ; // assegno l'estrusione dalla normale alla regione pCrvCompo->SetExtrusion( vtN) ; @@ -1230,7 +1294,7 @@ Pocketing::SetCurveAllTempProp( int nCrvId, ICurve* pCurve) { if ( pCurve == nullptr) return false ; - // reset proprietà temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCurve) ; // verifico se presenti info per lati aperti if ( ! m_pGeomDB->ExistsInfo( nCrvId, KEY_OPEN)) @@ -1269,11 +1333,11 @@ Pocketing::ResetCurveAllTempProp( ICurve* pCurve) //---------------------------------------------------------------------------- bool -Pocketing::Chain( int nGrpDestId) +Pocketing::Chain( int nGrpDestId) //AUX { // vettore puntatori alle curve ICURVEPOVECTOR vpCrvs ; - vpCrvs.reserve( m_vId.size()) ; + vpCrvs.reserve( m_vId.size()) ; // OGGETTI CLICCATI PRIMA DELL'APPLY // vettore selettori delle curve originali SELVECTOR vInds ; // recupero tutte le curve e le porto in globale @@ -1317,7 +1381,9 @@ Pocketing::Chain( int nGrpDestId) // recupero i percorsi concatenati int nCount = 0 ; INTVECTOR vnId2 ; + while ( chainC.GetChainFromNear( ptNear, false, vnId2)) { + // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) @@ -1370,29 +1436,33 @@ Pocketing::Chain( int nGrpDestId) } // creo nuovo gruppo int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; + if ( nPathId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ; m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ; // inserisco la curva composita nel gruppo destinazione int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ; + if ( nNewId == GDB_ID_NULL) return false ; // salvo info con eventuali lati aperti if ( ! vOpen.empty()) m_pGeomDB->SetInfo( nNewId, KEY_OPEN, vOpen) ; } + return true ; } //---------------------------------------------------------------------------- bool -Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) +Pocketing::ProcessPath(int nAuxId, int nPvId, int nClId) { - // recupero gruppo per geometria temporanea + // ========= GRUPPO TMP =================== + // recupero gruppo per geometria temporanea ( Gruppo TMP ) const string GRP_TEMP = "Temp" ; int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; - // se non c'è, lo aggiungo + // se non c'è, lo aggiungo if ( nTempId == GDB_ID_NULL) { nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nTempId == GDB_ID_NULL) @@ -1405,119 +1475,247 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) // in ogni caso lo dichiaro temporaneo e non visibile m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ; m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ; + // ======================================= - // verifico sia una curva chiusa (deve delimitare l'area da svuotare) - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; - if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO) - return false ; - ICurve* pCrv = ::GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ; - if ( pCrv == nullptr || ! pCrv->IsClosed()) { - m_pMchMgr->SetLastError( 2402, "Error in Pocketing : Open Contour") ; - return false ; + // ========= STEP ======================== + // verifico che lo step dell'utensile sia sensato + double dOkStep = ( m_Params.m_dStep > EPS_SMALL ? m_Params.m_dStep + EPS_SMALL : 0); + const double MIN_ZSTEP = 1.0 ; + if ( dOkStep >= EPS_SMALL && dOkStep < MIN_ZSTEP) { + dOkStep = MIN_ZSTEP + EPS_SMALL ; + string sInfo = "Warning in Pocketing : machining step too small (" + + ToString(m_Params.m_dStep, 2) + ")" ; + m_pMchMgr->SetWarning( 2456, sInfo) ; } - // copio la curva composita da elaborare - int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; - if ( nCopyId == GDB_ID_NULL) - return false ; - ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; - - // annullo i flag di tratto aperto - for ( int i = 0 ; i < int( pCompo->GetCurveCount()) ; ++ i) - pCompo->SetCurveTempProp( i, 0) ; - - // verifico se vanno gestiti i lati aperti - bool bSomeOpen = m_pGeomDB->ExistsInfo( nCrvId, KEY_OPEN) ; - if ( bSomeOpen) { - int nOpen ; - if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "Open="), nOpen) && nOpen == 0) - bSomeOpen = false ; + // verifico di non superare il massimo materiale + if ( m_Params.m_dStep > m_TParams.m_dMaxMat + EPS_SMALL) { + dOkStep = m_TParams.m_dMaxMat + EPS_SMALL ; + string sInfo = "Warning in Pocketing : machining step (" + ToString(m_Params.m_dStep, 1) + + ") bigger than MaxMaterial (" + ToString(m_TParams.m_dMaxMat, 1) + ")" ; + m_pMchMgr->SetWarning( 2457, sInfo) ; } + // ======================================= - // aggiorno flag per lati aperti - if ( bSomeOpen) { - INTVECTOR vOpen ; - m_pGeomDB->GetInfo( nCrvId, KEY_OPEN, vOpen) ; - for ( int j : vOpen) - pCompo->SetCurveTempProp( j, 1) ; - } + // recupero eventuale flag di lato aperto forzato fuori dal grezzo + int nOpenOutRaw ; + m_bOpenOutRaw = ( FromString( ExtractInfo(m_Params.m_sUserNotes, "OpenOutRaw="), nOpenOutRaw) && nOpenOutRaw != 0) ; - // recupero estrusione e spessore - Vector3d vtExtr = Z_AX ; - pCompo->GetExtrusion( vtExtr) ; - double dThick ; - pCompo->GetThickness( dThick) ; + SurfFlatRegionByContours SrfByC ; // superificie totale generata da tutte le curve concatenate + Plane3d plAux ; bool bFirstPlane = true ; // piano Ausiliario per verificare che le curve siano complanari + Vector3d vtExtr ; + double dThick = -INFINITO ; // spessore più grande tra le curve + int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; - // eventuale inversione direzione utensile - if ( m_Params.m_bToolInvert) { - vtExtr.Invert() ; - pCompo->SetExtrusion( vtExtr) ; - dThick = - dThick ; - pCompo->SetThickness( dThick) ; - } + while ( nPathId != GDB_ID_NULL) { // Scorro tutte le curve concatenate per creare la superficie da lavorare - // verifico sia piana e se necessario la appiattisco - PtrOwner pFlatCrv( FlattenCurve( *pCompo, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ; - if ( IsNull( pFlatCrv)) { - Plane3d plPlane ; - if ( ! pCompo->IsFlat( plPlane, true, 50 * EPS_SMALL)) - m_pMchMgr->SetLastError( 2403, "Error in Pocketing : Contour Not Flat") ; - else - m_pMchMgr->SetLastError( 2404, "Error in Pocketing : Tool Not Perpendicular to Flat Area") ; - return false ; - } - pFlatCrv->GetExtrusion( vtExtr) ; - pCompo->Clear() ; - pCompo->AddCurve( Release( pFlatCrv)) ; - pCompo->SetExtrusion( vtExtr) ; - pCompo->SetThickness( dThick) ; - // sistemo senso antiorario visto dalla direzione di estrusione - Plane3d plPlane ; double dArea ; - pCompo->GetArea( plPlane, dArea) ; - if ( plPlane.GetVersN() * vtExtr * dArea < 0) - pCompo->Invert() ; - - // unisco le parti allineate (tranne inizio-fine se chiusa) - if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false, true)) - return false ; - - // se ci sono lati aperti - bool bMidOpen = false ; - Point3d ptMidOpen ; - Vector3d vtMidOut ; - if ( bSomeOpen) { - // ricerca del punto medio del lato aperto più lungo - bMidOpen = GetMidOfLongestOpenSide( pCompo, ptMidOpen, vtMidOut) ; - // sistemazioni per eventuali lati aperti - if ( ! AdjustContourWithOpenEdges( pCompo)) { - m_pMchMgr->SetLastError( 2430, "Error in Pocketing : adjust open edges failed") ; + int nPi = m_pGeomDB->GetFirstInGroup( nPathId) ; + const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( nPi) ; + if ( pGObj == nullptr) return false ; + const ICurve* pOriCurve = ::GetCurve( pGObj) ; + if ( pOriCurve == nullptr) + return false ; + PtrOwner pCompoOriCrv( GetCurveComposite( pOriCurve->Clone())) ; + if ( IsNull( pCompoOriCrv)) + return false ; + + // unisco le parti allineate (tranne inizio-fine se chiusa) + if ( ! pCompoOriCrv->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false, true)) + return false ; + + // controllo se trovo dei Flag per lati aperti + bool bSomeOpen = m_pGeomDB->ExistsInfo( nPi, KEY_OPEN) ; + if ( bSomeOpen) { + int nOpen ; + if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "Open="), nOpen) && nOpen == 0) + bSomeOpen = false ; + } + + // annullo i flag di tratto aperto + for ( int i = 0; i < int( pCompoOriCrv->GetCurveCount()) ; ++i) + pCompoOriCrv->SetCurveTempProp( i, 0, 0) ; // alla sottocurva + + // aggiorno flag per lati aperti + if ( bSomeOpen) { + INTVECTOR vOpen ; + m_pGeomDB->GetInfo( nPi, KEY_OPEN, vOpen) ; + for (int j : vOpen) + pCompoOriCrv->SetCurveTempProp( j, 1, 0) ; // alla sottocurva + } + + // recupero estrusione e spessore + Vector3d vtExtr_p = Z_AX ; + pCompoOriCrv->GetExtrusion( vtExtr_p) ; + double dThick_p ; + pCompoOriCrv->GetThickness( dThick_p) ; + + // verifico sia piana e se necessario la appiattisco + PtrOwner pFlatCrv( FlattenCurve( *pCompoOriCrv, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ; + if ( IsNull( pFlatCrv)) { + Plane3d plPlane ; + if ( ! pCompoOriCrv->IsFlat( plPlane, true, 50 * EPS_SMALL)) + m_pMchMgr->SetLastError( 2403, "Error in Pocketing : Contour Not Flat") ; + else + m_pMchMgr->SetLastError( 2404, "Error in Pocketing : Tool Not Perpendicular to Flat Area") ; + return false; + } + pFlatCrv->GetExtrusion( vtExtr_p) ; + pCompoOriCrv->Clear() ; + pCompoOriCrv->AddCurve( Release( pFlatCrv)) ; + pCompoOriCrv->SetExtrusion( vtExtr_p) ; + pCompoOriCrv->SetThickness( dThick_p) ; + + // setto come proprietà temperanea il suo Id ( per riprenderlo dopo per casi ottimizzati) + pCompoOriCrv->SetTempProp( nPi, 0) ; // a tutta la curva + + // controllo che le curve siano complanari e con stessa estrusione (la prima come riferimento) + Plane3d plAct ; + pCompoOriCrv->IsFlat( plAct) ; + if ( bFirstPlane) { + plAux = plAct ; + bFirstPlane = false ; + pCompoOriCrv->GetThickness( dThick_p) ; + dThick = dThick_p ; // prima come riferimento + vtExtr = vtExtr_p ; // prima come riferimento + SrfByC.AddCurve( pCompoOriCrv->Clone()) ; + } + else { + Vector3d vtN1, vtN2 ; + if ( abs( plAct.GetDist() - plAux.GetDist()) < EPS_SMALL + && AreSameOrOppositeVectorApprox( plAct.GetVersN(), plAux.GetVersN()) // se stessa normale + && AreSameVectorApprox( vtExtr, vtExtr_p)) { // se stessa estrusione + SrfByC.AddCurve( pCompoOriCrv->Clone()) ; + // prendo Thickness Massima tra tutte le curve dei chunks + double dCurrThink ; + pCompoOriCrv->GetThickness( dCurrThink) ; + if ( dCurrThink > dThick) + dThick = dCurrThink ; + } + } + + nPathId = m_pGeomDB->GetNextGroup( nPathId) ; // aggiorno il PathId con il successivo nel gruppo + + } + + // creazione della superficie da lavorare completa (dall'unione di tutte le curve concatenate) + PtrOwner pSrfByC( SrfByC.GetSurf()) ; + if ( pSrfByC == nullptr) + return false ; + + // creo la superificie finale ( quella con le curve modificate se contengono dei lati aperti ) + PtrOwner pSrfPock( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfPock)) + return false ; + + // vettore per i punti iniziali delle curve che definiscono i contorni dei Chunks + PNTVECTOR vPtStart( pSrfByC->GetChunkCount()) ; + + // vettori controllo per lati aperti + BOOLVECTOR vbMidOpen( pSrfByC->GetChunkCount()) ; + PNTVECTOR vPtMidOpen( vbMidOpen.size()) ; + VCT3DVECTOR vVtMidOut( vPtMidOpen.size()) ; + + for ( int c = 0 ; c < pSrfByC->GetChunkCount() ; c++) { // ciclo sui chunk ottenuti + + // riferimento della curva esterna del chunk (c)-esimo (bordo esterno) + PtrOwner pCrvExt( GetCurveComposite( pSrfByC->GetLoop( c, 0))) ; + bool bSomeOpen = m_pGeomDB->ExistsInfo( pCrvExt->GetTempProp( 0), KEY_OPEN) ; + + // se trovo dei ==| LATI APERTI |== allora modifico il bordo esterno + bool bMidOpen = false ; + Point3d ptMidOpen ; + Vector3d vtMidOut ; + if ( bSomeOpen) { + // ricerca del punto medio del lato aperto più lungo + bMidOpen = GetMidOfLongestOpenSide( pCrvExt, ptMidOpen, vtMidOut) ; + // sistemazioni per eventuali lati aperti + if ( ! AdjustContourWithOpenEdges( pCrvExt)) { + m_pMchMgr->SetLastError( 2430, "Error in Pocketing : adjust open edges failed") ; + return false; + } + } + + // sposto l'inizio a metà del tratto più lungo ( o aperto più lungo) della curva esterna + if ( bMidOpen) { + const double LEN_OUT = 5 ; + double dPar ; int nFlag ; + bMidOpen = ( DistPointCurve( ptMidOpen + LEN_OUT * vtMidOut, *pCrvExt).GetParamAtMinDistPoint( 0, dPar, nFlag) && pCrvExt->ChangeStartPoint( dPar)) ; + } + if ( ! bMidOpen) + AdjustContourStart( pCrvExt) ; + + // recupero il punto di inizio (per poi salvarlo nelle info di CL path) + Point3d ptStart ; pCrvExt->GetStartPoint( ptStart) ; + vPtStart[c] = ptStart ; // salvataggio del punto nel vettore + + // inserisco il Loop esterno + if ( ! pSrfPock->AddExtLoop( pCrvExt->Clone())) + return false ; + + // aggiorno i vettori di controllo + vbMidOpen.push_back( bMidOpen) ; + vPtMidOpen.push_back( ptMidOpen) ; + vVtMidOut.push_back( vtMidOut) ; + + for ( int l = 1 ; l < pSrfByC->GetLoopCount( c) ; l++) { // scorro il loop interni del Chunk ( bordi delle isole ) + + PtrOwner pCrvInt(( ICurveComposite*)pSrfByC->GetLoop( c, l)) ; + if ( IsNull( pCrvInt)) + return false ; + + bool bSomeOpen_i = m_pGeomDB->ExistsInfo( pCrvInt->GetTempProp( 0), KEY_OPEN) ; + + // se trovo dei ==| LATI APERTI |== allora modifico il bordo esterno + bool bMidOpen_i = false ; + Point3d ptMidOpen_i ; + Vector3d vtMidOut_i ; + if ( bSomeOpen_i) { + // ricerca del punto medio del lato aperto più lungo + bMidOpen_i = GetMidOfLongestOpenSide( pCrvInt, ptMidOpen_i, vtMidOut_i) ; + // sistemazioni per eventuali lati aperti + if ( ! AdjustContourWithOpenEdges( pCrvInt)) { + m_pMchMgr->SetLastError( 2430, "Error in Pocketing : adjust open edges failed") ; + return false; + } + } + if ( bMidOpen_i) { + const double LEN_OUT = 5 ; + double dPar_i; int nFlag_i ; + bMidOpen_i = ( DistPointCurve( ptMidOpen_i + LEN_OUT * vtMidOut_i, *pCrvInt).GetParamAtMinDistPoint( 0, dPar_i, nFlag_i) && pCrvInt->ChangeStartPoint( dPar_i)) ; + } + if ( ! bMidOpen_i) + AdjustContourStart( pCrvInt) ; + + // aggiungo curve interne + if ( ! pSrfPock->AddIntLoop( pCrvInt->Clone())) + return false ; } } - // sposto l'inizio a metà del tratto più lungo ( o aperto più lungo) - if ( bMidOpen) { - const double LEN_OUT = 5 ; - double dPar ; int nFlag ; - bMidOpen = ( DistPointCurve( ptMidOpen + LEN_OUT * vtMidOut, *pCompo).GetParamAtMinDistPoint( 0, dPar, nFlag) && pCompo->ChangeStartPoint( dPar)) ; - } - if ( ! bMidOpen) - AdjustContourStart( pCompo) ; + // normale della superifice finale || extrusione prima curva selezionata + if ( AreOppositeVectorApprox( vtExtr, pSrfPock->GetNormVersor())) + pSrfPock->Invert() ; - // recupero il punto di inizio (per poi salvarlo nelle info di CL path) - Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + if ( m_Params.m_bToolInvert) { + // eventuale inversione direzione utensile + vtExtr.Invert() ; + pSrfPock->Invert() ; + dThick = -dThick ; + } // recupero il box del grezzo in globale BBox3d b3Raw ; - if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) { + BBox3d b3Chunk ; pSrfPock->GetBBox( GLOB_FRM, b3Chunk) ; + if ( ! GetRawGlobBox( m_nPhase, b3Chunk, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) { m_pMchMgr->SetLastError( 2405, "Error in Pocketing : Empty RawBox") ; return false ; } // recupero distanza da fondo dei grezzi interessati dal percorso - double dRbDist = 0 ; + double dRbDist = 0 ; double dAllRbDist = 0 ; if ( AreSameVectorApprox( vtExtr, Z_AX)) { - if ( ! GetDistanceFromRawBottom( m_nPhase, nCopyId, m_TParams.m_dTDiam, dRbDist)) + if ( ! GetDistanceFromRawBottom( m_nPhase, b3Chunk, m_TParams.m_dTDiam, dRbDist, dAllRbDist)) return false ; } @@ -1536,76 +1734,62 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) // sottraggo eventuale offset longitudinale dDepth -= GetOffsL() ; - // recupero nome del path - string sPathName ; - m_pGeomDB->GetName( nPathId, sPathName) ; - // assegno il versore fresa Vector3d vtTool = vtExtr ; + m_bAggrBottom = false; + // calcolo l'elevazione massima - double dElev ; - if ( CalcRegionElevation( pCompo, vtTool, dDepth, 0.5 * m_TParams.m_dDiam, dElev)) { - if ( dElev < EPS_SMALL && AreSameVectorApprox( vtExtr, Z_AX)) { - BBox3d b3Crv ; - pCompo->GetLocalBBox( b3Crv) ; - dElev = max( 0., b3Raw.GetMax().z - b3Crv.GetMin().z + min( 0., dThick) + dDepth) ; + double dElev = -INFINITO ; + for ( int c = 0; c < pSrfPock->GetChunkCount() ; c++) { + double dCurrElev ; + if ( CalcRegionElevation( GetCurveComposite( pSrfPock->GetLoop( c,0)), vtTool, dDepth, 0.5 * m_TParams.m_dDiam, dCurrElev)) { + if ( dCurrElev < EPS_SMALL && AreSameVectorApprox( vtExtr, Z_AX)) { + BBox3d b3Crv ; + pSrfPock->GetLoop( c, 0)->GetLocalBBox( b3Crv) ; + dCurrElev = max( 0., b3Raw.GetMax().z - b3Crv.GetMin().z + min(0., dThick) + dDepth) ; + } + if ( dCurrElev > dElev) + dElev = dCurrElev ; } + else + return false; } - else - return false ; + // eventuale imposizione massima elevazione da note utente double dMaxElev ; - if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "MaxElev="), dMaxElev) && dElev > dMaxElev) + if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "MaxElev="), dMaxElev) && dElev > dMaxElev) dElev = dMaxElev ; - // verifico che lo step dell'utensile sia sensato - double dOkStep = ( m_Params.m_dStep > EPS_SMALL ? m_Params.m_dStep + EPS_SMALL : 0) ; - const double MIN_ZSTEP = 1.0 ; - if ( dOkStep >= EPS_SMALL && dOkStep < MIN_ZSTEP) { - dOkStep = MIN_ZSTEP + EPS_SMALL ; - string sInfo = "Warning in Pocketing : machining step too small (" + - ToString( m_Params.m_dStep, 2) + ")" ; - m_pMchMgr->SetWarning( 2456, sInfo) ; - } - // verifico che il massimo materiale dell'utensile sia sensato const double MIN_MAXMAT = 1.0 ; if ( m_TParams.m_dMaxMat < dElev && m_TParams.m_dMaxMat < MIN_MAXMAT) { string sInfo = "Error in Pocketing : Tool MaxMaterial too small (" + - ToString( m_TParams.m_dMaxMat, 2) + ")" ; - m_pMchMgr->SetLastError( 2422, sInfo) ; + ToString(m_TParams.m_dMaxMat, 2) + ")" ; + m_pMchMgr->SetLastError(2422, sInfo) ; return false ; } - // verifico di non superare il massimo materiale - // se lo step supera la capacità dell'utensile - if ( m_Params.m_dStep > m_TParams.m_dMaxMat + EPS_SMALL) { - dOkStep = m_TParams.m_dMaxMat + EPS_SMALL ; - string sInfo = "Warning in Pocketing : machining step (" + ToString( m_Params.m_dStep, 1) + - ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; - m_pMchMgr->SetWarning( 2457, sInfo) ; - } // se lavorazione singola - if ( dOkStep < EPS_SMALL || dOkStep > dElev) { - // se l'elevazione supera la capacità dell'utensile - if ( dElev > m_TParams.m_dMaxMat + EPS_SMALL) { - string sInfo = "Warning in Pocketing : machining depth (" + ToString( dElev, 1) + - ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; - m_pMchMgr->SetWarning( 2458, sInfo) ; + if ( dOkStep < EPS_SMALL || dOkStep > dElev) { + // se l'elevazione supera la capacità dell'utensile + if ( dElev > m_TParams.m_dMaxMat + EPS_SMALL ) { + string sInfo = "Warning in Pocketing : machining depth (" + ToString(dElev, 1) + + ") bigger than MaxMaterial (" + ToString(m_TParams.m_dMaxMat, 1) + ")" ; + m_pMchMgr->SetWarning(2458, sInfo) ; dDepth -= dElev - m_TParams.m_dMaxMat ; dElev = m_TParams.m_dMaxMat ; } } - // altrimenti lavorazione a step + // altrimenti lavorazione a step else { - // se l'elevazione supera il massimo affondamento dell'utensile + // se l'elevazione supera il massimo affondamento dell'utensile double dSafe = m_pMchMgr->GetCurrMachiningsMgr()->GetMaxDepthSafe() ; double dMaxDepth = m_TParams.m_dLen - ( m_TParams.m_dDiam > m_dTHoldDiam ? m_dTHoldBase : m_dTHoldLen) - dSafe ; if ( dElev > dMaxDepth + EPS_SMALL) { - // segnalo, riduco e continuo + // segnalo, riduco e continuo string sInfo = "Warning in Pocketing : machining depth (" + ToString( dElev, 1) + - ") bigger than MaxDepth (" + ToString( dMaxDepth, 1) + ")" ; + ") bigger than MaxDepth (" + ToString(dMaxDepth, 1) + ")" ; m_pMchMgr->SetWarning( 2458, sInfo) ; dDepth -= dElev - dMaxDepth ; dElev = dMaxDepth ; @@ -1614,20 +1798,18 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) // verifico se tavola basculante bool bTiltTab = false ; - m_bTiltingTab = ( m_pMchMgr->GetCurrMachine()->GetCurrTableIsTilting( bTiltTab) && bTiltTab) ; + m_bTiltingTab = ( m_pMchMgr->GetCurrMachine()->GetCurrTableIsTilting( bTiltTab) && bTiltTab) ; // verifico se testa da sopra (Z+) m_bAboveHead = m_pMchMgr->GetHeadAbove( m_TParams.m_sHead) ; // verifiche per svuotature dal basso - m_bAggrBottom = false ; - if ( ! VerifyPathFromBottom( pCompo, vtTool)) { - return false ; + m_bAggrBottom = false ; + if ( ! VerifyPathFromBottom( pSrfPock, vtTool)) { + return false; } - // recupero eventuale flag di lato aperto forzato fuori dal grezzo - int nOpenOutRaw ; - m_bOpenOutRaw = ( FromString( ExtractInfo( m_Params.m_sUserNotes, "OpenOutRaw="), nOpenOutRaw) && nOpenOutRaw != 0) ; + string sPathName = "P1" ; // se richiesta anteprima if ( nPvId != GDB_ID_NULL) { @@ -1638,7 +1820,7 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) m_pGeomDB->SetName( nPxId, sPathName) ; m_pGeomDB->SetMaterial( nPxId, GREEN) ; // creo l'anteprima del percorso - if ( ! GeneratePocketingPv( nPxId, pCompo)) + if ( ! GeneratePocketingPv( nPxId, pSrfPock)) return false ; } @@ -1653,47 +1835,47 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) // verifico se archi vanno approssimati con segmenti di retta int nSplitArcs = m_pMchMgr->GetCurrMachiningsMgr()->GetSplitArcs() ; - bool bSplitArcs = ( nSplitArcs == SPLAR_ALWAYS || - ( nSplitArcs == SPLAR_NO_XY_PLANE && ! vtExtr.IsZplus()) || - ( nSplitArcs == SPLAR_GEN_PLANE && vtExtr.IsGeneric())) ; + bool bSplitArcs = ( nSplitArcs == SPLAR_ALWAYS || + ( nSplitArcs == SPLAR_NO_XY_PLANE && !vtExtr.IsZplus()) || + ( nSplitArcs == SPLAR_GEN_PLANE && vtExtr.IsGeneric())) ; // assegno il vettore estrazione al gruppo del percorso m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ; // assegno i punti di inizio e fine al gruppo del percorso - m_pGeomDB->SetInfo( nPxId, KEY_START, ptStart) ; - m_pGeomDB->SetInfo( nPxId, KEY_END, ptStart) ; + m_pGeomDB->SetInfo( nPxId, KEY_START, vPtStart[0]); //<-------- + m_pGeomDB->SetInfo( nPxId, KEY_END, vPtStart[0]); //<-------- // assegno l'elevazione massima m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; - // Imposto dati comuni + // Imposto dati comuni SetPathId( nPxId) ; SetToolDir( vtTool) ; - // Eseguo la lavorazione a seconda del tipo + // Eseguo la lavorazione del chunk (c)-esimo modificato per lati aperti a seconda del tipo di lavorazione richiesto switch ( m_Params.m_nSubType) { - case POCKET_SUB_ZIGZAG : - if ( ! AddZigZag( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) + case POCKET_SUB_ZIGZAG: + if ( ! AddZigZag( pSrfPock, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) return false ; break ; - case POCKET_SUB_ONEWAY : - if ( ! AddOneWay( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs)) + case POCKET_SUB_ONEWAY: + if ( ! AddOneWay( pSrfPock, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs)) return false ; break ; - case POCKET_SUB_SPIRALIN : - if ( ! AddSpiralIn( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, bMidOpen, ptMidOpen, vtMidOut, nPathId)) + case POCKET_SUB_SPIRALIN: + if ( ! AddSpiralIn( pSrfPock, vPtStart, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, vbMidOpen, vPtMidOpen, vVtMidOut, nPathId)) return false ; break ; - case POCKET_SUB_SPIRALOUT : - if ( ! AddSpiralOut( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) + case POCKET_SUB_SPIRALOUT: + if ( ! AddSpiralOut( pSrfPock, vPtStart, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) return false ; break ; } } - // incremento numero di svuotature - ++ m_nPockets ; + m_nPockets++ ; return true ; + } //---------------------------------------------------------------------------- @@ -1810,12 +1992,12 @@ Pocketing::CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& v //---------------------------------------------------------------------------- bool -Pocketing::VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) +Pocketing::VerifyPathFromBottom( const ISurfFlatRegion* pSrfPock, const Vector3d& vtTool) { - // se non è svuotatura dal basso in alto, esco + // se non è svuotatura dal basso in alto, esco if ( vtTool.z > MIN_ZDIR_TOP_TOOL) return true ; - // se c'è testa non dall'alto o tavola basculante, esco + // se c'è testa non dall'alto o tavola basculante, esco if ( ! m_bAboveHead || m_bTiltingTab) return true ; // recupero dati di eventuale rinvio da sotto @@ -1828,31 +2010,40 @@ Pocketing::VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& double dMinDist = INFINITO ; Vector3d vtMinDir ; VCT3DVECTOR vDir ; - double dParS, dParE ; pCompo->GetDomain( dParS, dParE) ; - for ( double dPar = dParS ; dPar < dParE + EPS_PARAM ; dPar += 0.5) { - // distanza minima del punto e relativa direzione dal contorno del grezzo - Point3d ptP ; double dCurrDist = INFINITO ; Vector3d vtCurrDir ; - if ( pCompo->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP) && - GetMinDistanceFromRawSide( m_nPhase, ptP, 0, m_AggrBottom.vtMDir, MCH_AGB_DELTAMAX_MDIR, dCurrDist, vtCurrDir)) { - if ( dCurrDist < dMinDist - 10 * EPS_SMALL && - find_if( vDir.begin(), vDir.end(), [&](const Vector3d& vtV){ return vtCurrDir * vtV > cos( 15 * DEGTORAD) ; }) == vDir.end()) { - // inserisco la direzione tra quelle già esplorate - vDir.emplace_back( vtCurrDir) ; - // determino la distanza di tutti gli altri punti dal contorno del grezzo lungo questa direzione - for ( double dPar2 = dParS ; dPar2 < dParE + EPS_PARAM ; dPar2 += 0.5) { - if ( abs( dPar2 - dPar) > EPS_PARAM) { - Point3d ptQ ; - double dQDist ; - if ( pCompo->GetPointD1D2( dPar2, ICurve::FROM_MINUS, ptQ) && - GetDistanceFromRawSide( m_nPhase, ptQ, vtCurrDir, dQDist) && dQDist > dCurrDist) - dCurrDist = dQDist ; + + for ( int c = 0 ; c < pSrfPock->GetChunkCount() ; c++) { + for ( int l = 0 ; l < pSrfPock->GetLoopCount( c) ; l++) { + PtrOwner pCompo( GetCurveComposite( pSrfPock->GetLoop( c, l))) ; + if ( IsNull( pCompo)) + return false ; + + double dParS, dParE ; pCompo->GetDomain( dParS, dParE) ; + for ( double dPar = dParS ; dPar < dParE + EPS_PARAM ; dPar += 0.5) { + // distanza minima del punto e relativa direzione dal contorno del grezzo + Point3d ptP ; double dCurrDist = INFINITO ; Vector3d vtCurrDir ; + if ( pCompo->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP) && + GetMinDistanceFromRawSide( m_nPhase, ptP, 0, m_AggrBottom.vtMDir, MCH_AGB_DELTAMAX_MDIR, dCurrDist, vtCurrDir)) { + if ( dCurrDist < dMinDist - 10 * EPS_SMALL && + find_if( vDir.begin(), vDir.end(), [&]( const Vector3d& vtV) { return vtCurrDir * vtV > cos(15 * DEGTORAD); }) == vDir.end()) { + // inserisco la direzione tra quelle già esplorate + vDir.emplace_back( vtCurrDir) ; + // determino la distanza di tutti gli altri punti dal contorno del grezzo lungo questa direzione + for ( double dPar2 = dParS; dPar2 < dParE + EPS_PARAM; dPar2 += 0.5) { + if ( abs( dPar2 - dPar) > EPS_PARAM) { + Point3d ptQ ; + double dQDist ; + if ( pCompo->GetPointD1D2( dPar2, ICurve::FROM_MINUS, ptQ) && + GetDistanceFromRawSide( m_nPhase, ptQ, vtCurrDir, dQDist) && dQDist > dCurrDist) + dCurrDist = dQDist ; + } + } + // se la massima distanza trovata è inferiore al minimo, lo aggiorno + if ( dCurrDist < dMinDist) { + dMinDist = dCurrDist ; + vtMinDir = vtCurrDir ; + } } } - // se la massima distanza trovata è inferiore al minimo, lo aggiorno - if ( dCurrDist < dMinDist) { - dMinDist = dCurrDist ; - vtMinDir = vtCurrDir ; - } } } } @@ -1871,16 +2062,10 @@ Pocketing::VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& //---------------------------------------------------------------------------- bool -Pocketing::GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) +Pocketing::GeneratePocketingPv( int nPathId, const ISurfFlatRegion* pSrfPock) { // creo copia della curva composita - PtrOwner pCrv( pCompo->Clone()) ; - if ( IsNull( pCrv)) - return false ; - // calcolo la regione - SurfFlatRegionByContours SfrCntrRr ; - SfrCntrRr.AddCurve( Release( pCrv)) ; - PtrOwner pSfr( SfrCntrRr.GetSurf()) ; + PtrOwner pSfr( CloneSurfFlatRegion( pSrfPock)) ; if ( IsNull( pSfr)) return false ; // ne recupero il contorno @@ -1888,11 +2073,11 @@ Pocketing::GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) pCrv2.Set( pSfr->GetLoop( 0, 0)) ; if ( IsNull( pCrv2)) return false ; - // inserisco la curva nel DB + // inserisco la curva nel DB int nC2Id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, Release( pCrv2)) ; if ( nC2Id == GDB_ID_NULL) return false ; - // assegno nome e colore + // assegno nome e colore m_pGeomDB->SetName( nC2Id, MCH_PV_CUT) ; m_pGeomDB->SetMaterial( nC2Id, RED) ; // eventuali altri contorni ( interni di contornatura chiusa) @@ -1942,7 +2127,7 @@ GetCurveRadius( const ICurve* pCrv) //---------------------------------------------------------------------------- bool -Pocketing::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, +Pocketing::AddZigZag( const ISurfFlatRegion* pSrfPock, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) { // recupero distanze di sicurezza @@ -1956,175 +2141,411 @@ Pocketing::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, con nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; double dStep = dElev / nStep ; - // determino il riferimento di base della svuotatura - Frame3d frPocket ; - Point3d ptCen ; pCompo->GetCentroid( ptCen) ; - frPocket.Set( ptCen, vtExtr) ; - frPocket.Rotate( ptCen, vtExtr, m_Params.m_dSideAngle) ; - - ICRVCOMPOPOVECTOR vpCrvs ; - int nOffsCrvNbr = 0 ; - - // verifico se si tratta di caso ottimizzato - bool bOptimizedZigZag = false ; - bool bOutRawLeadIn = false ; - if ( ! OptimizedZigZag( nPathId, vtTool, dDepth, dSafeZ, frPocket, bOptimizedZigZag, vpCrvs)) - return false ; - if ( bOptimizedZigZag && ! vpCrvs.empty()) { - nOffsCrvNbr = 1 ; - // verifico se attacco fuori dal grezzo - Point3d ptStart ; - vpCrvs[0]->GetStartPoint( ptStart) ; - Vector3d vtDir ; - vpCrvs[0]->GetStartDir( vtDir) ; - ptStart += -vtDir * ( m_TParams.m_dDiam / 2 + dSafeZ) ; - ptStart.ToGlob( frPocket) ; - ptStart += - vtTool * dDepth ; - double dTestElev ; - if ( ! GetElevation( m_nPhase, ptStart, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElev) || dTestElev < EPS_SMALL) - bOutRawLeadIn = true ; - // sistemo attacco (per essere completamente fuori dal grezzo) - if ( bOutRawLeadIn || m_bOpenOutRaw) - vpCrvs[0]->ExtendStartByLen( m_TParams.m_dDiam / 2 + dSafeZ) ; - } - - // se non ottimizzato e utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore - if ( ( ! bOptimizedZigZag || ! ( bOutRawLeadIn || m_bOpenOutRaw)) && m_TParams.m_nType == TT_MILL_NOTIP) { - if ( ! LeadInIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; - return false ; - } - } - - // se caso non ottimizzato calcolo curva offsettata del raggio utensile + sovramateriale + (se non lucidatura) extra double dTRad = m_TParams.m_dDiam / 2 ; double dOffs = dTRad + GetOffsR() ; - double dExtra = (( m_TParams.m_nType != TT_MILL_POLISHING) ? min( 0.1 * m_TParams.m_dDiam, 2.0) : 0) ; - OffsetCurve OffsCrv ; - if ( ! bOptimizedZigZag) { - if ( ! OffsCrv.Make( pCompo, - ( dOffs + dExtra), ICurve::OFF_FILLET)) { + double dExtra = (( m_TParams.m_nType != TT_MILL_POLISHING) ? min(0.1 * m_TParams.m_dDiam, 2.0) : 0) ; + + // vettore delle curve esterne Offsettate (per attacchi) e numero di Chunks + ICRVCOMPOPOVECTOR vCrvExt ; + int nChunks = 0 ; + + // copia della mia superificie + PtrOwner pSrfToPock( CloneSurfFlatRegion( pSrfPock)) ; + if ( IsNull( pSrfToPock)) + return false ; + + // scorro tutti i Chunks della regione per svuotarli + for ( int c = 0 ; c < pSrfToPock->GetChunkCount() ; c++) { + + // copio il Chunk (c)-esimo + PtrOwner pSrfChunk( CloneSurfFlatRegion( pSrfToPock->CloneChunk( c))) ; + if ( IsNull( pSrfChunk)) + return false ; + // superficie per ingressi ed uscite + PtrOwner pSrfLeanInOut( CloneSurfFlatRegion( pSrfChunk)) ; + + // determino il riferimento in base alla svuotatura + Frame3d frPocket ; + Point3d ptCen ; pSrfToPock->GetCentroid( ptCen) ; + frPocket.Set( ptCen, vtExtr) ; + frPocket.Rotate( ptCen, vtExtr, m_Params.m_dSideAngle) ; + + // porto la superificie nel nuovo sistema di riferimento + pSrfChunk->ToLoc( frPocket) ; + + // verifico se si tratta di caso ottimizzato + bool bOptimizedZigZag = false ; + bool bOutRawLeadIn = false ; + ICRVCOMPOPOVECTOR vpCrvs ; // vettore con i paths per il Chunk (c)-esimo + + if ( ! OptimizedZigZag( pSrfChunk, vtTool, dDepth, dSafeZ, frPocket, bOptimizedZigZag, vpCrvs)) + return false ; + if ( bOptimizedZigZag && ! vpCrvs.empty()) { + nChunks = 1; + // verifico se attacco fuori dal grezzo + Point3d ptStart ; + vpCrvs[0]->GetStartPoint( ptStart) ; + Vector3d vtDir ; + vpCrvs[0]->GetStartDir( vtDir) ; + ptStart += -vtDir * ( m_TParams.m_dDiam / 2 + dSafeZ) ; + ptStart.ToGlob( frPocket) ; + ptStart += -vtTool * dDepth ; + double dTestElev ; + if ( ! GetElevation( m_nPhase, ptStart, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElev) || dTestElev < EPS_SMALL) + bOutRawLeadIn = true ; + // sistemo attacco (per essere completamente fuori dal grezzo) + if ( bOutRawLeadIn || m_bOpenOutRaw) + vpCrvs[0]->ExtendStartByLen( m_TParams.m_dDiam / 2 + dSafeZ) ; + } + + // se non ottimizzato e utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore + if (( ! bOptimizedZigZag || ! ( bOutRawLeadIn || m_bOpenOutRaw)) && m_TParams.m_nType == TT_MILL_NOTIP) { + if ( ! LeadInIsOk()) { + m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; + return false; + } + } + + // se non sono nel caso ottimizzato, effettuo il primo Offset della regione e controllo quanti Chunks ottengo... + if ( ! bOptimizedZigZag) { + if ( ! pSrfChunk->Offset( - dOffs - dExtra, ICurve::OFF_FILLET)) { + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + return false ; + } + nChunks = pSrfChunk->GetChunkCount() ; // facendo il primo Offset il Chunk (c)-esimo può generare altri Chunks... + } + + // tratto ogni Chunk ottenuto come se fosse una superficie singola, quindi con la propria svuotatura + bool bStart = true ; // controllo se prima curva + for ( int cc = 0 ; cc < nChunks ; cc++) { // per ognuno di questi Chunks... + + PtrOwner pSrfZigZag( GetSurfFlatRegion( pSrfChunk->CloneChunk( cc))) ; + if ( IsNull( pSrfZigZag)) + return false ; + + if ( ! bOptimizedZigZag) { + vpCrvs.clear() ; + if ( ! CalcZigZag( pSrfZigZag, vpCrvs)) + return false ; + } + + // se lucidatura + if ( m_TParams.m_nType == TT_MILL_POLISHING) { + // ciclo sui percorsi + for (int k = 0; k < int( vpCrvs.size()); ++k) { + // se attacco a scivolo + if ( GetLeadInType() == POCKET_LI_GLIDE) { + double dU; + vpCrvs[k]->GetParamAtLength(m_Params.m_dLiTang, dU); + vpCrvs[k]->AddJoint(dU); + Point3d ptStart; + vpCrvs[k]->GetStartPoint(ptStart); + vpCrvs[k]->ModifyStart(ptStart + vtTool * m_Params.m_dLiElev); + } + // se uscita a scivolo + if ( GetLeadOutType() == POCKET_LO_GLIDE) { + double dLen, dU; + vpCrvs[k]->GetLength(dLen); + vpCrvs[k]->GetParamAtLength(dLen - m_Params.m_dLoTang, dU); + vpCrvs[k]->AddJoint(dU); + Point3d ptEnd; + vpCrvs[k]->GetEndPoint(ptEnd); + vpCrvs[k]->ModifyEnd(ptEnd + vtTool * m_Params.m_dLiElev); + } + } + } + + // inserisco i movimenti di svuotatura + for ( int j = 1 ; j <= nStep ; ++j) { + // ciclo sui percorsi + int nPath = int( vpCrvs.size()); + for ( int k = 0 ; k < nPath ; ++k) { + // ciclo sulle curve elementari + int nMaxInd = vpCrvs[k]->GetCurveCount() - 1; + for ( int i = 0 ; i <= nMaxInd ; ++i) { + // curva corrente + const ICurve* pCrvC = vpCrvs[k]->GetCurve( i) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) + return false; + pCurve->ToGlob( frPocket) ; + // aggiungo affondamento + pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; + // --- se PRIMA ENTITA' --- + if ( i == 0) { + // dati inizio entità + Point3d ptStart ; + pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; + pCurve->GetStartDir( vtStart) ; + // determino inizio attacco + Point3d ptP1 ; + if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) + return false; + // determino elevazione su inizio attacco + double dStElev ; + GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev) ; + dStElev = max(dStElev, j * dStep) ; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev); + if ( bUnderRaw) + dStElev = max( dStElev, j * dStep) ; + dStElev -= ( ptP1 - ptStart) * vtExtr ; + // se ottimizzata e attacco nel grezzo + if ( bOptimizedZigZag && !( bOutRawLeadIn || m_bOpenOutRaw)) { + // se richiesto attacco a zigzag o a spirale, l'elevazione va nell'attacco + if ( GetLeadInType() == POCKET_LI_ZIGZAG || GetLeadInType() == POCKET_LI_HELIX) { + ptP1 += vtExtr * dStElev ; + dStElev = 0 ; + } + } + // se inizio, approccio globale al punto iniziale + if ( bStart) { + if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutRawLeadIn || m_bOpenOutRaw)) { + m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; + return false ; + } + bStart = false ; + } + // altrimenti, approccio di collegamento + else { + if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutRawLeadIn || m_bOpenOutRaw)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false; + } + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, + bSplitArcs, bOutRawLeadIn || m_bOpenOutRaw)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + return false ; + } + } + // elaborazioni sulla curva corrente + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + SetFeed( GetFeed()) ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) + return false ; + } + else if ( pCurve->GetType() == CRV_ARC) { + ICurveArc* pArc = GetCurveArc( pCurve) ; + Point3d ptCen = pArc->GetCenter() ; + double dAngCen = pArc->GetAngCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + Point3d ptP3 ; + pArc->GetEndPoint(ptP3) ; + SetFeed( GetFeed()) ; + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + // --- se ULTIMA ENTITA' --- + if ( i == nMaxInd) { + // dati fine entità + Point3d ptEnd; + pCurve->GetEndPoint(ptEnd); + Vector3d vtEnd; + pCurve->GetEndDir(vtEnd); + // aggiungo uscita + double dEndElev = dElev; + Point3d ptP1; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev, true)) { + m_pMchMgr->SetLastError(2416, "Error in Pocketing : LeadOut not computable") ; + return false; + } + dEndElev = max( dEndElev, j * dStep) ; + // se lucidatura o caso ottimizzato e ultimo percorso di ultimo step, aggiungo retrazione + if (( m_TParams.m_nType == TT_MILL_POLISHING || bOptimizedZigZag) && k == nPath - 1 && j == nStep) { + if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Retract not computable") ; + return false; + } + } + // altrimenti, aggiungo retrazione di collegamento + else { + if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError(2418, "Error in Pocketing : Link not computable"); + return false; + } + } + } + } + } + } + } + + // Curva esterna (per passare vicino ai bordi) + + // se lucidatura o caso ottimizzato, non aggiungo contorno + if ( m_TParams.m_nType == TT_MILL_POLISHING /* || bOptimizedZigZag*/) + return true; + + bool bChangeFirst = true; + Point3d ptLastEnd; + + // Copio il Chunk c-esimo e lo porto nel sistema di riferimento della svuotatura + pSrfChunk.Set( CloneSurfFlatRegion( pSrfPock->CloneChunk( c))) ; + if ( IsNull( pSrfChunk)) + return false ; + pSrfChunk->ToLoc( frPocket) ; + + // creo l'Offset per le curve estene + if ( ! pSrfChunk->Offset( -dOffs, ICurve::OFF_FILLET)) { m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; return false ; } - nOffsCrvNbr = OffsCrv.GetCurveCount() ; - } - // ciclo sulle curve risultanti - bool bStart = true ; - while ( nOffsCrvNbr > 0) { + // creo un vettore con tutti i loop formati, aggiustando i loro punti iniziali + ICRVCOMPOPOVECTOR vCrvLoops ; + for ( int cc = 0 ; cc < pSrfChunk->GetChunkCount() ; cc++) { + for ( int l = 0 ; l < pSrfChunk->GetLoopCount( cc) ; l++) { - if ( bOptimizedZigZag) - nOffsCrvNbr = 0 ; // setto a zero per non rientrare nel while - else { - // recupero la prima curva di offset - PtrOwner pOffs( CreateCurveComposite()) ; - if ( IsNull( pOffs) || ! pOffs->AddCurve( OffsCrv.GetLongerCurve())) { + PtrOwner pOffs( CreateCurveComposite()) ; + if ( IsNull( pOffs) || ! pOffs->AddCurve( pSrfChunk->GetLoop( cc, l))) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false ; + } + + // se richiesto, la inverto + if ( m_Params.m_bInvert) + pOffs->Invert() ; + + // resetto le proprietà per attacchi + ResetCurveAllTempProp( pOffs) ; + + // aggiusto il punto iniziale + AdjustContourStart( pOffs) ; + + // verifico archi + VerifyArcs( pOffs) ; + + vCrvLoops.emplace_back( Release( pOffs)) ; + } + } + + // se sono nel caso ottimizzato devo togliere il loop esterno + if ( bOptimizedZigZag) { + double dMaxArea = -INFINITO ; int nJumpInd = 0 ; + for ( int i = 0 ; i < vCrvLoops.size() ; i++) { + double dArea ; vCrvLoops[i]->GetAreaXY( dArea) ; + if ( dArea > dMaxArea) { + dMaxArea = dArea ; + nJumpInd = i ; + } + } + ICRVCOMPOPOVECTOR vCrvHelp ; + for ( int i = 0 ; i < vCrvLoops.size() ; i++) { + if ( i != nJumpInd) + vCrvHelp.emplace_back( vCrvLoops[i]->Clone()) ; + } + vCrvLoops.clear() ; + vCrvLoops.resize( vCrvHelp.size()) ; + for ( int i = 0 ; i < vCrvHelp.size() ; i++) + vCrvLoops[i].Set( Release( vCrvHelp[i])) ; + } + + // guardo il punto finale in cui si trova la fresa + Point3d ptEnd ; + if( vpCrvs.size() > 0) + vpCrvs.back()->GetEndPoint( ptEnd) ; + + // ordino le curve a partire dal punto finale raggiunto della fresa + Point3d ptRef = ptEnd ; + double dMinDist = INFINITO ; + int nIndexSwitch = -1 ; + for ( int i = -1 ; i < vCrvLoops.size() - 1 ; i++) { + for ( int j = i + 1 ; j < vCrvLoops.size() ; j++) { + Point3d ptS ; vCrvLoops[j]->GetStartPoint( ptS) ; + if ( Dist( ptS, ptRef) < dMinDist) { + dMinDist = Dist( ptS, ptRef) ; + nIndexSwitch = j ; + } + } + if ( nIndexSwitch != i + 1) { + PtrOwner pCrvClosest( vCrvLoops[nIndexSwitch]->Clone()) ; + vCrvLoops[nIndexSwitch].Set(Release( vCrvLoops[i+1])) ; + vCrvLoops[i+1].Set( Release( pCrvClosest)) ; + } + vCrvLoops[i+1]->GetEndPoint( ptRef) ; + dMinDist = INFINITO ; + } + + for( int u = 0 ; u < vCrvLoops.size() ; u++) { + + // recupero la prima curva di offset disponibile + PtrOwner pOffs( CreateCurveComposite()); + if ( IsNull( pOffs) || ! pOffs->AddCurve( vCrvLoops[u]->Clone())) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; + return false; } - nOffsCrvNbr = OffsCrv.GetCurveCount() ; - // porto la curva nel riferimento della svuotatura - pOffs->ToLoc( frPocket) ; - - // calcolo i percorsi di svuotatura - vpCrvs.clear() ; - if ( ! CalcZigZag( pOffs, vpCrvs)) - return false ; - } - - // se lucidatura - if ( m_TParams.m_nType == TT_MILL_POLISHING) { - // ciclo sui percorsi - for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) { - // se attacco a scivolo - if ( GetLeadInType() == POCKET_LI_GLIDE) { - double dU ; - vpCrvs[k]->GetParamAtLength( m_Params.m_dLiTang, dU) ; - vpCrvs[k]->AddJoint( dU) ; - Point3d ptStart ; - vpCrvs[k]->GetStartPoint( ptStart) ; - vpCrvs[k]->ModifyStart( ptStart + vtTool * m_Params.m_dLiElev) ; - } - // se uscita a scivolo - if ( GetLeadOutType() == POCKET_LO_GLIDE) { - double dLen, dU ; - vpCrvs[k]->GetLength( dLen) ; - vpCrvs[k]->GetParamAtLength( dLen - m_Params.m_dLoTang, dU) ; - vpCrvs[k]->AddJoint( dU) ; - Point3d ptEnd ; - vpCrvs[k]->GetEndPoint( ptEnd) ; - vpCrvs[k]->ModifyEnd( ptEnd + vtTool * m_Params.m_dLiElev) ; - } - } - } - - // inserisco i movimenti di svuotatura - for ( int j = 1 ; j <= nStep ; ++ j) { - // ciclo sui percorsi - int nPath = int( vpCrvs.size()) ; - for ( int k = 0 ; k < nPath ; ++ k) { - // ciclo sulle curve elementari - int nMaxInd = vpCrvs[k]->GetCurveCount() - 1 ; - for ( int i = 0 ; i <= nMaxInd ; ++ i) { + // aggiungo la lavorazione di questa curva + Point3d ptP1 ; + for ( int j = 1; j <= nStep; ++j) { + // ciclo sulle curve elementari + int nMaxInd = pOffs->GetCurveCount() - 1 ; + for ( int i = 0 ; i <= nMaxInd ; ++i) { // curva corrente - const ICurve* pCrvC = vpCrvs[k]->GetCurve( i) ; + const ICurve* pCrvC = pOffs->GetCurve( i) ; // copio la curva PtrOwner pCurve( pCrvC->Clone()) ; if ( IsNull( pCurve)) return false ; pCurve->ToGlob( frPocket) ; // aggiungo affondamento - pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entità - if ( i == 0 ) { - // dati inizio entità + pCurve->Translate( -vtTool * ( dDepth - dElev + j * dStep)) ; + // --- se PRIMA ENTITA' --- + if ( i == 0) { + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; pCurve->GetStartDir( vtStart) ; - // determino inizio attacco - Point3d ptP1 ; - if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) - return false ; - // determino elevazione su inizio attacco - double dStElev ; - GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev) ; - dStElev = max( dStElev, j * dStep) ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw) - dStElev = max( dStElev, j * dStep) ; - dStElev -= ( ptP1 - ptStart) * vtExtr ; - // se ottimizzata e attacco nel grezzo - if ( bOptimizedZigZag && ! ( bOutRawLeadIn || m_bOpenOutRaw)) { - // se richiesto attacco a zigzag o a spirale, l'elevazione va nell'attacco - if ( GetLeadInType() == POCKET_LI_ZIGZAG || GetLeadInType() == POCKET_LI_HELIX) { - ptP1 += vtExtr * dStElev ; + // se primo step, approccio e affondo + if ( j == 1) { + // determino inizio attacco + if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) + return false ; + // determino elevazione su inizio attacco + double dStElev ; + if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = dStep; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; + if ( bUnderRaw) + dStElev = max( dStElev, dStep) ; + dStElev -= ( ptP1 - ptStart) * vtExtr ; + // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco + if ( GetLeadInType() == POCKET_LI_ZIGZAG || + GetLeadInType() == POCKET_LI_HELIX || + GetLeadInType() == POCKET_LI_GLIDE) { + ptP1 += vtExtr * dStElev; dStElev = 0 ; } - } - // se inizio, approccio globale al punto iniziale - if ( bStart) { - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutRawLeadIn || m_bOpenOutRaw)) { - m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; - return false ; - } - bStart = false ; - } - // altrimenti, approccio di collegamento - else { - if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutRawLeadIn || m_bOpenOutRaw)) { + // approccio al punto iniziale + if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr)) { m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; return false ; } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs)) { + m_pMchMgr->SetLastError(2415, "Error in Pocketing : LeadIn not computable"); + return false; + } } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, - bSplitArcs, bOutRawLeadIn || m_bOpenOutRaw)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; + // altrimenti solo collegamento + else { + SetFeed( GetStartFeed()) ; + GetCurrPos( ptP1) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs)) { + m_pMchMgr->SetLastError(2418, "Error in Pocketing : Link not computable") ; + return false; + } } } // elaborazioni sulla curva corrente @@ -2142,186 +2563,39 @@ Pocketing::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, con Vector3d vtN = pArc->GetNormVersor() ; Point3d ptP3 ; pArc->GetEndPoint( ptP3) ; - SetFeed( GetFeed()) ; + SetFeed( GetFeed()); if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entità + // se ultima entità if ( i == nMaxInd) { - // dati fine entità - Point3d ptEnd ; - pCurve->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pCurve->GetEndDir( vtEnd) ; - // aggiungo uscita - double dEndElev = dElev ; - Point3d ptP1 ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev, true)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; - return false ; - } - dEndElev = max( dEndElev, j * dStep) ; - // se lucidatura o caso ottimizzato e ultimo percorso di ultimo step, aggiungo retrazione - if ( ( m_TParams.m_nType == TT_MILL_POLISHING || bOptimizedZigZag) && k == nPath - 1 && j == nStep) { - if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Retract not computable") ; + // se ultimo step, uscita e retrazione di collegamento + if ( j == nStep) { + // dati fine entità + Point3d ptEnd ; + pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; + pCurve->GetEndDir( vtEnd) ; + // aggiungo uscita + double dEndElev = dElev ; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev)) { + m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; return false ; } - } - // altrimenti, aggiungo retrazione di collegamento - else { - if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; + // se ci sono ancora curve, aggiungo retrazione di collegamento + if ( pOffs->GetCurveCount() > 0) { + if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false ; + } } - } - } - } - } - } - } - - // se lucidatura o caso ottimizzato, non aggiungo contorno - if ( m_TParams.m_nType == TT_MILL_POLISHING || bOptimizedZigZag) - return true ; - - // calcolo seconda curva offsettata del raggio utensile + sovramateriale - OffsetCurve OffsCrv2 ; - if ( ! OffsCrv2.Make( pCompo, - dOffs, ICurve::OFF_FILLET)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; - return false ; - } - - // ciclo sulle curve risultanti - while ( OffsCrv2.GetCurveCount() > 0) { - - // recupero la prima curva di offset - PtrOwner pOffs2( CreateCurveComposite()) ; - if ( IsNull( pOffs2) || ! pOffs2->AddCurve( OffsCrv2.GetLongerCurve())) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - VerifyArcs( pOffs2) ; - - // se richiesto, la inverto - if ( m_Params.m_bInvert) - pOffs2->Invert() ; - - // sposto l'inizio a metà del tratto più lungo - AdjustContourStart( pOffs2) ; - - // aggiungo la lavorazione di questa curva - Point3d ptP1 ; - for ( int j = 1 ; j <= nStep ; ++ j) { - // ciclo sulle curve elementari - int nMaxInd = pOffs2->GetCurveCount() - 1 ; - for ( int i = 0 ; i <= nMaxInd ; ++ i) { - // curva corrente - const ICurve* pCrvC = pOffs2->GetCurve( i) ; - // copio la curva - PtrOwner pCurve( pCrvC->Clone()) ; - if ( IsNull( pCurve)) - return false ; - // aggiungo affondamento - pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entità - if ( i == 0 ) { - // dati inizio entità - Point3d ptStart ; - pCurve->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pCurve->GetStartDir( vtStart) ; - // se primo step, approccio e affondo - if ( j == 1) { - // determino inizio attacco - if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) - return false ; - // determino elevazione su inizio attacco - double dStElev ; - if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dStep ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw) - dStElev = max( dStElev, dStep) ; - dStElev -= ( ptP1 - ptStart) * vtExtr ; - // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco - if ( GetLeadInType() == POCKET_LI_ZIGZAG || - GetLeadInType() == POCKET_LI_HELIX || - GetLeadInType() == POCKET_LI_GLIDE) { - ptP1 += vtExtr * dStElev ; - dStElev = 0 ; - } - // approccio al punto iniziale - if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, bSplitArcs)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - } - // altrimenti solo collegamento - else { - SetFeed( GetStartFeed()) ; - GetCurrPos( ptP1) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } - } - } - // elaborazioni sulla curva corrente - if ( pCurve->GetType() == CRV_LINE) { - ICurveLine* pLine = GetCurveLine( pCurve) ; - Point3d ptP3 = pLine->GetEnd() ; - SetFeed( GetFeed()) ; - if ( AddLinearMove( ptP3) == GDB_ID_NULL) - return false ; - } - else if ( pCurve->GetType() == CRV_ARC) { - ICurveArc* pArc = GetCurveArc( pCurve) ; - Point3d ptCen = pArc->GetCenter() ; - double dAngCen = pArc->GetAngCenter() ; - Vector3d vtN = pArc->GetNormVersor() ; - Point3d ptP3 ; - pArc->GetEndPoint( ptP3) ; - SetFeed( GetFeed()) ; - if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) - return false ; - } - // se ultima entità - if ( i == nMaxInd) { - // se ultimo step, uscita e retrazione di collegamento - if ( j == nStep) { - // dati fine entità - Point3d ptEnd ; - pCurve->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pCurve->GetEndDir( vtEnd) ; - // aggiungo uscita - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; - return false ; - } - // se ci sono ancora curve, aggiungo retrazione di collegamento - if ( OffsCrv2.GetCurveCount() > 0) { - if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } - } - // altrimenti retrazione finale - else { - if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Retract not computable") ; - return false ; + // altrimenti retrazione finale + else { + if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Retract not computable") ; + return false ; + } } } } @@ -2335,22 +2609,37 @@ Pocketing::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, con //---------------------------------------------------------------------------- bool -Pocketing::CalcZigZag( const ICurveComposite* pOffs, - ICRVCOMPOPOVECTOR& vpCrvs) +Pocketing::CalcZigZag( const ISurfFlatRegion* pSrfZigZag, ICRVCOMPOPOVECTOR& vpCrvs) { + + // check parametri + if ( pSrfZigZag == nullptr) + return true ; + + // per tagli delle curve non sul secondo offset per zone non svuotate + double dExtra = (( m_TParams.m_nType != TT_MILL_POLISHING) ? min(0.1 * m_TParams.m_dDiam, 2.0) : 0) ; + + // creo il vettore dei contorni + ICRVCOMPOPOVECTOR vFirstOff ; + for ( int c = 0 ; c < pSrfZigZag->GetChunkCount(); c++) { + for ( int l = 0 ; l < pSrfZigZag->GetLoopCount(c); l++) { + vFirstOff.emplace_back( GetCurveComposite( pSrfZigZag->GetLoop( c, l)->Clone())) ; + } + } + // ingombro del contorno offsettato BBox3d b3Pocket ; - pOffs->GetLocalBBox( b3Pocket) ; + vFirstOff[0]->GetLocalBBox( b3Pocket) ; Point3d ptMin ; double dDimX, dDimY, dDimZ ; b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; // lunghezza del contorno offsettato - double dLen ; pOffs->GetLength( dLen) ; + double dLen ; vFirstOff[0]->GetLength( dLen) ; // passi in Y - int nYStep = static_cast( ceil( ( dDimY - 30 * EPS_SMALL) / GetSideStep())) ; + int nYStep = static_cast< int >( ceil(( dDimY - 30 * EPS_SMALL) / GetSideStep())) ; double dYStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ; - int nRef = ( ( nYStep + ( m_Params.m_bInvert ? 0 : 1)) % 2) ; + int nRef = (( nYStep + ( m_Params.m_bInvert ? 0 : 1)) % 2) ; // tratto valido struct Section { @@ -2359,72 +2648,78 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, Point3d ptE ; double dOs ; double dOe ; + int nOffIndS ; + int nOffIndE ; } ; - // raccolta di tratti - typedef vector> VECVECSECT ; - VECVECSECT vvSec ; + struct ParIsland { + double dU ; + int nInd ; + } ; + + // raccolta di tratti + typedef vector> VECVECSECT ; VECVECSECT vvSec ; vvSec.resize( nYStep + 1) ; // calcolo le linee di svuotatura int nCount = 0 ; - for ( int i = 0 ; i <= nYStep ; ++ i) { + for ( int i = 0 ; i <= nYStep ; ++i) { // determino senso bool bPlus = (( i % 2) == nRef) ; // 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)) { + if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } - // calcolo la classificazione della curva rispetto al contorno esterno offsettato - IntersCurveCurve intCC( *pLine, *pOffs) ; + + if ( ! bPlus) + pLine->Invert() ; + + // calcolo la classificazione della linea rispetto alla superificie CRVCVECTOR ccClass ; - if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass)) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - // determino gli intervalli di curva da conservare - Intervals inOk ; - for ( auto& ccOne : ccClass) { - if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M) - inOk.Add( ccOne.dParS, ccOne.dParE) ; - } - // inserisco i tratti validi (secondo X+ i pari, secondo X- i dispari) - double dParS, dParE ; - bool bFound = ( bPlus ? inOk.GetFirst( dParS, dParE) : inOk.GetLast( dParE, dParS)) ; - while ( bFound) { - // determino i dati della sezione - Section Sect ; - Sect.bActive = true ; - pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, Sect.ptS) ; - pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, Sect.ptE) ; - pOffs->GetParamAtPoint( Sect.ptS, Sect.dOs, 10 * EPS_SMALL) ; - pOffs->GetParamAtPoint( Sect.ptE, Sect.dOe, 10 * EPS_SMALL) ; - // inserisco nel contenitore - vvSec[i].emplace_back( Sect) ; - ++ nCount ; - // recupero successivo intervallo - bFound = ( bPlus ? inOk.GetNext( dParS, dParE) : inOk.GetPrev( dParE, dParS)) ; + pSrfZigZag->GetCurveClassification( *pLine, EPS_SMALL, ccClass) ; + for ( int j = 0 ; j < ccClass.size() ; j++) { + if ( ccClass[j].nClass == CRVC_IN) { // memorizzo il segmento + Section currSec; + currSec.bActive = true; + PtrOwner pSeg( GetCurveLine( pLine->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; + Point3d ptS, ptE ; + pSeg->GetStartPoint( ptS) ; pSeg->GetEndPoint( ptE) ; + currSec.ptS = ptS ; currSec.ptE = ptE ; + for ( int k = 0 ; k < vFirstOff.size() ; k++) { + if ( vFirstOff[k]->IsPointOn( ptS)) { + currSec.nOffIndS = k ; + double dUOS; vFirstOff[k]->GetParamAtPoint( ptS, dUOS) ; + currSec.dOs = dUOS ; + } + if ( vFirstOff[k]->IsPointOn( ptE)){ + currSec.nOffIndE = k ; + double dUOE; vFirstOff[k]->GetParamAtPoint( ptE, dUOE) ; + currSec.dOe = dUOE ; + } + } + vvSec[i].emplace_back( currSec) ; + ++nCount ; // numero di segmenti inseriti + } } } - // dominio del contorno - double dUmin, dUmax ; - pOffs->GetDomain( dUmin, dUmax) ; - double dUspan = dUmax - dUmin ; + int nStatus = 0 ; // 0 -> inizio oppure ho inserito una parte di isola | 2 -> sto inserendo un segmento + Point3d ptS_ref ; + PtrOwner plastLine( CreateCurveLine()) ; // creo i percorsi di svuotatura vpCrvs.reserve( nCount) ; int nI = -1, nJ = -1 ; while ( true) { // se sezione non valida - if ( nI < 0 || nJ < 0) { - // ricerco la prima valida - for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) { - for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) { + if ( nI < 0 || nJ < 0) { + // ricerco la prima valida ( il primo segmento con bActive messo a true) + for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++k) { + for (int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++l) { if ( vvSec[k][l].bActive) { nI = k ; nJ = l ; @@ -2432,9 +2727,10 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, } } // se trovata, creo nuova curva composita - if ( nI >= 0 && nJ >= 0) { + if ( nI >= 0 && nJ >= 0) { // creo la curva vpCrvs.emplace_back( CreateCurveComposite()) ; + nStatus = 0 ; // aggiungo punto iniziale vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ; } @@ -2442,21 +2738,111 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, else break ; } - // determino senso + // determino senso bool bPlus = (( nI % 2) == nRef) ; - // aggiungo la sezione alla curva + // aggiungo la sezione alla curva Section& Sec = vvSec[nI][nJ] ; Sec.bActive = false ; vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ; + + if (vpCrvs[0]->GetCurveCount() == 9) + int a = 0; + + if ( nStatus == 0) { // primo segmento per il raccordo smussato + plastLine.Set( GetCurveLine( vpCrvs.back()->GetLastCurve()->Clone())) ; + plastLine->GetStartPoint( ptS_ref) ; + } + if ( nStatus == 2) { // ho precedentemente aggiunto il bordo di un'isola, quindi mi salvo il secondo segmento + PtrOwner pSeg1( GetCurveLine( vpCrvs.back()->GetLastCurve()->Clone())) ; + PtrOwner pCrvLink( CreateCurveComposite()) ; + PtrOwner pSeg2( GetCurveLine( plastLine->Clone())) ; + if ( CalcBoundedZigZagLink( pSeg2, pSeg1, vFirstOff, pCrvLink)) { // se riesco a creare una semicirconferenza ... + double dUE ; // paramtro finale della curva totale fino ad ora + vpCrvs[vpCrvs.size() - 1]->GetParamAtPoint( ptS_ref, dUE) ; // punto finale della curva totale fino ad ora + PtrOwner pCrvToSave( CreateCurveComposite()) ; // tratto di curva precedente a pSeg1, pCrvLink, pSeg2 + if( dUE != 0) // se il tratto di curva precedente esiste ... + pCrvToSave.Set(GetCurveComposite(vpCrvs[vpCrvs.size() - 1]->CopyParamRange( 0, dUE))) ; // ... lo salvo + pCrvToSave->AddCurve( Release( pSeg2)) ; // aggiungo al tratto precedente il pSeg1 (trimmed alla fine) + pCrvToSave->AddCurve( Release( pCrvLink)) ; // aggiungo la semicirconferenza + pCrvToSave->AddCurve( Release( pSeg1)) ; // aggiungo il pSeg2 (trimmed all'inizio) + vpCrvs[vpCrvs.size() - 1]->Clear() ; + vpCrvs[vpCrvs.size() - 1]->AddCurve( Release( pCrvToSave)) ; // sistemo il percorso + } + else { // ... se non ho creato una semicirconferenza cerco di smussare pSeg1 - pCrvLink - pSeg2 (pCrvlink è il tratto di isola) + double dUS, dUE, dUS_I, dUE_I ; + vpCrvs[vpCrvs.size() - 1]->GetDomain( dUS, dUE) ; // dominio del percorso + vpCrvs[vpCrvs.size() - 1]->GetParamAtPoint( ptS_ref, dUS) ; // dUS -> parametro della curva totale nel punto iniziale di pSeg1 + PtrOwner pCrvToSmooth( CreateCurveComposite()) ; // cuvra smussata pSeg1 - pCrvLink - pSeg2 + pCrvToSmooth->AddCurve(vpCrvs[vpCrvs.size() - 1]->CopyParamRange( dUS, dUE)); + + double dLen1, dLenI_s, dLenI_e, dLen2 ; + + PtrOwner pCrv1( CreateCurveLine()) ; // segmento pSeg1 + Point3d pt1, pt2; + pCrvToSmooth->GetFirstCurve()->GetStartPoint( pt1) ; + pCrvToSmooth->GetFirstCurve()->GetEndPoint( pt2) ; + pCrv1->Set( pt1, pt2) ; + PtrOwner pCrv2( CreateCurveLine()); // segmento pSeg2 + pCrvToSmooth->GetLastCurve()->GetStartPoint( pt1) ; + pCrvToSmooth->GetLastCurve()->GetEndPoint( pt2) ; + pCrv2->Set(pt1, pt2) ; + + Point3d ptSH, ptEH ; // punto iniziale sul pSeg1 + pCrv1->GetEndPoint( ptSH) ; vpCrvs[vpCrvs.size() - 1]->GetParamAtPoint( ptSH, dUS_I) ; // parametro sulla curva globale di inizio di pCrvLink + pCrv2->GetStartPoint( ptEH) ; vpCrvs[vpCrvs.size() - 1]->GetParamAtPoint( ptEH, dUE_I) ; // paramtro sulla curva globale di fine di pCrvLink + PtrOwner pCrvIsl( CreateCurveComposite()) ; // segmento pCrvLink + pCrvIsl->AddCurve(vpCrvs[vpCrvs.size() - 1]->CopyParamRange( dUS_I, dUE_I)) ; + + + pCrv1->GetLength( dLen1) ; // lunghezza di pSeg1 + pCrv2->GetLength( dLen2) ; // lunghezza di pSeg2 + pCrvIsl->GetFirstCurve()->GetLength( dLenI_s); // lunghezza prima curva di PCrvLink + pCrvIsl->GetLastCurve()->GetLength( dLenI_e) ; // lunghezza ultima curva di pCrvLink + + // raccordo tra pSeg1 e pCrvLink + double dTollLeft = 1 - ( dLen1 - ( m_TParams.m_dTDiam / 16)) / dLen1 ; // % parametro sinistro per smusso + double dTollRight = ( m_TParams.m_dTDiam / 16) / dLenI_s ; // % parametro destro di smusso + PtrOwner pCrv_1I( CreateCurveComposite()) ; // curva unione di pSeg1 e pCrvLink smussata + pCrv_1I->AddCurve( pCrv1->Clone()); pCrv_1I->AddCurve( pCrvIsl->Clone()) ; + ModifyCurveToSmooted( pCrv_1I, dTollLeft, dTollRight) ; + + double dUS_1IH, dUE_1IH, dToTLen ; + pCrv_1I->GetDomain( dUS_1IH, dUE_1IH) ; // dominio della curva smussata tra pSeg1 e PCrvLink + pCrv_1I->GetLength( dToTLen) ; // nuova lunghezza della curva smussata tra pSeg1 e pCrvLink + dTollLeft = 1 - ( dLenI_e - (m_TParams.m_dTDiam / 16)) / dLenI_e; // % paramtro sinistro per smusso + dTollRight = ( m_TParams.m_dTDiam / 16) / dLen2 ; // % parametro destro per smusso + PtrOwner pCrv_I2( CreateCurveComposite()) ; // curva unione del primo smusso con pSeg2 (il tutto smussato) + pCrv_I2->AddCurve( pCrv_1I->Clone()) ; pCrv_I2->AddCurve( pCrv2->Clone()) ; + ModifyCurveToSmooted( pCrv_I2, dTollLeft, dTollRight) ; + + PtrOwner pCrvToSave( CreateCurveComposite()) ; + if ( dUS != 0) + pCrvToSave->AddCurve(( vpCrvs[vpCrvs.size() - 1]->CopyParamRange( 0, dUS))) ; + + pCrvToSave->AddCurve( Release( pCrv_I2)) ; + vpCrvs[vpCrvs.size() - 1]->Clear() ; + vpCrvs[vpCrvs.size() - 1]->AddCurve(Release( pCrvToSave)) ; + + } + // pSeg2 ora diventa pSeg1 e il procedimento si itera per tutto il percorso + plastLine.Set( GetCurveLine( vpCrvs.back()->GetLastCurve()->Clone())) ; + plastLine->GetStartPoint( ptS_ref) ; + } // cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno - double dUstart = Sec.dOe ; - double dUref = ( bPlus ? INFINITO : - INFINITO) ; + double dUstart = Sec.dOe ; + int nIndexIslandE = Sec.nOffIndE ; // isola di arrivo + double dUmin, dUmax ; + vFirstOff[nIndexIslandE]->GetDomain( dUmin, dUmax) ; + double dUspan = dUmax - dUmin ; + double dUref = ( bPlus ? INFINITO : -INFINITO) ; int nNextI = -1 ; int nNextJ = -1 ; - int li = nJ + 1 ; - for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) { - for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) { - if ( ! vvSec[k][l].bActive) + int li = nJ + 1 ; + for (int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++k) { + for ( int l = li ; l < int( vvSec[k].size()) ; ++l) { + if ( ! vvSec[k][l].bActive) // se sezione non attiva... non la considero + continue ; + if ( vvSec[k][l].nOffIndS != nIndexIslandE) // se isola diversa... non la considero continue ; double dU = vvSec[k][l].dOs ; if ( bPlus) { @@ -2480,17 +2866,17 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, } li = 0 ; } - // se trovato, aggiungo il tratto di contorno e continuo + // se trovato, controllo il contorno dell'isola if ( nNextI != -1) { PtrOwner pCopy ; if ( bPlus) { - if ( dUref > dUmax) + if ( dUref > dUmax) dUref -= dUspan ; - pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ; + pCopy.Set( vFirstOff[nIndexIslandE]->CopyParamRange( dUstart, dUref)) ; if ( ! IsNull( pCopy)) { double dCLen ; pCopy->GetLength( dCLen) ; if ( dCLen > 0.5 * dLen) { - pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ; + pCopy.Set( vFirstOff[nIndexIslandE]->CopyParamRange( dUref, dUstart)) ; if ( ! IsNull( pCopy)) pCopy->Invert() ; } @@ -2499,19 +2885,23 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, else { if ( dUref < dUmin) dUref += dUspan ; - pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ; + pCopy.Set( vFirstOff[nIndexIslandE]->CopyParamRange( dUref, dUstart)) ; if ( ! IsNull( pCopy)) { pCopy->Invert() ; - double dCLen ; pCopy->GetLength( dCLen) ; + double dCLen; pCopy->GetLength( dCLen) ; if ( dCLen > 0.5 * dLen) - pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ; + pCopy.Set( vFirstOff[nIndexIslandE]->CopyParamRange( dUstart, dUref)) ; } } + // controllo che nel percorso scelto non ritorni indietro superando la precendete passata BBox3d b3Copy ; if ( ! IsNull( pCopy)) pCopy->GetLocalBBox( b3Copy) ; - if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { + if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { // tengo la curva (non ritorno indietro più dello step) + Point3d ptS, ptE ; vpCrvs.back()->AddCurve( Release( pCopy)) ; + nStatus = 2 ; + // aggiungo il Link nI = nNextI ; nJ = nNextJ ; } @@ -2525,22 +2915,208 @@ Pocketing::CalcZigZag( const ICurveComposite* pOffs, nJ = -1 ; } } + return true ; } //---------------------------------------------------------- bool -Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, double dSafeZ, +Pocketing::GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICURVEPOVECTOR& vLinks, ISurfFlatRegion* pSrfToCut) { + + // controllo dei parametri + if ( vFirstOffs.size() == 0 || vCrvs.size() < vFirstOffs.size() ) + return false ; + pSrfToCut->Clear() ; + + // 1) creo la regione esterna + PtrOwner pSrfExtern( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfExtern)) + return false ; + + for ( int i = 0 ; i < vFirstOffs.size() ; i++) { + if ( i == 0) + pSrfExtern->AddExtLoop( vFirstOffs[i]->Clone()) ; + else { + ICurve* pCrvIntLoop( vFirstOffs[i]->Clone()) ; + if ( ! pCrvIntLoop->Invert() || ! pSrfExtern->AddIntLoop( pCrvIntLoop)) + return false ; + } + } + + // 2) Creo la regione svuotata dal Tool + PtrOwner pSrfTool( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfTool)) + return false ; + + for ( int i = 0 ; i < vCrvs.size(); i++) { + PtrOwner pSrfToolRegOffi( GetSurfFlatRegionFromFatCurve( vCrvs[i]->Clone(), m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, false, false)) ; + if ( i == 0) + pSrfTool.Set( Release( pSrfToolRegOffi)) ; + else + pSrfTool->Add( *Release( pSrfToolRegOffi)) ; + } + + for ( int i = 0; i < vLinks.size(); i++) { + if ( ! IsNull( vLinks[i])) { + PtrOwner pSrfToolRegLinki( GetSurfFlatRegionFromFatCurve( vLinks[i]->Clone(), m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, false, false)) ; + pSrfTool->Add( *Release( pSrfToolRegLinki)) ; + } + } + + // 3) Creo la regione contenente tutte le parti non svuotate + pSrfToCut->CopyFrom( pSrfExtern->Clone()) ; + if ( ! pSrfToCut->Subtract( *pSrfTool)) + return false ; + + return true ; +} + +//---------------------------------------------------------- +bool +Pocketing::CalcBoundedZigZagLink( ICurveLine* pCrv1, ICurveLine* pCrv2, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink, int nIndexCut) { + + // controllo dei parametri + if ( pCrv1 == nullptr || pCrv2 == nullptr) + return false ; + if ( ! ( nIndexCut == 1 || nIndexCut == 2 || nIndexCut == 3 || nIndexCut == 4)) + return false ; + pCrvLink->Clear() ; + + // prendo i parametri per il raccordo + Vector3d vtS, vtE, vtH ; + pCrv1->GetEndDir( vtS) ; + pCrv2->GetStartDir( vtE) ; + Point3d ptS, ptE, ptE1, ptS2 ; + pCrv1->GetEndPoint( ptS) ; + pCrv2->GetStartPoint( ptE) ; + vtH = ptE - ptS ; + double dLen1, dLen2 ; + pCrv1->GetLength( dLen1) ; + pCrv2->GetLength( dLen2) ; + double dUS1, dUE1, dUS2, dUE2 ; + pCrv1->GetDomain( dUS1, dUE1) ; + pCrv2->GetDomain( dUS2, dUE2) ; + double dAngle, dAngleH ; + double dDist = Dist( ptS, ptE) ; + + PtrOwner pCrvH1( CreateCurveLine()) ; + PtrOwner pCrvH2( CreateCurveLine()) ; + PtrOwner pCrvTempLink( CreateCurveComposite()) ; + PtrOwner pCrvTest( CreateCurveComposite()) ; + + if ( pCrvH1 == nullptr || pCrvH2 == nullptr || pCrvTempLink == nullptr || pCrvTest == nullptr) + return false ; + + if ( vtS.GetAngle( vtE, dAngle) && abs( dAngle) < 180 + 5 * EPS_SMALL && abs( dAngle) > 180 - 5 * EPS_SMALL + && vtH.GetAngle( vtE, dAngleH) && abs( dAngleH) < 90 + 5 * EPS_SMALL && abs( dAngleH) > 90 - 5 * EPS_SMALL && dLen1 > dDist && dLen2 > dDist) { + // creo una semi circonferenza + double dRad = dDist / 2 ; + ICurveArc* pSemiCir( CreateCurveArc()) ; + Point3d ptNS, ptNE ; + + switch ( nIndexCut) + { + case 1: // taglio solo la prima + pCrv1->GetParamAtLength( dLen1 - dRad, dUE1) ; + break ; + case 2: // taglio solo la seconda + pCrv2->GetParamAtLength( dRad, dUS2) ; + break ; + case 3: // taglio entrambe + pCrv1->GetParamAtLength( dLen1 - dRad, dUE1) ; + pCrv2->GetParamAtLength( dRad, dUS2) ; + break ; + default: + break ; + } + + pCrv1->GetPointD1D2( dUE1, ICurve::FROM_MINUS, ptNS); + pCrv2->GetPointD1D2( dUS2, ICurve::FROM_PLUS, ptNE); + if (pSemiCir->Set2PVN(ptNS, ptNE, vtS, Z_AX)) { + pCrvH1.Set(GetCurveLine(pCrv1->CopyParamRange(dUS1, dUE1))); + pCrvH2.Set(GetCurveLine(pCrv2->CopyParamRange(dUS2, dUE2))); + pCrvTempLink->AddCurve(pSemiCir->Clone()); + } + } + else if( dLen1 - m_TParams.m_dDiam / 4 > 50 * EPS_SMALL && dLen2 - m_TParams.m_dDiam / 4 > 50 * EPS_SMALL) { + // se non riesco collego con un segmento ? no, esco dalla funzione + return false ; + + switch ( nIndexCut) + { + case 1: // taglio solo la prima + pCrv1->GetParamAtLength( dLen1 - m_TParams.m_dDiam / 4, dUE1) ; + break ; + case 2: // taglio solo la seconda + pCrv2->GetParamAtLength( m_TParams.m_dDiam / 4, dUS2) ; + break ; + case 3: // taglio entrambe + pCrv1->GetParamAtLength( dLen1 - m_TParams.m_dDiam / 4, dUE1) ; + pCrv2->GetParamAtLength( m_TParams.m_dDiam / 4, dUS2) ; + break ; + default: + break; + } + + pCrvH1.Set( GetCurveLine( pCrv1->CopyParamRange( dUS1, dUE1))) ; + pCrvH2.Set( GetCurveLine( pCrv2->CopyParamRange( dUS2, dUE2))) ; + pCrvH1->GetEndPoint( ptS) ; + pCrvH1->GetEndDir( vtS) ; + pCrvH2->GetStartPoint( ptE) ; + pCrvH2->GetStartDir( vtE) ; + if ( ! CalcBoundedSmootedLink( ptS, vtS, ptE, vtE, 0.5, vOffIslands, pCrvTempLink)) + return false ; + } + else { + return false ; + } + + // controllo finale sui raccordi ammissibili ... + if ( pCrvTest->AddCurve( pCrvH1->Clone()) && pCrvTest->AddCurve( pCrvTempLink->Clone()) && pCrvTest->AddCurve( pCrvH2->Clone())) { + //pCrv1->Clear() ; + //pCrv1->AddCurve( Release( pCrvH1)) ; + Point3d pt1, pt2; + pCrvH1->GetStartPoint(pt1); + pCrvH1->GetEndPoint(pt2); + pCrv1->Set(pt1, pt2); + pCrvLink->Clear() ; + //m_pGeomDB->AddGeoObj(GDB_ID_NULL, GDB_ID_ROOT, pCrvTempLink->Clone()); + pCrvLink->AddCurve( pCrvTempLink->Clone()) ; + pCrvH2->GetStartPoint(pt1); + pCrvH2->GetEndPoint(pt2); + pCrv2->Set(pt1, pt2); + //pCrv2->Clear() ; + //pCrv2->AddCurve( pCrvH2->Clone()) ; + + return true ; + } + + return false ; +} + +//---------------------------------------------------------- +bool +Pocketing::OptimizedZigZag( ISurfFlatRegion* pSrf, const Vector3d& vtTool, double dDepth, double dSafeZ, Frame3d& frPocket, bool& bOptimizedZigZag, ICRVCOMPOPOVECTOR& vpCrvs) { - // recupero la curva originale che delimita la svuotatura - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; + // clono la superficie (chunk c-esimo dell'originale) + PtrOwner pSrfPocket( CloneSurfFlatRegion( pSrf)) ; + if ( IsNull( pSrfPocket)) + return false ; + + // recupero la curva ORIGINALE che delimita la svuotatura (questa curva non risente dell'offset fatto dalla superificie creata dopo) + int nCrvId = pSrfPocket->GetLoop( 0, 0)->GetTempProp( 0) ; PtrOwner pCrvPocket( CloneCurveComposite( m_pGeomDB->GetGeoObj( nCrvId))) ; if ( IsNull( pCrvPocket)) - return false ; + return true ; + + // porto la curva nel sistema di riferimento locale pCrvPocket->ToLoc( frPocket) ; + + // setto proprietà sulle curve SetCurveAllTempProp( nCrvId, pCrvPocket) ; pCrvPocket->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + // sistemo senso antiorario visto dalla direzione di estrusione Vector3d vtPocket; pCrvPocket->GetExtrusion( vtPocket) ; Plane3d plPlane ; double dArea ; @@ -2550,7 +3126,7 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, // recupero gli id dei lati chiusi INTVECTOR vnInfoClosed ; - for( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i ++) { + for( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i++) { int nProp ; if ( pCrvPocket->GetCurveTempProp( i, nProp) && nProp == 0) vnInfoClosed.push_back( i) ; @@ -2559,21 +3135,21 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, // modifico pCrvPocket per poterla passare a CalcZigZag bool bTwoOpposite ; - Vector3d vtDir ; + Vector3d vtDir ; // direzione principale del segmento più lungo (linea) switch ( nClosedSides) { - case 0 : + case 0 : // 0 lati CHIUSI -> tutti APERTI ZigZagOptimizedNoClosedEdges( pCrvPocket, bOptimizedZigZag, vtDir) ; break ; - case 1 : + case 1 : // 1 lato CHIUSO ZigZagOptimizedOneClosedEdge( pCrvPocket, vnInfoClosed[0], bOptimizedZigZag, vtDir) ; break ; - case 2 : + case 2 : // 2 lati CHIUSI ZigZagOptimizedTwoClosedEdges( pCrvPocket, vnInfoClosed, bOptimizedZigZag, bTwoOpposite, vtDir) ; break ; - case 3 : + case 3 : // 3 lati CHIUSI ZigZagOptimizedThreeClosedEdges( pCrvPocket, vnInfoClosed, bOptimizedZigZag, bTwoOpposite, vtDir) ; break ; - default : + default : // nessuna ottimizzazione... bOptimizedZigZag = false ; break ; } @@ -2589,13 +3165,72 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, if ( nClosedSides == 0) dAng += m_Params.m_dSideAngle ; pCrvPocket->ToGlob( frPocket) ; + + Frame3d frameH( frPocket) ; + Point3d ptCen = frPocket.Orig() ; Vector3d vtExtr = frPocket.VersZ() ; frPocket.Rotate( ptCen, vtExtr, -dAng) ; pCrvPocket->ToLoc( frPocket) ; + // vettore contenente le curve di primo Offset ottimizzate ( bordo esterno Optimized e isole ) + ICRVCOMPOPOVECTOR vFirstOffsets ;; + vFirstOffsets.emplace_back( Release( pCrvPocket)) ; // la curva esterna modificata + + double dTRad = m_TParams.m_dDiam / 2 ; + double dOffs = dTRad + GetOffsR() ; + double dExtra = (( m_TParams.m_nType != TT_MILL_POLISHING) ? min( 0.1 * m_TParams.m_dDiam, 2.0) : 0) ; + + PtrOwner pSrfPocketClone( CloneSurfFlatRegion( pSrfPocket)) ; + if ( IsNull( pSrfPocketClone)) + return false ; + + if ( ! pSrfPocketClone->Offset( - dOffs - dExtra, ICurve::OFF_FILLET)) { // le isole interne vanno Offsettate + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + return false ; + } + + ICRVCOMPOPOVECTOR vCrvAllLoops ; + double dMaxArea = -INFINITO; int nIndex = -1; int p = 0 ; // p è il # di loop totali + + for ( int cu = 0 ; cu < pSrfPocketClone->GetChunkCount(); cu++) { + for ( int l = 0 ; l < pSrfPocketClone->GetLoopCount( cu); l++) { + // inserisco i loops portandoli nel nuovo sistema di riferimento + PtrOwner pCrvLoop( GetCurveComposite( pSrfPocketClone->GetLoop( cu, l))) ; + if ( IsNull( pCrvLoop)) + return false ; + pCrvLoop->ToGlob( frameH) ; + pCrvLoop->ToLoc( frPocket) ; + + double dArea; pCrvLoop->GetAreaXY( dArea) ; + if ( dArea > dMaxArea) { + dMaxArea = dArea ; + nIndex = p ; + } + + vCrvAllLoops.emplace_back( Release( pCrvLoop)) ; + p++ ; + } + } + + for ( int i = 0 ; i < vCrvAllLoops.size() ; i++) { + if ( i != nIndex) { + vFirstOffsets.emplace_back( vCrvAllLoops[i]->Clone()) ; + } + } + + // creo la superficie da svuotare ottimizzata + SurfFlatRegionByContours pSrfMod ; + for ( int i = 0 ; i < vFirstOffsets.size() ; i++) + pSrfMod.AddCurve( vFirstOffsets[i]->Clone()) ; + PtrOwner pSrfZigZag( GetSurfFlatRegion( pSrfMod.GetSurf())) ; + if ( IsNull( pSrfZigZag)) + return false ; + if ( AreOppositeVectorApprox( vtExtr, pSrfZigZag->GetNormVersor())) + pSrfZigZag->Invert() ; + // calcolo il percorso di svuotatura - if ( ! CalcZigZag( pCrvPocket, vpCrvs)) + if ( ! CalcZigZag( pSrfZigZag, vpCrvs)) return false ; // se un lato chiuso @@ -2607,11 +3242,11 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, vpCrvs[0]->GetStartPoint( ptStart) ; Vector3d vtDir ; vpCrvs[0]->GetStartDir( vtDir) ; - Point3d ptTest = ptStart + ( -vtDir) * ( m_TParams.m_dDiam / 2 + dSafeZ) ; + Point3d ptTest = ptStart + ( - vtDir) * ( m_TParams.m_dDiam / 2 + dSafeZ) ; ptTest.ToGlob( frPocket) ; ptTest += - vtTool * dDepth ; double dTestElev ; - // se è nel grezzo provo a ruotare di 90 gradi + // se è nel grezzo provo a ruotare di 90 gradi if ( GetElevation( m_nPhase, ptTest, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElev) && dTestElev > EPS_SMALL) { Vector3d vtDirO = vtDir ; vtDirO.Rotate( Z_AX, ( m_Params.m_bInvert ? -90 : 90)) ; @@ -2619,7 +3254,7 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, ptTestO.ToGlob( frPocket) ; ptTestO += - vtTool * dDepth ; double dTestElevO ; - // se è fuori dal grezzo uso inizio ruotato + // se è fuori dal grezzo uso inizio ruotato if ( ! GetElevation( m_nPhase, ptTestO, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElevO) || dTestElevO < EPS_SMALL) { Point3d ptNewStart = ptStart + vtDirO ; vpCrvs[0]->AddLine( ptNewStart, false) ; @@ -2627,7 +3262,7 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, } } // se due lati chiusi consecutivi o tre lati chiusi... - else if ( ( nClosedSides == 2 || nClosedSides == 3) && ! bTwoOpposite) { + else if (( nClosedSides == 2 || nClosedSides == 3) && ! bTwoOpposite) { // inverto il percorso vpCrvs[0]->Invert() ; // allungo opportunamente inizio e fine @@ -2655,7 +3290,7 @@ Pocketing::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, bool Pocketing::ZigZagOptimizedNoClosedEdges( ICurveComposite* pCrvPocket, bool& bOptimizedZigZag, Vector3d& vtDir) { - // individuo il segmento di retta più lungo + // individuo il segmento di retta più lungo int nMax = -1 ; double dMaxLen = 0 ; for ( int i = 0 ; i < int( pCrvPocket->GetCurveCount()) ; ++ i) { @@ -2703,7 +3338,7 @@ Pocketing::ZigZagOptimizedOneClosedEdge( ICurveComposite* pCrvPocket, int nClose pCrv->ExtendStartByLen( 300) ; pCrv->ExtendEndByLen( 300) ; - // sarà la prima curva del percorso + // sarà la prima curva del percorso if ( ! CutCurveWithLine( pCrvPocket, pCrv)) return false ; @@ -2719,8 +3354,9 @@ Pocketing::ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INT // verifico che i lati chiusi siano linee PtrOwner pCrv1( CloneCurveLine( pCrvPocket->GetCurve( vnClosedIds[0]))) ; PtrOwner pCrv2( CloneCurveLine( pCrvPocket->GetCurve( vnClosedIds[1]))) ; - if ( IsNull( pCrv1) || IsNull( pCrv2)) + if ( IsNull( pCrv1) || IsNull( pCrv2)) return true ; + // verifico abbiano direzioni opposte Vector3d vtDir1, vtDir2 ; pCrv1->GetStartDir( vtDir1) ; @@ -2749,7 +3385,7 @@ Pocketing::ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INT pCrv1->SetExtrusion( vtExtr) ; pCrv2->SetExtrusion( vtExtr) ; - // determino la curva chiusa più lunga + // determino la curva chiusa più lunga double dLen1 ; pCrv1->GetLength( dLen1) ; double dLen2 ; pCrv2->GetLength( dLen2) ; @@ -2774,7 +3410,7 @@ Pocketing::ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INT if ( ! CutCurveWithLine( pCrvPocket, pCrv1)) return false ; - // sarà la prima curva del percorso + // sarà la prima curva del percorso pCrv2->SimpleOffset( -dOffs) ; pCrv2->ExtendStartByLen( 300) ; pCrv2->ExtendEndByLen( 300) ; @@ -2862,7 +3498,7 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I if ( ! CutCurveWithLine( pCrvPocket, pCrv3)) return false ; - // sarà la prima curva del percorso + // sarà la prima curva del percorso pCrv2->SimpleOffset( -dOffs) ; pCrv2->ExtendStartByLen( 300) ; pCrv2->ExtendEndByLen( 300) ; @@ -2878,8 +3514,8 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I Pocketing::ZigZagOptimizedComputeOffset( ICurveComposite* pCrvPocket, const Vector3d& vtMainDir, int nOffsettedEdgesOnY, const INTVECTOR& vnClosedIds) { - // calcolo il side step che verrà utilizzato in CalcZigZag - Frame3d frLoc ; + // calcolo il side step che verrà utilizzato in CalcZigZag + /*Frame3d frLoc; if ( ! frLoc.Set( ORIG, Z_AX, vtMainDir)) return true ; BBox3d b3Loc ; @@ -2896,7 +3532,7 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I // individuo i lati vicini a quelli closed for ( int i = 0 ; i < ( int)vnClosedIds.size() ; i ++) { - int nNext = vnClosedIds[i] == pCrvPocket->GetCurveCount() - 1 ? 0 : vnClosedIds[i] + 1 ; + int nNext = vnClosedIds[i] == pCrvPocket->GetCurveCount() - 1 ? 0 : vnClosedIds[i] + 1 ; int nPrev = vnClosedIds[i] == 0 ? pCrvPocket->GetCurveCount() - 1 : vnClosedIds[i] - 1 ; pCrvPocket->SetCurveTempProp( nNext, 1, 1) ; pCrvPocket->SetCurveTempProp( nPrev, 1, 1) ; @@ -2904,12 +3540,12 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I // verifico se resteranno aree residue e calcolo eventuale offset per pCrvPocket double dOffs = 0 ; - for ( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i ++) { + for (int i = 0; i < pCrvPocket->GetCurveCount(); i++) { double dOffsTmp = 0 ; double dVal = 0 ; - if ( pCrvPocket->GetCurve(i)->GetType() == CRV_LINE) { + if ( pCrvPocket->GetCurve( i)->GetType() == CRV_LINE) { Vector3d vtDir ; if ( ! pCrvPocket->GetCurve( i)->GetStartDir( vtDir)) return false ; @@ -2920,14 +3556,14 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I pCrvPocket->GetCurve( i)->GetLength( dLen) ; if ( nProp == 1 && dLen > 1000 * EPS_SMALL) { - // gestione speciale se vicino al lato closed + // gestione speciale se vicino al lato closed double dCosAlpha = vtMainDir * vtDir ; - if ( abs( dCosAlpha) > EPS_SMALL && abs( dCosAlpha) < 1 - EPS_SMALL) + if ( abs( dCosAlpha) > EPS_SMALL && abs( dCosAlpha) < 1 - EPS_SMALL) // se non quasi paralleli o quasi perpendicolari dOffsTmp = abs( 0.5 * m_TParams.m_dDiam * dCosAlpha) ; } else { double dSinAlpha = ( vtMainDir ^ vtDir).Len() ; - if ( abs( dSinAlpha) > EPS_SMALL) + if ( abs( dSinAlpha) > EPS_SMALL) // se sono quasi perpendicolari dVal = ( dYSideStep - 0.5 * m_TParams.m_dDiam) / dSinAlpha - 0.5 * m_TParams.m_dDiam ; if ( dVal > EPS_SMALL) { double dCosAlpha = vtMainDir * vtDir ; @@ -2937,7 +3573,9 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I } if ( dOffsTmp > dOffs) dOffs = dOffsTmp ; - } + }*/ + + double dOffs = m_TParams.m_dDiam / 2 + 5 * EPS_SMALL; if ( dOffs > EPS_SMALL) { // calcolo offset @@ -2953,7 +3591,7 @@ Pocketing::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const I pCrvPocket->Clear() ; pCrvPocket->AddCurve( OffsCrv.GetCurve()) ; } - + return true ; } @@ -2987,305 +3625,429 @@ Pocketing::CutCurveWithLine( ICurveComposite* pCrvA, const ICurveLine* pCrvB) //---------------------------------------------------------------------------- bool -Pocketing::AddOneWay( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs) +Pocketing::AddOneWay( const ISurfFlatRegion* pSrfPock, const Vector3d& vtTool, const Vector3d& vtExtr, + double dDepth, double dElev, double dOkStep, bool bSplitArcs) { + // recupero distanze di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; double dSafeAggrBottZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeAggrBottZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // se utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore + // se utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore if ( m_TParams.m_nType == TT_MILL_NOTIP) { - if ( ! LeadInIsOk()) { + if ( ! LeadInIsOk()) { m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; - return false ; + return false; } } // determino numero e affondamento degli step int nStep = 1 ; - nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + nStep = max( 1, static_cast( ceil(dElev / dOkStep))) ; double dStep = dElev / nStep ; - // calcolo curva offsettata del raggio utensile + sovramateriale double dTRad = 0.5 * m_TParams.m_dDiam ; double dOffs = dTRad + GetOffsR() ; - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCompo, - dOffs, ICurve::OFF_FILLET)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + double dExtra = min( 0.1 * m_TParams.m_dDiam, 1.0) ; + + // copio la regione da svuotare, il Chunk (c)-esimo + PtrOwner pSrfToPock( pSrfPock->Clone()) ; + if ( IsNull( pSrfToPock)) return false ; + + // classifico i chunks in modo da creare delle regioni ideali; una regione ideale è formata da un chunk principale + // con tutti gli altri contenuti in esso ( in questo modo ottimizzo i percorsi per i bordi) + typedef vector> SRFFLTVECTOR ; + SRFFLTVECTOR vSrfFlat ; + INTVECTOR vChunksAvailable( pSrfToPock->GetChunkCount(), 1) ; + + for ( int c = 0 ; c < pSrfToPock->GetChunkCount() ; c++) { + PtrOwner pSrfIdeal( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfIdeal)) + return false ; + if ( vChunksAvailable[c] == 1) { // se Chunk valido... + PtrOwner pCrvExt( GetCurveComposite( pSrfToPock->GetLoop( c, 0))) ; + if ( IsNull( pCrvExt)) + return false ; + pSrfIdeal.Set( pSrfToPock->CloneChunk( c)) ; + vChunksAvailable[c] = -1 ; + for ( int i = 0; i < vChunksAvailable.size(); i++) { + if ( vChunksAvailable[i] == 1) { // se chunk valido... + PtrOwner pCrvExtC( GetCurveComposite( pSrfToPock->GetLoop( i, 0))) ; + if ( IsNull( pCrvExtC)) + return false ; + IntersCurveCurve intCC( *pCrvExtC, *pCrvExt) ; + CRVCVECTOR ccClass ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN) { + pSrfIdeal->Add( *pSrfToPock->CloneChunk( i)) ; + vChunksAvailable[i] = -1 ; + } + } + } + } + if ( pSrfIdeal->GetChunkCount() > 0) { + vSrfFlat.emplace_back( Release( pSrfIdeal)) ; + } } - // ciclo sulle curve risultanti - while ( OffsCrv.GetCurveCount() > 0) { + // === per ogni superificie ideale creo 2 Offsets ===, + // - dOffs con le curve da percorrere all'inizio ( bordo da percorrere, senza mai superarlo) + // - dOffs - dExtra per definire le curve interne della svuotatura ( bordo immaginario per il OneWay ) - // recupero la prima curva di offset - PtrOwner pOffs( CreateCurveComposite()) ; - if ( IsNull( pOffs) || ! pOffs->AddCurve( OffsCrv.GetLongerCurve())) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + for ( int nIdealSurf = 0 ; nIdealSurf < vSrfFlat.size() ; nIdealSurf++) { + + // === PRIMO OFFSET === + PtrOwner pSrfIdeal( CloneSurfFlatRegion( vSrfFlat[nIdealSurf])->Clone()) ; + if ( IsNull( pSrfIdeal)) + return false ; + + // per entrate ed uscite + PtrOwner pSrfLeanInOut( CloneSurfFlatRegion( pSrfIdeal)) ; + + // effettuo il primo Offset della regione e controllo quanti Chunks ottengo + if ( ! pSrfIdeal->Offset( - dOffs, ICurve::OFF_FILLET)) { + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; return false ; } - // se richiesto, la inverto - if ( m_Params.m_bInvert) - pOffs->Invert() ; + // salvo tutte le curve di Offset in un vettore per poi ordinarle + ICRVCOMPOPOVECTOR vAllCrv ; + for ( int cc = 0 ; cc < pSrfIdeal->GetChunkCount() ; cc++) { + for ( int l = 0 ; l < pSrfIdeal->GetLoopCount( cc) ; l++) { + vAllCrv.emplace_back( GetCurveComposite( pSrfIdeal->GetLoop( cc, l))) ; + } + } - // sposto l'inizio a metà del tratto più lungo - AdjustContourStart( pOffs) ; + int nClosestInd = -1 ; int nFlag ; int nFocus = 0 ; + double dDist = INFINITO ; + Point3d ptHelp ; - // verifico archi - VerifyArcs( pOffs) ; + // scorro tutte le curve + for ( int i = 0 ; i < vAllCrv.size() ; i++) { + + //se richiesto, la inverto + if ( m_Params.m_bInvert) + vAllCrv[i]->Invert() ; - // coefficiente di riduzione feed di lavorazione di questa curva - double dFeedRid = min( GetSideStep() / m_TParams.m_dDiam, 1.0) ; + // verificare casi ottimizzati per OneWay ? + // ... - // aggiungo la lavorazione di questa curva - Point3d ptP1 ; - for ( int j = 1 ; j <= nStep ; ++ j) { - // ciclo sulle curve elementari - int nMaxInd = pOffs->GetCurveCount() - 1 ; - for ( int i = 0 ; i <= nMaxInd ; ++ i) { - // curva corrente - const ICurve* pCrvC = pOffs->GetCurve( i) ; - // copio la curva - PtrOwner pCurve( pCrvC->Clone()) ; - if ( IsNull( pCurve)) + // resetto le proprietà per casi ottimizzati + ResetCurveAllTempProp( vAllCrv[i]) ; + + if ( i == 0) { + // sposto l'inizio a metà del tratto più lungo + AdjustContourStart( vAllCrv[i]) ; + } + else if ( i < vAllCrv.size() - 1) { + // sposto l'inizio della curva più vicina al punto finale precendente + Point3d ptS ; + vAllCrv[i]->GetStartPoint( ptS) ; + + // setto i default delle variabili + if ( ! DistPointCurve( ptS, *vAllCrv[i + 1]).GetMinDistPoint( EPS_SMALL, ptHelp, nFlag)) return false ; - // aggiungo affondamento - pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entità - if ( i == 0 ) { - // dati inizio entità - Point3d ptStart ; - pCurve->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pCurve->GetStartDir( vtStart) ; - // se primo step, approccio e affondo - if ( j == 1) { - // determino inizio attacco - if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) - return false ; - // determino elevazione su inizio attacco - double dStElev ; - if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dStep ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw) - dStElev = max( dStElev, dStep) ; - dStElev -= ( ptP1 - ptStart) * vtExtr ; - // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco - if ( GetLeadInType() == POCKET_LI_ZIGZAG || - GetLeadInType() == POCKET_LI_HELIX || - GetLeadInType() == POCKET_LI_GLIDE) { - ptP1 += vtExtr * dStElev ; - dStElev = 0 ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, false)) { - m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; - return false ; - } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, bSplitArcs)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - } - // altrimenti solo collegamento - else { - SetFeed( GetStartFeed()) ; - GetCurrPos( ptP1) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } + dDist = INFINITO ; + + for ( int j = i + 1 ; j <= vAllCrv.size() - 1 ; j++) { + + // cerco il punto più vicino della curva + Point3d ptE ; + + if ( ! DistPointCurve( ptS, *vAllCrv[j]).GetMinDistPoint( EPS_SMALL, ptE, nFlag)) + return false ; + + if ( dDist > Dist(ptS, ptE)) { + dDist = Dist( ptS, ptE) ; + nClosestInd = j ; + ptHelp.Set( ptE.x, ptE.y, ptE.z) ; } } - // elaborazioni sulla curva corrente - if ( pCurve->GetType() == CRV_LINE) { - ICurveLine* pLine = GetCurveLine( pCurve) ; - Point3d ptP3 = pLine->GetEnd() ; - SetFeed( dFeedRid * GetFeed()) ; - if ( AddLinearMove( ptP3) == GDB_ID_NULL) - return false ; + + // avendo la curva più vicina ... + if ( nClosestInd != i + 1) { + PtrOwner ptoCCHelp( GetCurveComposite( Release(vAllCrv[i + 1]))); + vAllCrv[i + 1].Set( Release( vAllCrv[nClosestInd])) ; + vAllCrv[nClosestInd].Set(Release( ptoCCHelp)) ; } - else if ( pCurve->GetType() == CRV_ARC) { - ICurveArc* pArc = GetCurveArc( pCurve) ; - Point3d ptCen = pArc->GetCenter() ; - double dAngCen = pArc->GetAngCenter() ; - Vector3d vtN = pArc->GetNormVersor() ; - Point3d ptP3 ; - pArc->GetEndPoint( ptP3) ; - SetFeed( dFeedRid * GetFeed()) ; - if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + + // cambio il suo punto iniziale ... + double dU ; + Point3d ptNE( ptHelp.x, ptHelp.y, ptHelp.z) ; + if ( ! vAllCrv[i + 1]->GetParamAtPoint( ptNE, dU)) + return false ; + vAllCrv[i + 1]->ChangeStartPoint( dU) ; + + } + + // verifico archi + VerifyArcs( vAllCrv[i]) ; + + PtrOwner pOffs( CreateCurveComposite()); + if ( IsNull( pOffs) || ! pOffs->AddCurve( vAllCrv[i]->Clone())) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false ; + } + + // coefficiente di riduzione feed di lavorazione di questa curva + double dFeedRid = min(GetSideStep() / m_TParams.m_dDiam, 1.0); + + // aggiungo la lavorazione di questa curva + Point3d ptP1 ; + for ( int j = 1 ; j <= nStep ; ++j) { + // ciclo sulle curve elementari + int nMaxInd = pOffs->GetCurveCount() - 1 ; + for ( int i = 0 ; i <= nMaxInd ; ++i) { + // curva corrente + const ICurve* pCrvC = pOffs->GetCurve( i) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) return false ; - } - // se ultima entità - if ( i == nMaxInd) { - // se ultimo step, uscita e retrazione di collegamento - if ( j == nStep) { - // dati fine entità - Point3d ptEnd ; - pCurve->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pCurve->GetEndDir( vtEnd) ; - // aggiungo uscita - Point3d ptP1 ; - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; - return false ; + // aggiungo affondamento + pCurve->Translate( -vtTool * ( dDepth - dElev + j * dStep)) ; + // SE PRIMA ENTITA' + if ( i == 0) { + // dati inizio entità + Point3d ptStart ; + pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; + pCurve->GetStartDir( vtStart) ; + // se primo step, approccio e affondo + if ( j == 1) { + // determino inizio attacco + if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, nullptr, ptP1)) + return false ; + // determino elevazione su inizio attacco + double dStElev ; + if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = dStep ; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; + if ( bUnderRaw) + dStElev = max( dStElev, dStep) ; + dStElev -= ( ptP1 - ptStart) * vtExtr ; + // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco + if ( GetLeadInType() == POCKET_LI_ZIGZAG || + GetLeadInType() == POCKET_LI_HELIX || + GetLeadInType() == POCKET_LI_GLIDE) { + ptP1 += vtExtr * dStElev ; + dStElev = 0 ; + } + // approccio al punto iniziale + if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, false)) { + m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; + return false ; + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + return false; + } } - // aggiungo retrazione - if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + // altrimenti solo collegamento + else { + SetFeed( GetStartFeed()) ; + GetCurrPos( ptP1) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false ; + } + } + } + // elaborazioni sulla curva corrente (aggiungo movimenti dell'utensile : LINEAR o ARC) + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + SetFeed( dFeedRid * GetFeed()) ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; + } + else if ( pCurve->GetType() == CRV_ARC) { + ICurveArc* pArc = GetCurveArc( pCurve) ; + Point3d ptCen = pArc->GetCenter() ; + double dAngCen = pArc->GetAngCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + Point3d ptP3 ; + pArc->GetEndPoint( ptP3) ; + SetFeed( dFeedRid * GetFeed()) ; + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + // SE ULTIMA ENTITA' + if ( i == nMaxInd) { + // se ultimo step, uscita e retrazione di collegamento + if ( j == nStep) { + // dati fine entità + Point3d ptEnd ; + pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; + pCurve->GetEndDir( vtEnd) ; + // aggiungo uscita + Point3d ptP1 ; + double dEndElev = dElev ; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, nullptr, bSplitArcs, ptP1, dEndElev)) { + m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + return false ; + } + // aggiungo retrazione + if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false ; + } } } } } } - } - // calcolo seconda curva di offset - OffsetCurve OffsCrv2 ; - double dExtra = min( 0.1 * m_TParams.m_dDiam, 1.0) ; - if ( ! OffsCrv2.Make( pCompo, - ( dOffs + dExtra), ICurve::OFF_FILLET)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; - return false ; - } - - // ciclo sulle curve risultanti - while ( OffsCrv2.GetCurveCount() > 0) { - - PtrOwner pOffs2( CreateCurveComposite()) ; - if ( IsNull( pOffs2) || ! pOffs2->AddCurve( OffsCrv2.GetLongerCurve())) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - - // determino il riferimento di base e il box della svuotatura + // determino il riferimento in base alla svuotatura Frame3d frPocket ; - Point3d ptCen ; pCompo->GetCentroid( ptCen) ; + Point3d ptCen ; pSrfIdeal->GetCentroid( ptCen) ; frPocket.Set( ptCen, vtExtr) ; - frPocket.Rotate( ptCen, vtExtr, m_Params.m_dSideAngle) ; - pOffs2->ToLoc( frPocket) ; - BBox3d b3Pocket ; - pOffs2->GetLocalBBox( b3Pocket) ; + frPocket.Rotate ( ptCen, vtExtr, m_Params.m_dSideAngle) ; + pSrfIdeal->ToLoc( frPocket) ; + BBox3d b3Pocket ; pSrfIdeal->GetLocalBBox( b3Pocket) ; Point3d ptMin ; double dDimX, dDimY, dDimZ ; b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; // passi in Y - int nYStep = static_cast( ceil( ( dDimY + 2 * dExtra) / GetSideStep())) ; + int nYStep = static_cast( ceil((dDimY + 2 * dExtra) / GetSideStep())) ; double dYStep = ( nYStep > 0 ? ( dDimY + 2 * dExtra) / nYStep : 0) ; - -- nYStep ; + --nYStep ; // calcolo le linee di svuotatura const double EXP_LEN = 1.0 ; - for ( int j = 1 ; j <= nStep ; ++ j) { - for ( int i = 1 ; i <= nYStep ; ++ i) { - // definisco la linea + for ( int j = 1 ; j <= nStep ; ++j) { + for ( int i = 1 ; i <= nYStep ; ++i) { + + // definisco la linea PtrOwner pLine( CreateCurveLine()) ; Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + ( - dExtra + i * dYStep), ptMin.z + dDimZ) ; - if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) { + if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } - // calcolo la classificazione della curva rispetto al contorno esterno offsettato - IntersCurveCurve intCC( *pLine, *pOffs2) ; - CRVCVECTOR ccClass ; - if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass)) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - // determino gli intervalli di curva da conservare - Intervals inOk ; - for ( auto& ccOne : ccClass) { - if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M) - inOk.Add( ccOne.dParS, ccOne.dParE) ; - } - // inserisco i tratti validi - double dParS, dParE ; - bool bFound = inOk.GetFirst( dParS, dParE) ; - while ( bFound) { - // calcolo inizio con affondamento - Point3d ptS ; pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, ptS) ; - ptS.ToGlob( frPocket) ; - ptS.Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // determino inizio attacco - Point3d ptP ; - if ( ! CalcLeadInStart( ptS, frPocket.VersX(), vtExtr, nullptr, ptP)) - return false ; - // determino elevazione su inizio attacco - double dStElev ; - if ( ! GetElevation( m_nPhase, ptS - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = j * dStep ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw) - dStElev = max( dStElev, j * dStep) ; - dStElev -= ( ptP - ptS) * vtExtr ; - // sempre approccio di collegamento - if ( ! AddLinkApproach( ptP, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP, ptS, frPocket.VersX(), vtExtr, pCompo, nullptr, ! m_Params.m_bInvert, bSplitArcs, true)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - // calcolo fine con affondamento - Point3d ptE ; pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, ptE) ; - ptE.ToGlob( frPocket) ; - ptE.Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // movimento al punto finale - SetFeed( GetFeed()) ; - if ( AddLinearMove( ptE) == GDB_ID_NULL) - return false ; - // risalita - Point3d ptQ ; - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptE, frPocket.VersX(), vtExtr, nullptr, bSplitArcs, ptQ, dEndElev, true)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; - return false ; - } - // recupero successivo intervallo - bFound = inOk.GetNext( dParS, dParE) ; - // se ultimo movimento di ultima area, aggiungo retrazione globale - if ( j == nStep && i == nYStep && ! bFound && OffsCrv2.GetCurveCount() == 0) { - if ( ! AddRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; + + // riempio il vettore di segmenti + CRVCVECTOR ccClassSeg ; + pSrfIdeal->GetCurveClassification( *pLine, EPS_SMALL, ccClassSeg) ; + for ( int w = 0 ; w < ccClassSeg.size() ; w++) { + if ( ccClassSeg[w].nClass == CRVC_IN) { + + PtrOwner pCrvSeg( GetCurveLine( pLine->CopyParamRange( ccClassSeg[w].dParS, ccClassSeg[w].dParE))) ; + double duF, dLen ; + // accorcio leggermente il segmento per non toccare la prima curva di Offset + if ( ! pCrvSeg->GetLength( dLen) + || dLen < 2 * dExtra + || ! pCrvSeg->GetParamAtLength( dLen - dExtra, duF) + || ! pCrvSeg->TrimStartAtLen( dExtra) + || ! pCrvSeg->TrimEndAtParam( duF)) + pCrvSeg.Set( GetCurveLine( pLine->CopyParamRange( ccClassSeg[w].dParS, ccClassSeg[w].dParE))) ; + + Point3d ptS, ptE ; + pCrvSeg->GetStartPoint( ptS) ; + pCrvSeg->GetEndPoint( ptE) ; + + // ricavo la curva su cui si trova il punto iniziale + PtrOwner pCrvPtStartOn( CreateCurveComposite()) ; + if ( IsNull( pCrvPtStartOn)) + return false ; + for ( int v = 0; v < pSrfIdeal->GetChunkCount(); v++) { + for ( int b = 0; b < pSrfIdeal->GetLoopCount( v); b++) { + PtrOwner pCrvTest( GetCurveComposite( pSrfIdeal->GetLoop( v, b))) ; + if ( IsNull( pCrvTest)) + return false ; + if ( pCrvTest->IsPointOn( ptS)) { + pCrvPtStartOn.Set( Release( pCrvTest)) ; + v = pSrfIdeal->GetChunkCount() ; + break ; + } + } + } + + // INIZIO + ptS.ToGlob( frPocket) ; + ptS.Translate( - vtTool * (dDepth - dElev + j * dStep)) ; + // determino inizio attacco + Point3d ptP ; + if ( ! CalcLeadInStart( ptS, frPocket.VersX(), vtExtr, nullptr, ptP)) + return false; + // determino elevazione su inizio attacco + double dStElev ; + if ( ! GetElevation( m_nPhase, ptS - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = j * dStep ; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev); + if ( bUnderRaw) + dStElev = max( dStElev, j * dStep) ; + dStElev -= ( ptP - ptS) * vtExtr ; + // sempre approccio di collegamento + if ( ! AddLinkApproach( ptP, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable"); + return false; + } + // aggiungo attacco (forzato ad essere lineare) + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP, ptS, frPocket.VersX(), vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs, true)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable"); return false ; } - } - // altrimenti aggiungo retrazione di collegamento - else { - if ( ! AddLinkRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + + ptE.ToGlob( frPocket) ; + ptE.Translate( - vtTool * (dDepth - dElev + j * dStep)) ; + + // movimento al punto finale + SetFeed( GetFeed()) ; + if ( AddLinearMove( ptE) == GDB_ID_NULL) return false ; + + // FINE + Point3d ptQ ; + double dEndElev = dElev ; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptE, frPocket.VersX(), vtExtr, nullptr, bSplitArcs, ptQ, dEndElev, true)) { + m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + return false; } + + // se ultimo movimento di ultima area, aggiungo retrazione globale + if ( j == nStep && i == nYStep) { + if ( ! AddRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; + return false; + } + } + // altrimenti aggiungo retrazione di collegamento + else { + if ( ! AddLinkRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false; + } + } + } } + } } + } return true ; } + //---------------------------------------------------------------------------- bool -Pocketing::AddSpiralIn( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, bool bMidOpen, - const Point3d& ptMidOpen, const Vector3d& vtMidOut, int nPathId) +Pocketing::AddSpiralIn( const ISurfFlatRegion* pSrfPock, const PNTVECTOR vPtStart, const Vector3d& vtTool, const Vector3d& vtExtr, + double dDepth, double dElev, double dOkStep, bool bSplitArcs, BOOLVECTOR vbMidOpen, + PNTVECTOR vPtMidOpen, VCT3DVECTOR vVtMidOut, int nPathId) { // recupero distanze di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; @@ -3293,238 +4055,263 @@ Pocketing::AddSpiralIn( const ICurveComposite* pCompo, const Vector3d& vtTool, c // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // ciclo sulle regioni - const int MAX_REGS = 50 ; - int nReg = 0 ; - while ( nReg < MAX_REGS) { - - // calcolo la spirale dall'esterno all'interno e la curva che unisce inizio e fine - PtrOwner pMCrv( CreateCurveComposite()) ; - PtrOwner pRCrv( CreateCurveComposite()) ; - if ( IsNull( pMCrv) || IsNull( pRCrv)) { - m_pMchMgr->SetLastError( 2411, "Error in Pocketing : toolpath allocation failed") ; + // ciclo sui Chunks + for ( int c = 0 ; c < pSrfPock->GetChunkCount() ; c++) { + + // copio il chunk + PtrOwner pSrfChunk( GetSurfFlatRegion( pSrfPock->CloneChunk( c))) ; + if ( IsNull( pSrfChunk)) return false ; - } - // se lucidatura con epicicli - if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL ) { - // verifico che i parametri lucidatura siano sensati - if ( m_Params.m_dEpicyclesDist < 100 * EPS_SMALL) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; + const int MAX_REGS = 50 ; + int nReg = 0 ; + + // porto il Chunk nel sistema di riferimento locale + Point3d ptCen ; pSrfChunk->GetCentroid(ptCen) ; + Frame3d frPocket ; frPocket.Set( ptCen, vtExtr) ; + pSrfChunk->ToLoc( frPocket) ; + + while ( nReg < MAX_REGS) { + + // superifice per ingressi ed uscite + PtrOwner pSrfLeanInOut( CloneSurfFlatRegion( pSrfChunk)); + + // calcolo la spirale dall'esterno all'interno e la curva che unisce inizio e fine + PtrOwner pMCrv( CreateCurveComposite()) ; + PtrOwner pRCrv( CreateCurveComposite()) ; + if (IsNull( pMCrv) || IsNull( pRCrv)) { + m_pMchMgr->SetLastError(2411, "Error in Pocketing : toolpath allocation failed"); + return false; } - // modifico il diametro dell'utensile per tenere conto anche del diametro degli epicicli - m_TParams.m_dDiam += 2 * m_Params.m_dEpicyclesRad ; - } - bool bOptimizedTrap = false ; - if ( ! CalcSpiral( pCompo, nReg, bSplitArcs, pMCrv, pRCrv, nPathId, bOptimizedTrap)) - return false ; - // se terminate le regioni, esco - if ( pMCrv->GetCurveCount() == 0) - break ; - ++ nReg ; - - if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { - // riporto il diametro dell'utensile al valore originale - m_TParams.m_dDiam -= 2 * m_Params.m_dEpicyclesRad ; - // aggiorno i percorsi di svuotatura con epicicli - if ( ! ComputePolishingPath( pMCrv, pRCrv, bSplitArcs)) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - } - - // se prima regione e gestione lato aperto ( caso non ottimizzato) - bool bOutStart = ( nReg == 1 && bMidOpen) ; - if ( bOutStart && ! bOptimizedTrap) { - // calcolo il punto fuori - Point3d ptOut = ptMidOpen + vtMidOut * ( 0.5 * m_TParams.m_dDiam + dSafeZ) ; - // verifico che il punto sia veramente fuori dal grezzo - double dStElev ; - bOutStart = ( ! GetElevation( m_nPhase, ptOut, vtTool, 0.5 * m_TParams.m_dDiam, vtTool, dStElev) || dStElev < EPS_SMALL) ; - if ( bOutStart || m_bOpenOutRaw) { - // aggiungo al ritorno l'uscita - if ( pRCrv->GetCurveCount() == 0) { - Point3d ptStart ; pMCrv->GetStartPoint( ptStart) ; - pRCrv->AddPoint( ptStart) ; + // se lucidatura con epicicli + if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { + // verifico che i parametri lucidatura siano sensati + if ( m_Params.m_dEpicyclesDist < 100 * EPS_SMALL) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false; } - pRCrv->AddLine( ptOut, true) ; - // premetto alla spirale la partenza da fuori - pMCrv->AddLine( ptOut, false) ; + // modifico il diametro dell'utensile per tenere conto anche del diametro degli epicicli + m_TParams.m_dDiam += 2 * m_Params.m_dEpicyclesRad ; } - } - // calcolo gli eventuali punti fuori dal grezzo nel caso ottimizzato - int nOutsideRaw = 0 ; - if ( bOptimizedTrap) { - AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, pRCrv, vtTool, dDepth, nOutsideRaw) ; - bOutStart = ( nOutsideRaw > 0) ; - } + bool bOptimizedTrap = false ; + if ( ! CalcSpiral( pSrfChunk, nReg, vPtStart[c], bSplitArcs, pMCrv, pRCrv, nPathId, bOptimizedTrap)) + return false; - // verifico se ingresso da considerare fuori grezzo anche se dentro - bool bForcedOutStart = ( bMidOpen && m_bOpenOutRaw) ; + // se terminate le regioni, esco + if ( pMCrv->GetCurveCount() == 0) + break ; // passo al chunk originale successivo + ++nReg ; - // se utensile che non lavora di testa e ingresso non fuori dal pezzo, errore - if ( m_TParams.m_nType == TT_MILL_NOTIP && ! bOutStart && ! bForcedOutStart) { - if ( ! LeadInIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; - return false ; + // riporto le curve nel sistema di riferimento della svuotatura + if ( ! bOptimizedTrap) { + pMCrv->ToGlob( frPocket) ; + pRCrv->ToGlob( frPocket) ; } - } - // determino numero e affondamento degli step - int nStep = 1 ; - nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; - double dStep = dElev / nStep ; - - int nMaxInd = pMCrv->GetCurveCount() - 1 ; - int nMaxRInd = pRCrv->GetCurveCount() - 1 ; - - // ciclo sugli step - Point3d ptP1 ; - for ( int j = 1 ; j <= nStep ; ++ j) { - // se sono nel caso ottimizzato e ho attacco e uscita entrambi dentro/fuori dal grezzo, ad ogni step inverto la direzione della curva - if ( bOptimizedTrap && nOutsideRaw != 1 && j > 1) - pMCrv->Invert() ; - // ciclo sulle curve elementari - for ( int i = 0 ; i <= nMaxInd ; ++ i) { - // curva corrente - const ICurve* pCrvC = pMCrv->GetCurve( i) ; - // copio la curva - PtrOwner pCurve( pCrvC->Clone()) ; - if ( IsNull( pCurve)) + if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { + // riporto il diametro dell'utensile al valore originale + m_TParams.m_dDiam -= 2 * m_Params.m_dEpicyclesRad ; + // aggiorno i percorsi di svuotatura con epicicli + if ( ! ComputePolishingPath( pMCrv, pRCrv, bSplitArcs)) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; - // aggiungo affondamento - pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entità - if ( i == 0 ) { - // dati inizio entità - Point3d ptStart ; - pCurve->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pCurve->GetStartDir( vtStart) ; - // se primo step, approccio e affondo - if ( j == 1) { - // determino inizio attacco - if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, pRCrv, ptP1)) - return false ; - // determino elevazione su inizio attacco (se non trovata, elevazione è step) - double dStElev ; - if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dStep ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw || ( bOutStart && ! m_bAboveHead)) - dStElev = max( dStElev, dStep) ; - dStElev -= ( ptP1 - ptStart) * vtExtr ; - // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco - if ( GetLeadInType() == POCKET_LI_ZIGZAG || - GetLeadInType() == POCKET_LI_HELIX || - GetLeadInType() == POCKET_LI_GLIDE) { - ptP1 += vtExtr * dStElev ; - dStElev = 0 ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutStart || bForcedOutStart)) { - m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; - return false ; - } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, pRCrv, ! m_Params.m_bInvert, bSplitArcs, bOutStart || bForcedOutStart)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - } - // altrimenti solo collegamento - else { - SetFeed( GetStartFeed()) ; - GetCurrPos( ptP1) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, pRCrv, ! m_Params.m_bInvert, bSplitArcs, bOutStart || bForcedOutStart)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } + } + } + + // se prima regione e gestione lato aperto ( caso non ottimizzato) + bool bOutStart = ( nReg == 1 && vbMidOpen[c]); + if ( bOutStart && !bOptimizedTrap) { + // calcolo il punto fuori + Point3d ptOut = vPtMidOpen[c] + vVtMidOut[c] * (0.5 * m_TParams.m_dDiam + dSafeZ); + // verifico che il punto sia veramente fuori dal grezzo + double dStElev; + bOutStart = ( ! GetElevation( m_nPhase, ptOut, vtTool, 0.5 * m_TParams.m_dDiam, vtTool, dStElev) || dStElev < EPS_SMALL); + if ( bOutStart || m_bOpenOutRaw) { + // aggiungo al ritorno l'uscita + if (pRCrv->GetCurveCount() == 0) { + Point3d ptStart; pMCrv->GetStartPoint(ptStart); + pRCrv->AddPoint(ptStart); } + pRCrv->AddLine(ptOut, true); + // premetto alla spirale la partenza da fuori + pMCrv->AddLine(ptOut, false); } - // elaborazioni sulla curva corrente - if ( pCurve->GetType() == CRV_LINE) { - ICurveLine* pLine = GetCurveLine( pCurve) ; - Point3d ptP3 = pLine->GetEnd() ; - SetFeed( GetFeed()) ; - if ( AddLinearMove( ptP3) == GDB_ID_NULL) + } + + // calcolo gli eventuali punti fuori dal grezzo nel caso ottimizzato + int nOutsideRaw = 0; + if ( bOptimizedTrap) { + AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, pRCrv, vtTool, dDepth, nOutsideRaw) ; + bOutStart = ( nOutsideRaw > 0) ; + } + + // verifico se ingresso da considerare fuori grezzo anche se dentro + bool bForcedOutStart = ( vbMidOpen[c] && m_bOpenOutRaw); + + // se utensile che non lavora di testa e ingresso non fuori dal pezzo, errore + if ( m_TParams.m_nType == TT_MILL_NOTIP && !bOutStart && !bForcedOutStart) { + if ( ! LeadInIsOk()) { + m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; + return false ; + } + } + + // determino numero e affondamento degli step + int nStep = 1 ; + nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + double dStep = dElev / nStep ; + + int nMaxInd = pMCrv->GetCurveCount() - 1 ; + int nMaxRInd = pRCrv->GetCurveCount() - 1 ; + + // ciclo sugli step + Point3d ptP1 ; + for ( int j = 1; j <= nStep; ++j) { + // se sono nel caso ottimizzato e ho attacco e uscita entrambi dentro/fuori dal grezzo, ad ogni step inverto la direzione della curva + if ( bOptimizedTrap && nOutsideRaw != 1 && j > 1) + pMCrv->Invert() ; + // ciclo sulle curve elementari + for ( int i = 0 ; i <= nMaxInd ; ++i) { + // curva corrente + const ICurve* pCrvC = pMCrv->GetCurve( i) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) return false ; - } - else if ( pCurve->GetType() == CRV_ARC) { - ICurveArc* pArc = GetCurveArc( pCurve) ; - Point3d ptCen = pArc->GetCenter() ; - double dAngCen = pArc->GetAngCenter() ; - Vector3d vtN = pArc->GetNormVersor() ; - Point3d ptP3 ; - pArc->GetEndPoint( ptP3) ; - SetFeed( GetFeed()) ; - if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) - return false ; - } - // se ultima entità - if ( i == nMaxInd) { - // se step intermedio, ritorno all'inizio direttamente - if ( j < nStep) { - // se necessario ritorno all'inizio - if ( nMaxRInd >= 0) { - // copio la curva di ritorno - PtrOwner pRet( pRCrv->Clone()) ; - if ( IsNull( pRet)) + // aggiungo affondamento + pCurve->Translate( -vtTool * (dDepth - dElev + j * dStep)) ; + // se prima entità + if ( i == 0) { + // dati inizio entità + Point3d ptStart ; + pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; + pCurve->GetStartDir( vtStart) ; + // se primo step, approccio e affondo + if ( j == 1) { + // determino inizio attacco + if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, pRCrv, ptP1)) return false ; - // aggiungo affondamento - pRet->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se attacco a scivolo, accorcio della lunghezza dell'attacco - if ( GetLeadInType() == POCKET_LI_GLIDE) { - double dLen ; pRet->GetLength( dLen) ; - if ( dLen > m_Params.m_dLiTang + 10 * EPS_SMALL) - pRet->TrimEndAtLen( dLen - m_Params.m_dLiTang) ; - else - pRet->Clear() ; + // determino elevazione su inizio attacco (se non trovata, elevazione è step) + double dStElev ; + if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = dStep ; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev); + if ( bUnderRaw || ( bOutStart && !m_bAboveHead)) + dStElev = max( dStElev, dStep) ; + dStElev -= ( ptP1 - ptStart) * vtExtr ; + // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco + if ( GetLeadInType() == POCKET_LI_ZIGZAG || + GetLeadInType() == POCKET_LI_HELIX || + GetLeadInType() == POCKET_LI_GLIDE) { + ptP1 += vtExtr * dStElev ; + dStElev = 0 ; } - // emetto - SetFeed( GetFeed()) ; - if ( pRet->GetCurveCount() > 0 && AddCurveMove( pRet) == GDB_ID_NULL) + // approccio al punto iniziale + if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bOutStart || bForcedOutStart)) { + m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; return false ; + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, pRCrv, !m_Params.m_bInvert, bSplitArcs, bOutStart || bForcedOutStart)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + return false ; + } + } + // altrimenti solo collegamento + else { + SetFeed( GetStartFeed()) ; + GetCurrPos( ptP1) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, pRCrv, !m_Params.m_bInvert, bSplitArcs, bOutStart || bForcedOutStart)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false ; + } } } - // atrimenti ultimo step, uscita e retrazione - else { - // dati fine entità - Point3d ptEnd ; - pCurve->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pCurve->GetEndDir( vtEnd) ; - // aggiungo uscita - Point3d ptP1 ; - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, pRCrv, bSplitArcs, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + // elaborazioni sulla curva corrente + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + SetFeed( GetFeed()) ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; + } + else if ( pCurve->GetType() == CRV_ARC) { + ICurveArc* pArc = GetCurveArc( pCurve) ; + Point3d ptCen = pArc->GetCenter() ; + double dAngCen = pArc->GetAngCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + Point3d ptP3 ; + pArc->GetEndPoint( ptP3); + SetFeed( GetFeed()) ; + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + // se ultima entità + if ( i == nMaxInd) { + // se step intermedio, ritorno all'inizio direttamente + if ( j < nStep) { + // se necessario ritorno all'inizio + if ( nMaxRInd >= 0) { + // copio la curva di ritorno + PtrOwner pRet( pRCrv->Clone()) ; + if ( IsNull( pRet)) + return false ; + // aggiungo affondamento + pRet->Translate( -vtTool * (dDepth - dElev + j * dStep)) ; + // se attacco a scivolo, accorcio della lunghezza dell'attacco + if ( GetLeadInType() == POCKET_LI_GLIDE) { + double dLen ; pRet->GetLength( dLen) ; + if ( dLen > m_Params.m_dLiTang + 10 * EPS_SMALL) + pRet->TrimEndAtLen( dLen - m_Params.m_dLiTang) ; + else + pRet->Clear() ; + } + // emetto + SetFeed( GetFeed()) ; + if ( pRet->GetCurveCount() > 0 && AddCurveMove( pRet) == GDB_ID_NULL) + return false ; + } } - if ( ! m_bAboveHead) - dEndElev = max( dEndElev, j * dStep) ; - // aggiungo retrazione - if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; - return false ; + // atrimenti ultimo step, uscita e retrazione + else { + // dati fine entità + Point3d ptEnd ; + pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; + pCurve->GetEndDir( vtEnd) ; + // aggiungo uscita + Point3d ptP1 ; + double dEndElev = dElev ; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, pRCrv, bSplitArcs, ptP1, dEndElev)) { + m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + return false ; + } + if ( !m_bAboveHead) + dEndElev = max( dEndElev, j * dStep) ; + // aggiungo retrazione + if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; + return false ; + } } } } } } } + return true ; } //---------------------------------------------------------------------------- bool -Pocketing::AddSpiralOut( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, +Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrfPock, const PNTVECTOR vPtStart, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) { // recupero distanze di sicurezza @@ -3534,211 +4321,233 @@ Pocketing::AddSpiralOut( const ICurveComposite* pCompo, const Vector3d& vtTool, double dAppr = m_Params.m_dStartPos ; // ciclo sulle regioni - const int MAX_REGS = 50 ; - int nReg = 0 ; - while ( nReg < MAX_REGS) { - - // calcolo la spirale dall'interno all'esterno - PtrOwner pMCrv( CreateCurveComposite()) ; - PtrOwner pRCrv( CreateCurveComposite()) ; - if ( IsNull( pMCrv) || IsNull( pRCrv)) { - m_pMchMgr->SetLastError( 2411, "Error in Pocketing : toolpath allocation failed") ; + for ( int c = 0 ; c < pSrfPock->GetChunkCount() ; c++) { + + // copio il chunk + PtrOwner pSrfChunk( GetSurfFlatRegion( pSrfPock->CloneChunk( c))) ; + if ( IsNull( pSrfChunk)) return false ; - } - // se lucidatura con epicicli - if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL ) { - // verifico che parametri lucidatura siano sensati - if ( m_Params.m_dEpicyclesDist < 100 * EPS_SMALL) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + // porto il Chunk nel sistema di riferimento locale + Point3d ptCen ; pSrfChunk->GetCentroid( ptCen) ; + Frame3d frPocket ; frPocket.Set( ptCen, vtExtr) ; + pSrfChunk->ToLoc( frPocket) ; + + int nReg = 0; + int MAX_REGS = 50 ; + + while ( nReg < MAX_REGS) { + + // superificie per ingressi ed uscite + PtrOwner pSrfLeanInOut(CloneSurfFlatRegion(pSrfChunk)); + + // calcolo la spirale dall'interno all'esterno + PtrOwner pMCrv(CreateCurveComposite()); + PtrOwner pRCrv(CreateCurveComposite()); + if ( IsNull( pMCrv) || IsNull( pRCrv)) { + m_pMchMgr->SetLastError( 2411, "Error in Pocketing : toolpath allocation failed") ; return false ; } - // modifico il diametro dell'utensile per tenere conto anche del raggio degli epicicli - m_TParams.m_dDiam += 2 * m_Params.m_dEpicyclesRad ; - } - bool bOptimizedTrap = false ; - if ( ! CalcSpiral( pCompo, nReg, bSplitArcs, pMCrv, pRCrv, nPathId, bOptimizedTrap)) - return false ; - // se terminate le regioni, esco - if ( pMCrv->GetCurveCount() == 0) - break ; - ++ nReg ; - - if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { - // riporto il diametro dell'utensile al valore originale - m_TParams.m_dDiam -= 2 * m_Params.m_dEpicyclesRad ; - // aggiorno i percorsi di svuotatura con epicicli - if ( ! ComputePolishingPath( pMCrv, pRCrv, bSplitArcs)) { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - } - - // nel caso ottimizzato verifico se posso entrare e uscire fuori dal grezzo - bool bOutStart = false ; - int nOutsideRaw = 0 ; - if ( bOptimizedTrap) { - AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, pRCrv, vtTool, dDepth, nOutsideRaw) ; - bOutStart = ( nOutsideRaw > 0) ; - } - - // se utensile che non lavora di testa e ingresso non fuori dal pezzo, errore - if ( m_TParams.m_nType == TT_MILL_NOTIP && ! bOutStart) { - if ( ! LeadInIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; - return false ; - } - } - - // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) - if ( ! bOptimizedTrap) { - pMCrv->Invert() ; - pRCrv->Invert() ; - } - - // determino numero e affondamento degli step - int nStep = 1 ; - nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; - double dStep = dElev / nStep ; - - int nMaxInd = pMCrv->GetCurveCount() - 1 ; - int nMaxRInd = pRCrv->GetCurveCount() - 1 ; - - // ciclo sugli step - Point3d ptP1 ; - for ( int j = 1 ; j <= nStep ; ++ j) { - // se sono nel caso ottimizzato e ho attacco e uscita entrambi dentro/fuori dal grezzo, ad ogni step inverto la direzione della curva - if ( bOptimizedTrap && nOutsideRaw != 1 && j > 1) - pMCrv->Invert() ; - // ciclo sulle curve elementari - for ( int i = 0 ; i <= nMaxInd ; ++ i) { - // curva corrente - const ICurve* pCrvC = pMCrv->GetCurve( i) ; - // copio la curva - PtrOwner pCurve( pCrvC->Clone()) ; - if ( IsNull( pCurve)) + // se lucidatura con epicicli + if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { + // verifico che parametri lucidatura siano sensati + if ( m_Params.m_dEpicyclesDist < 100 * EPS_SMALL) { + m_pMchMgr->SetLastError(2413, "Error in Pocketing : Toolpath not computable") ; return false ; - // aggiungo affondamento - pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entità - if ( i == 0 ) { - // dati inizio entità - Point3d ptStart ; - pCurve->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pCurve->GetStartDir( vtStart) ; - // se primo step, approccio e affondo - if ( j == 1) { - // determino inizio attacco - if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, pRCrv, ptP1)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - // determino elevazione su inizio attacco - double dStElev ; - if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dStep ; - bool bUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bUnderRaw || ( bOutStart && ! m_bAboveHead)) - dStElev = max( dStElev, dStep) ; - dStElev -= ( ptP1 - ptStart) * vtExtr ; - // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco - if ( GetLeadInType() == POCKET_LI_ZIGZAG || - GetLeadInType() == POCKET_LI_HELIX || - GetLeadInType() == POCKET_LI_GLIDE) { - ptP1 += vtExtr * dStElev ; - dStElev = 0 ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, false)) { - m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; - return false ; - } - // aggiungo attacco - SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, pRCrv, m_Params.m_bInvert, bSplitArcs, bOutStart)) { - m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } - } - // altrimenti solo collegamento - else { - SetFeed( GetStartFeed()) ; - GetCurrPos( ptP1) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pCompo, pRCrv, m_Params.m_bInvert, bSplitArcs, bOutStart)) { - m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; - return false ; - } - } } - // elaborazioni sulla curva corrente - if ( pCurve->GetType() == CRV_LINE) { - ICurveLine* pLine = GetCurveLine( pCurve) ; - Point3d ptP3 = pLine->GetEnd() ; - SetFeed( GetFeed()) ; - if ( AddLinearMove( ptP3) == GDB_ID_NULL) + // modifico il diametro dell'utensile per tenere conto anche del raggio degli epicicli + m_TParams.m_dDiam += 2 * m_Params.m_dEpicyclesRad ; + } + + bool bOptimizedTrap = false; + if ( ! CalcSpiral( pSrfChunk, nReg, vPtStart[c], bSplitArcs, pMCrv, pRCrv, nPathId, bOptimizedTrap)) + return false ; + + // se terminate le regioni, esco + if ( pMCrv->GetCurveCount() == 0) + break ; + ++nReg ; + + // riporto le curve nel sistema di riferimento della svuotatura + pMCrv->ToGlob( frPocket) ; + pRCrv->ToGlob( frPocket) ; + + if ( m_TParams.m_nType == TT_MILL_POLISHING && m_Params.m_dEpicyclesRad > EPS_SMALL) { + // riporto il diametro dell'utensile al valore originale + m_TParams.m_dDiam -= 2 * m_Params.m_dEpicyclesRad ; + // aggiorno i percorsi di svuotatura con epicicli + if (!ComputePolishingPath( pMCrv, pRCrv, bSplitArcs)) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false ; + } + } + + // nel caso ottimizzato verifico se posso entrare e uscire fuori dal grezzo + bool bOutStart = false ; + int nOutsideRaw = 0 ; + if ( bOptimizedTrap) { + AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, pRCrv, vtTool, dDepth, nOutsideRaw) ; + bOutStart = ( nOutsideRaw > 0) ; + } + + // se utensile che non lavora di testa e ingresso non fuori dal pezzo, errore + if ( m_TParams.m_nType == TT_MILL_NOTIP && !bOutStart) { + if ( ! LeadInIsOk()) { + m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; + return false ; + } + } + + // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) + if ( ! bOptimizedTrap) { + pMCrv->Invert() ; + pRCrv->Invert() ; + } + + // determino numero e affondamento degli step + int nStep = 1 ; + nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + double dStep = dElev / nStep; + + int nMaxInd = pMCrv->GetCurveCount() - 1 ; + int nMaxRInd = pRCrv->GetCurveCount() - 1 ; + + // ciclo sugli step + Point3d ptP1 ; + for ( int j = 1 ; j <= nStep ; ++j) { + // se sono nel caso ottimizzato e ho attacco e uscita entrambi dentro/fuori dal grezzo, ad ogni step inverto la direzione della curva + if ( bOptimizedTrap && nOutsideRaw != 1 && j > 1) + pMCrv->Invert() ; + // ciclo sulle curve elementari + for ( int i = 0 ; i <= nMaxInd ; ++i) { + // curva corrente + const ICurve* pCrvC = pMCrv->GetCurve( i) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) return false ; - } - else if ( pCurve->GetType() == CRV_ARC) { - ICurveArc* pArc = GetCurveArc( pCurve) ; - Point3d ptCen = pArc->GetCenter() ; - double dAngCen = pArc->GetAngCenter() ; - Vector3d vtN = pArc->GetNormVersor() ; - Point3d ptP3 ; - pArc->GetEndPoint( ptP3) ; - SetFeed( GetFeed()) ; - if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) - return false ; - } - // se ultima entità - if ( i == nMaxInd) { - // se step intermedio - if ( j < nStep) { - // se necessario ritorno all'inizio - if ( nMaxRInd >= 0) { - // copio la curva di ritorno - PtrOwner pRet( pRCrv->Clone()) ; - if ( IsNull( pRet)) + // aggiungo affondamento + pCurve->Translate( -vtTool * (dDepth - dElev + j * dStep)) ; + // se prima entità + if ( i == 0) { + // dati inizio entità + Point3d ptStart ; + pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; + pCurve->GetStartDir( vtStart) ; + // se primo step, approccio e affondo + if ( j == 1) { + // determino inizio attacco + if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, pRCrv, ptP1)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; return false ; - // aggiungo affondamento - pRet->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se attacco a scivolo, accorcio della lunghezza dell'attacco - if ( GetLeadInType() == POCKET_LI_GLIDE) { - double dLen ; pRet->GetLength( dLen) ; - if ( dLen > m_Params.m_dLiTang + 10 * EPS_SMALL) - pRet->TrimEndAtLen( dLen - m_Params.m_dLiTang) ; - else - pRet->Clear() ; } - // emetto - SetFeed( GetFeed()) ; - if ( pRet->GetCurveCount() > 0 && AddCurveMove( pRet) == GDB_ID_NULL) + // determino elevazione su inizio attacco + double dStElev ; + if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = dStep ; + bool bUnderRaw = m_bAboveHead && !m_bAggrBottom && !m_bTiltingTab && + GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev); + if ( bUnderRaw || ( bOutStart && !m_bAboveHead)) + dStElev = max( dStElev, dStep); + dStElev -= ( ptP1 - ptStart) * vtExtr ; + // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco + if ( GetLeadInType() == POCKET_LI_ZIGZAG || + GetLeadInType() == POCKET_LI_HELIX || + GetLeadInType() == POCKET_LI_GLIDE) { + ptP1 += vtExtr * dStElev ; + dStElev = 0 ; + } + // approccio al punto iniziale + if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, false)) { + m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; return false ; + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, pRCrv, m_Params.m_bInvert, bSplitArcs, bOutStart)) { + m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + return false ; + } + } + // altrimenti solo collegamento + else { + SetFeed( GetStartFeed()) ; + GetCurrPos( ptP1) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, pRCrv, m_Params.m_bInvert, bSplitArcs, bOutStart)) { + m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ; + return false ; + } } } - // atrimenti ultimo step, uscita e retrazione - else { - // dati fine entità - Point3d ptEnd ; - pCurve->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pCurve->GetEndDir( vtEnd) ; - // aggiungo uscita - Point3d ptQ ; - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, pRCrv, bSplitArcs, ptQ, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + // elaborazioni sulla curva corrente + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + SetFeed( GetFeed()) ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; + } + else if ( pCurve->GetType() == CRV_ARC) { + ICurveArc* pArc = GetCurveArc( pCurve) ; + Point3d ptCen = pArc->GetCenter() ; + double dAngCen = pArc->GetAngCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + Point3d ptP3 ; + pArc->GetEndPoint( ptP3) ; + SetFeed( GetFeed()); + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + // se ultima entità + if ( i == nMaxInd) { + // se step intermedio + if ( j < nStep) { + // se necessario ritorno all'inizio + if ( nMaxRInd >= 0) { + // copio la curva di ritorno + PtrOwner pRet( pRCrv->Clone()) ; + if ( IsNull( pRet)) + return false ; + // aggiungo affondamento + pRet->Translate( -vtTool * ( dDepth - dElev + j * dStep)) ; + // se attacco a scivolo, accorcio della lunghezza dell'attacco + if ( GetLeadInType() == POCKET_LI_GLIDE) { + double dLen ; pRet->GetLength( dLen) ; + if ( dLen > m_Params.m_dLiTang + 10 * EPS_SMALL) + pRet->TrimEndAtLen( dLen - m_Params.m_dLiTang) ; + else + pRet->Clear() ; + } + // emetto + SetFeed( GetFeed()) ; + if ( pRet->GetCurveCount() > 0 && AddCurveMove( pRet) == GDB_ID_NULL) + return false ; + } } - if ( ! m_bAboveHead) - dEndElev = max( dEndElev, j * dStep) ; - // aggiungo retrazione - if ( ! AddRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { - m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; - return false ; + // atrimenti ultimo step, uscita e retrazione + else { + // dati fine entità + Point3d ptEnd ; + pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; + pCurve->GetEndDir( vtEnd) ; + // aggiungo uscita + Point3d ptQ ; + double dEndElev = dElev; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, pRCrv, bSplitArcs, ptQ, dEndElev)) { + m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ; + return false ; + } + if ( !m_bAboveHead) + dEndElev = max( dEndElev, j * dStep) ; + // aggiungo retrazione + if ( ! AddRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 2417, "Error in Pocketing : Retract not computable") ; + return false ; + } } } } @@ -3750,9 +4559,10 @@ Pocketing::AddSpiralOut( const ICurveComposite* pCompo, const Vector3d& vtTool, //---------------------------------------------------------------------------- bool -Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, +Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int nReg, Point3d ptStart, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv, int nPathId, bool& bOptimizedTrap) { + // inizializzo i risultati pMCrv->Clear() ; pRCrv->Clear() ; @@ -3761,150 +4571,332 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, double dTRad = 0.5 * m_TParams.m_dDiam ; double dOffs = dTRad + GetOffsR() ; - // se circonferenza, chiamo la funzione specializzata - Point3d ptCen ; Vector3d vtN ; double dRad ; bool bCCW ; - if ( pCompo->IsACircle( 100 * EPS_SMALL, ptCen, vtN, dRad, bCCW)) { - double dIntRad = 0 ; - if ( m_Params.m_nSubType == POCKET_SUB_SPIRALOUT && GetLeadInType() == POCKET_LI_HELIX) { - dIntRad = min( 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam), dRad - dOffs) ; - m_dMaxHelixRad = dIntRad ; - } - if ( nReg == 0) - return CalcCircleSpiral( ptCen, vtN, dRad - dOffs, dIntRad, bSplitArcs, pMCrv, pRCrv) ; - else - return true ; + // recupero il versore normale della superificie, ruotandola nel piano XY + PtrOwner pSrfToWork( pSrfPock->Clone()) ; + if ( IsNull( pSrfToWork) || pSrfToWork->GetChunkCount() == 0) + return false; + + // controllo se ho isole per i casi ottimizzati + bool bHasIsland = false ; + for ( int j = 1 ; j < pSrfPock->GetLoopCount( 0) ; j++) { + PtrOwner pCrvBorder( GetCurveComposite( pSrfPock->GetLoop( 0, j))) ; + if( ! IsNull( pCrvBorder)) + bHasIsland = true ; } - // recupero la curva originaria della svuotatura (non allargata per lati aperti) per verificare caso trapezoide - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; - PtrOwner pCrvPocket( CloneCurveComposite( m_pGeomDB->GetGeoObj( nCrvId))) ; - if ( IsNull( pCrvPocket)) - return false ; - SetCurveAllTempProp( nCrvId, pCrvPocket) ; - pCrvPocket->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; - - Point3d pt ; - Vector3d vtB1, vtL1, vtB2 ; - if ( pCrvPocket->IsATrapezoid( 100 * EPS_SMALL, pt, vtB1, vtL1, vtB2)) { - Vector3d vtDir( vtB1), vtOtherDir( vtL1) ; - // se parallelogramma scelgo come base i lati lunghi - Vector3d vtL2( -vtB1 + vtL1 + vtB2) ; - if ( AreSameOrOppositeVectorApprox( vtL1, vtL2)) { - if ( vtL1.Len() > vtB1.Len()) - swap( vtDir, vtOtherDir) ; + // se non ho isole allora controllo casi ottimizzati + if ( ! bHasIsland) { + // caso spirale + PtrOwner pCrvBorder( CreateCurveComposite()) ; + pCrvBorder->AddCurve( pSrfPock->GetLoop( 0, 0)->Clone()) ; + Point3d ptCen ; Vector3d vtN ; double dRad ; bool bCCW ; + if ( pCrvBorder->IsACircle( 100 * EPS_SMALL, ptCen, vtN, dRad, bCCW)) { + double dIntRad = 0 ; + if ( m_Params.m_nSubType == POCKET_SUB_SPIRALOUT && GetLeadInType() == POCKET_LI_HELIX) { + dIntRad = min( 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam), dRad - dOffs) ; + m_dMaxHelixRad = dIntRad ; + } + return CalcCircleSpiral( ptCen, vtN, dRad - dOffs, dIntRad, bSplitArcs, pMCrv, pRCrv) ; } - vtDir.Normalize() ; - Vector3d vtOrtho = OrthoCompo( vtOtherDir, vtDir) ; - double dPocketSize = vtOrtho.Len() ; - if ( dPocketSize < m_TParams.m_dDiam + EPS_SMALL) { - if ( nReg == 0) { - CalcTrapezoidSpiral( pCrvPocket, vtDir, dPocketSize, pMCrv, pRCrv, bOptimizedTrap) ; + // caso trapezoide + int nCrvId = pSrfPock->GetLoop( 0, 0)->GetTempProp( 0) ; + PtrOwner pCrvPocket( CloneCurveComposite( m_pGeomDB->GetGeoObj( nCrvId))) ; + if ( IsNull( pCrvPocket)) + return true ; + SetCurveAllTempProp( nCrvId, pCrvPocket) ; + pCrvPocket->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + + Point3d pt ; Vector3d vtB1, vtL1, vtB2 ; + if ( pCrvPocket->IsATrapezoid( 100 * EPS_SMALL, pt, vtB1, vtL1, vtB2)) { + Vector3d vtDir( vtB1), vtOtherDir( vtL1) ; + // se parallelogramma scelgo come base i lati lunghi + Vector3d vtL2( - vtB1 + vtL1 + vtB2) ; + if ( AreSameOrOppositeVectorApprox( vtL1, vtL2)) { + if ( vtL1.Len() > vtB1.Len()) + swap( vtDir, vtOtherDir) ; + } + vtDir.Normalize(); + Vector3d vtOrtho = OrthoCompo( vtOtherDir, vtDir); + double dPocketSize = vtOrtho.Len() ; + if ( dPocketSize < m_TParams.m_dDiam + EPS_SMALL) { + CalcTrapezoidSpiral( pCrvPocket, vtDir, dPocketSize, pMCrv, pRCrv, bOptimizedTrap); + ModifyCurveToSmooted( pCrvPocket, 0.002, 0.002) ; if ( bOptimizedTrap) return true ; } - else - return true ; } + } // ciclo di offset verso l'interno const int MAX_ITER = 1000 ; int nIter = 0 ; - ICURVEPOVECTOR vOffs ; - ICURVEPOVECTOR vCrvStack ; - DBLVECTOR vRadStack ; - PtrOwner pOffs ; - double dCurrRad = GetCurveRadius( pCompo) ; + ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset + ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset + + PtrOwner pSrfAct( CloneSurfFlatRegion( pSrfToWork)) ; // regione attuale + PtrOwner pSrfPrec( CloneSurfFlatRegion( pSrfToWork)) ; // regione precedente + if( IsNull( pSrfAct) || IsNull( pSrfPrec) || pSrfAct->GetChunkCount() == 0 || pSrfPrec->GetChunkCount() == 0) + return false ; + PtrOwner pCutRegion( CreateSurfFlatRegion()) ; // regione lavorata dall'utensile + while ( nIter < MAX_ITER) { - // calcolo - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( ( nIter == 0 ? (ICurve*) pCompo : pOffs), - dOffs, ICurve::OFF_FILLET) || - ( nIter == 0 && nReg == 0 && OffsCrv.GetCurveCount() == 0)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + // salvo la regione + pSrfPrec.Set( pSrfAct->Clone()) ; + // calcolo offset della flatRegion + if ( ! pSrfAct->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; + + // estraggo il contorno della FlatRegion (ciclo i Chunks e prendo i rispettivi Loops) + if ( nIter == 0) { + PtrOwner pSrfChunknReg( pSrfAct->CloneChunk( nReg)) ; + if ( IsNull( pSrfChunknReg)) // se supero i chunk ottenuti + return true ; + pSrfAct.Set( Release( pSrfChunknReg)) ; } - // se primo offset e richiesta regione oltre il massimo, esco - if ( nIter == 0 && nReg >= OffsCrv.GetCurveCount()) - return true ; - // recupero le curve di offset e le metto sullo stack (se primo offset solo quella voluta) - int nCount = 0 ; - ICurve* pCrv = OffsCrv.GetLongerCurve() ; - while ( pCrv != nullptr) { - if ( nIter != 0 || nReg == nCount) { - vCrvStack.emplace_back( pCrv) ; - vRadStack.emplace_back( dCurrRad) ; - if ( nIter == 0) - break ; + + int nChunks = pSrfAct->GetChunkCount(); + + for ( int i = 0 ; i < nChunks; i++ ) { + // per ogni chunk... + int nLoops = pSrfAct->GetLoopCount( i) ; + for ( int j = 0 ; j < nLoops ; j++ ) { + // per ogni loop... + PtrOwner ptoCCBorder( GetCurveComposite( pSrfAct->GetLoop( i, j))) ; + if ( j > 0 ) // inverto l'orientamento delle curve interne (offset delle isole trovate) + ptoCCBorder->Invert() ; + // controllo quali regioni di Offset possono essere sostituite + bool bInsert = true ; + + ICurveArc* pCrvToolShape( CreateCurveArc()) ; // superifice di ingombro del tool + if ( pCrvToolShape == nullptr) + return false ; + + // prendo il centroide dell'Offset + Point3d ptC ; + ptoCCBorder->GetCentroid( ptC) ; + + // creo la curva che rappresenta il mio Tool centrata nel centroide dell'Offset + pCrvToolShape->SetXY( ptC, m_TParams.m_dDiam / 2 + 5 * EPS_SMALL) ; + + // guardo se l'Offset è contenuto nella curva del Tool + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *ptoCCBorder, *pCrvToolShape) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + + if ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN && vOffs.size() > 0) + bInsert = false ; + + if( bInsert) + vOffs.emplace_back( Release( ptoCCBorder)) ; + + PtrOwner ptoCCExtBorder( GetCurveComposite( pSrfAct->GetLoop( i, j))) ; + if ( nIter == 0 ) { // salvo il bordo per i link (non invertiti) + vOffsFirstCurve.emplace_back( Release( ptoCCExtBorder)) ; + } } - else - delete( pCrv) ; - pCrv = OffsCrv.GetCurve() ; - ++ nCount ; } - // recupero la prossima curva di offset - PtrOwner pNextOffs ; - if ( ! vCrvStack.empty()) { - pNextOffs.Set( Release( vCrvStack.back())) ; - vCrvStack.pop_back() ; - dCurrRad = vRadStack.back() ; - vRadStack.pop_back() ; - } - double dRad = GetCurveRadius( pNextOffs) ; - bool bNextOk = ( dRad > EPS_ZERO && dRad < dCurrRad) ; + bool bSmallRad = ( nIter == 0 ? dOffs < dTRad + GetOffsR() + EPS_ZERO : dOffs < dTRad + EPS_ZERO) ; - // se completato step di offset, accodo la curva offsettata al percorso di lavoro - if ( ! IsNull( pOffs) && ( bNextOk || bSmallRad)) { - // inserisco l'offset nel vettore - vOffs.emplace_back( Release( pOffs)) ; - } - // se offset va bene - if ( bNextOk) { - // sistemo per prossimo step - dCurrRad = dRad ; - pOffs.Set( Release( pNextOffs)) ; - // nuovo valore pari allo step + + if ( nChunks > 0) { dOffs = GetSideStep() ; } - // se altrimenti riducibile, provo con offset ridotto al raggio utensile else if ( ! bSmallRad) { - // nuovo valore pari al raggio - dOffs = ( nIter == 0 ? dTRad + GetOffsR() : dTRad) ; - } - // altrimenti esco - else + pSrfAct.Set( Release( pSrfPrec)) ; + dOffs = ( nIter == 0 ? dTRad + GetOffsR() : dTRad ) ; + } + else break ; - // incremento contatore iterazioni - ++ nIter ; - } - // calcolo i collegamenti + ++ nIter ; + } + + // se non ho trovato curve di Offset allora esco + if ( vOffs.size() == 0) + return true ; + + // cambio il punto iniziale della prima Curva di Offset + Point3d ptNewStart ; + if ( vOffs[0]->IsPointOn( ptStart)) { + double duS ; + vOffs[0]->GetParamAtPoint( ptStart, duS) ; + vOffs[0]->ChangeStartPoint( duS) ; + } + else { // se non dovesse essere sulla curva, allora cerco il più vicino + int nFlag ; + if ( DistPointCurve( ptStart, *vOffs[0]).GetMinDistPoint( EPS_SMALL, ptNewStart, nFlag)) { + double duS ; + vOffs[0]->GetParamAtPoint( ptNewStart, duS) ; + vOffs[0]->ChangeStartPoint( duS) ; + } + } + + // smusso le curve di offset ( ad eccezione della prima) + ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse + + for ( int i = 0; i < vOffs.size(); i++ ) { + if( i != 0) + ModifyCurveToSmooted( vOffs[i], 0.01, 0.01) ; + vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ; + } + + for ( int i = 0 ; i < vOffsFirstCurve.size() ; i++ ) { + if( i != 0 ) + ModifyCurveToSmooted( vOffsFirstCurve[i], 0.01, 0.01) ; + vOffsFirstCurve[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + } + + // setto il punto iniziale della svuotatura + double dNewUS ; + vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS); + vOffs[0]->ChangeStartPoint( dNewUS) ; + + // riordino le curve cambiando il loro punto di inizio e creando poi i collegamenti + int nClosestInd = -1 ; int nFlag ; int nFocus = 0 ; + double dDist = INFINITO ; + Point3d ptHelp ; ICURVEPOVECTOR vLinks( vOffs.size()) ; - for ( int i = 1 ; i < int( vOffs.size()) ; ++ i) { - // punti di inizio e fine - Point3d ptStart ; - vOffs[i-1]->GetEndPoint( ptStart) ; - Point3d ptEnd ; - vOffs[i]->GetStartPoint( ptEnd) ; - // calcolo il collegamento (garantendo che non esca dalla svuotatura) - PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) - vLinks[i].Set( Release( pCrvLink)) ; + + for ( int i = 0 ; i < vOffs.size() - 1; i++) { + + Point3d ptS ; + if ( ! vOffs[i]->GetStartPoint( ptS)) + return false ; + + // setto i default delle variabili + if ( ! DistPointCurve( ptS, *vOffs[i+1]).GetMinDistPoint( EPS_SMALL, ptHelp, nFlag)) + return false ; + dDist = INFINITO ; + + for ( int j = i + 1 ; j <= vOffs.size() - 1; j++) { + // cerco il punto più vicino della curva + Point3d ptE ; + + if ( ! DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptE, nFlag)) + return false ; + + if ( dDist > Dist( ptS, ptE) ) { + dDist = Dist( ptS, ptE) ; + nClosestInd = j ; + ptHelp.Set( ptE.x, ptE.y, ptE.z) ; + } + } + // avendo la curva più vicina ... + + // 1) scambio la curva i con la curva nClosestInd + if ( nClosestInd != i + 1) { + PtrOwner ptoCCHelp( GetCurveComposite( Release( vOffs[i + 1]))) ; + vOffs[i + 1].Set( Release( vOffs[nClosestInd])) ; + vOffs[nClosestInd].Set( Release( ptoCCHelp)) ; + } + + // 2) cambio il suo punto iniziale ... + double dU ; + Point3d ptNE( ptHelp.x, ptHelp.y, ptHelp.z) ; + if ( ! vOffs[i + 1]->GetParamAtPoint( ptNE, dU)) + return false ; + vOffs[i + 1]->ChangeStartPoint( dU) ; + + // 2.1) Accorcio la curva per velocizzare ... + if( i == 0 ) { + PtrOwner pCrvExtraOff0( CreateCurveComposite()) ; + if ( IsNull( pCrvExtraOff0)) + return false ; + double dUExtra0 ; + vOffs[0]->GetParamAtLength( m_TParams.m_dDiam/4, dUExtra0) ; + pCrvExtraOff0->AddCurve( GetCurve( vOffs[0]->CopyParamRange( 0, dUExtra0))) ; + //vOffs[0]->AddCurve( Release( pCrvExtraOff0)) ; + PtrOwner pCrvExtraOff1( CreateCurveComposite()) ; + if ( IsNull( pCrvExtraOff1)) + return false ; + double dUExtra1, dLen1, duS, duE ; + if( vOffs.size() > 0) { + vOffs[1]->GetLength( dLen1) ; + if ( dLen1 > m_TParams.m_dDiam/4) { + vOffs[1]->GetParamAtLength( dLen1 - m_TParams.m_dDiam / 4, dUExtra1) ; + vOffs[1]->GetDomain( duS, duE) ; + pCrvExtraOff1->AddCurve( GetCurve( vOffs[1]->CopyParamRange( dUExtra1, duE))) ; + } + + PtrOwner pCrvLink( CreateCurveComposite()) ; + Vector3d vS, vE ; + if ( ! pCrvExtraOff0->GetEndDir( vS) + || ! pCrvExtraOff0->GetEndPoint( ptS) + || ! pCrvExtraOff1->GetStartDir( vE) + || ! pCrvExtraOff1->GetStartPoint( ptNE)) + return false ; + if ( CalcBoundedLink( ptS, ptNE, vOffsFirstCurve, pCrvLink)) { + PtrOwner pCrvFirstLink( Release( pCrvExtraOff0)) ; + pCrvFirstLink->AddCurve( Release( pCrvLink)) ; + pCrvFirstLink->AddCurve( Release( pCrvExtraOff1)) ; + ModifyCurveToSmooted( pCrvFirstLink, 0.025, 0.025) ; + vLinks[1].Set( Release( pCrvFirstLink)) ; + } + } + else { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false ; + } + + } else { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + double dUNS, dUNE, dUNEE, dLen ; + PtrOwner pCrvTest( CreateCurveComposite()) ; + PtrOwner pOff_i0(CloneCurveComposite( vOffs[i])) ; + PtrOwner pOff_i1(CloneCurveComposite( vOffs[i + 1])) ; + if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest)) { + PtrOwner pCrvLink( CreateCurveComposite()) ; + Vector3d vS, vE ; + vOffs[i].Set( Release( pOff_i0)) ; vOffs[i+1].Set( Release(pOff_i1)) ; + if ( ! vOffs[i]->GetStartDir( vS) || ! vOffs[i+1]->GetStartDir( vE)) + return false ; + if ( CalcBoundedSmootedLink( ptS, vS, ptNE, vE, 0.5, vOffsFirstCurve, pCrvLink)) + vLinks[i + 1].Set( Release( pCrvLink)) ; + else { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + return false ; + } + continue ; + } + + if ( ! pCrvTest->GetStartPoint( ptS) + || ! pCrvTest->GetEndPoint( ptNE) + || ! vOffs[i]->GetParamAtPoint( ptS, dUNS) + || ! vOffs[i+1]->GetParamAtPoint( ptNE, dUNE) ) + return false ; + + vOffs[i+1]->ChangeStartPoint( dUNE) ; + PtrOwner pCrvNewOffS( GetCurveComposite( vOffs[i]->CopyParamRange( 0, dUNS))) ; + vOffs[i]->Clear() ; + vOffs[i].Set( Release( pCrvNewOffS)) ; + vLinks[i + 1].Set( Release( pCrvTest)) ; + } + } + + // 3) controllo eventuali parti non svuotate... + PtrOwner pSrfToCut( CreateSurfFlatRegion()) ; + if ( GetUnclearedRegion( vOffsFirstCurve, vOffs, vLinks, pSrfToCut)) { + // 4) Modifico i percorsi + if ( ! RemoveExtraParts( pSrfToCut, vOffs, vOffsClosedCurves, vOffsFirstCurve, vLinks)) { return false ; } } // calcolo il percorso di ritorno if ( vOffs.size() >= 2) { - // punti di inizio e fine - Point3d ptStart ; - vOffs.back()->GetEndPoint( ptStart) ; - Point3d ptEnd ; - vOffs.front()->GetStartPoint( ptEnd) ; + + pRCrv->Clear() ; + // punto inziale e finale | vettore iniziale e finale + Point3d ptStart ; vOffs.back()->GetEndPoint( ptStart) ; + Point3d ptEnd ; vOffs.front()->GetStartPoint( ptEnd) ; + Vector3d vtStart ; vOffs.back()->GetEndDir( vtStart) ; + Vector3d vtEnd ; vOffs.front()->GetStartDir( vtEnd) ; + // calcolo il ritorno (garantendo che non esca dalla svuotatura) PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) { + if ( CalcBoundedSmootedLink( ptStart, vtStart, ptEnd, vtEnd, 0.5, vOffsFirstCurve, pCrvLink)) { pRCrv->AddCurve( Release( pCrvLink)) ; pRCrv->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false) ; // se necessario, approssimo archi con rette @@ -3920,14 +4912,16 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, } } + // creo il percorso di lavoro a partire dalla raccolta degli offset e dei collegamenti for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { // se collegamento da aggiungere if ( ! IsNull( vLinks[i])) { int nCrvsCount0 = pMCrv->GetCurveCount() ; // accodo nel percorso di lavorazione - pMCrv->AddCurve( Release( vLinks[i])) ; - // nel caso di lucidatura setto proprietà alle curve di collegamento per poterle identificare + if ( ! pMCrv->AddCurve( vLinks[i]->Clone())) + return false ; + // nel caso di lucidatura setto proprietà alle curve di collegamento per poterle identificare if ( m_TParams.m_nType == TT_MILL_POLISHING) { for ( int j = nCrvsCount0 ; j < pMCrv->GetCurveCount() ; j ++) pMCrv->SetCurveTempProp( j, LINK_CURVE_PROP) ; @@ -3937,7 +4931,7 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, if ( m_Params.m_bInvert) vOffs[i]->Invert() ; // aggiungo la curva - pMCrv->AddCurve( Release( vOffs[i])) ; + pMCrv->AddCurve( vOffs[i]->Clone()) ; } // verifico il percorso di lavoro @@ -3955,79 +4949,1590 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, // setto estrusione Vector3d vtExtr ; - if ( pCompo->GetExtrusion( vtExtr)) - pMCrv->SetExtrusion( vtExtr) ; + if( vOffs.size() > 0) + if ( vOffs[0]->GetExtrusion( vtExtr)) + pMCrv->SetExtrusion( vtExtr) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::ModifyCurveToSmooted( ICurveComposite* pCrv, double dRightPer, double dLeftPer) { + + // controllo parametri + if ( pCrv == nullptr) + return false ; + + ICURVEPOVECTOR vCrvStepsToFill; // vettore delle Curve da raccordare (curve della composita) + ICURVEPOVECTOR vCrvArcs ; // vettore contenente gli Archi (tra le curve della composita) + INTVECTOR vArcsToJump ; // vettore di indici per gli archi saltati (nel caso non si riesca a raccordare ...) + + // se nella composita ho meno di due curve allora non c'è nulla da raccordare + const ICurve* pMyCrv = pCrv->GetFirstCurve() ; + while ( pMyCrv != nullptr) { + vCrvStepsToFill.emplace_back( pMyCrv->Clone()) ; + pMyCrv = pCrv->GetNextCurve() ; + } + if ( vCrvStepsToFill.size() < 2) + return false ; + + // 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() ; + vCrvStepsToFill.emplace_back( pMyCrvFirst->Clone()) ; + } + + double dUE_ref, dUS_ref, dRadius, dPar1, dPar2, dULast; + + // riempio il vettore degli archi, scorro tutte le curve da raccordare ( la i-esima e la (i+1)-esima ) + for ( int i = 0; i < vCrvStepsToFill.size() - 1; i++) { + + // controllo che le curve non siano già tangenti + Vector3d vtS, vtE ; + if ( ! vCrvStepsToFill[i]->GetEndDir( vtS) || ! vCrvStepsToFill[i+1]->GetStartDir( vtE)) + continue ; + if ( AreSameVectorApprox( vtS, vtE)) { + vCrvArcs.emplace_back( CreateCurveComposite()) ; // arco nullo + vArcsToJump.push_back( i) ; // da scartare + 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 ; + + vCrvStepsToFill[i+1]->GetDomain( dU_cm_S, dULast2) ; + dUS_ref = dLeftPer * dULast2 ; + + // prendo i punti sulle due curve rispetto a tali parametri + Point3d ptS, 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) ; // uso come raggio la distanza tra i due punti + + int nMaxTestForArcs = 3 ; // tentativi per creare l'arco + int nIterForArcs = 0 ; + bool IntersBTWArcs = false ; + + // creo l'arco di raccordo + PtrOwner pCrvArc( CreateFillet( *vCrvStepsToFill[i]->Clone(), ptS, *vCrvStepsToFill[i+1]->Clone(), ptE, Z_AX, dRadius, dPar1, dPar2)) ; + + // controllo che l'arco creato non sia troppo piccolo + double dArcLen ; + if ( pCrvArc != nullptr && (! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) { + vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo + vArcsToJump.push_back( i) ; // da scartare + continue ; + } + + if ( i != 0 && vArcsToJump[i-1] == -1 && pCrvArc != nullptr) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi + IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ; + if( intCCH.GetIntersCount() > 0 ) + IntersBTWArcs = true ; + } + + // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti + while (( pCrvArc == nullptr || IntersBTWArcs) && nIterForArcs < nMaxTestForArcs) { + + dUE_ref = ( dULast1 + 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)) + return false ; + + dRadius = Dist( ptS, ptE) ; + + pCrvArc.Set( CreateFillet( *vCrvStepsToFill[i]->Clone(), ptS, *vCrvStepsToFill[i+1]->Clone(), ptE, Z_AX, dRadius, dPar1, dPar2)) ; + nIterForArcs++ ; + + IntersBTWArcs = false ; + if ( i != 0 && vArcsToJump[i-1] == -1 && pCrvArc != nullptr) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi + IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ; + if ( intCCH.GetIntersCount() > 0) + IntersBTWArcs = true ; + } + + } + if ( pCrvArc == nullptr) { // se ancora non riesco... salto l'arco + vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo + vArcsToJump.push_back( i) ; // da scartare + continue ; + } + + // se ho creato l'arco lo memorizzo + vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco valido + vArcsToJump.push_back( -1) ; // da considerare + } + + // creo la curva che restituirò + PtrOwner pCrvCO_temp( CreateCurveComposite()) ; + if ( pCrvCO_temp == nullptr) + return false ; + Point3d ptArcHelp, ptFirstPoint ; + + // unisco la curva i-esima con l'arco i-esimo (non guardo l'ultima curva nel vettore, controllo dopo il caso di curva chiusa) + for ( int i = 0 ; i < vCrvStepsToFill.size() -1 ; i++) { + + if ( vArcsToJump[i] == -1) { // se esiste l'arco ... + Point3d ptArcS, ptArcE ; + if ( ! vCrvArcs[i]->GetStartPoint( ptArcS) + || ! vCrvArcs[i]->GetEndPoint( ptArcE) + || ! vCrvStepsToFill[i]->GetParamAtPoint( ptArcS, dUE_ref) + || ! vCrvStepsToFill[i+1]->GetParamAtPoint( ptArcE, dUS_ref)) + return false ; + + if ( i == 0) { // ... e sono nella prima iterazione ... + if ( ! pCrv->IsClosed()) { // ... e se la curva è aperta -> la inserisco nel nuovo percorso + if ( ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[0]->CopyParamRange( 0, dUE_ref)))) + return false ; + } + ptFirstPoint = ptArcS ; + // ... e se la curva è chiusa -> non la inserisco nel nuovo percorso + } + else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) + if ( ! vCrvStepsToFill[i]->GetParamAtPoint( ptArcHelp, dUS_ref) + || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[i]->CopyParamRange( dUS_ref, dUE_ref)))) + return false ; + // aggiungo la curva 'tagliata per il raccordo' + } + + if ( ! pCrvCO_temp->AddCurve( vCrvArcs[i]->Clone())) // aggiungo l'arco di raccordo + return false ; + ptArcHelp = ptArcE ; + } + else { // se non esiste l'arco ... + if ( i == 0 ) { // e sono nella prima iterazione... + if ( ! vCrvStepsToFill[0]->GetEndPoint( ptArcHelp)) + return false ; + + if ( ! pCrv->IsClosed()) { // ...e se aperta // aggiungo la prima curva per intero + if ( ! vCrvStepsToFill[0]->GetParamAtPoint( ptArcHelp, dUE_ref) + || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[0]->CopyParamRange( 0, dUE_ref)))) + return false ; + } + ptFirstPoint = ptArcHelp ; + } + else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) + double dUS_cm ; + if ( ! vCrvStepsToFill[i]->GetParamAtPoint( ptArcHelp, dUS_ref) + || ! vCrvStepsToFill[i]->GetDomain( dUS_cm, dUE_ref) + || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[i]->CopyParamRange( dUS_ref, dUE_ref))) + || ! vCrvStepsToFill[i]->GetEndPoint( ptArcHelp)) + return false ; + } + } + + } + + // ultima curva... + if ( pCrv->IsClosed()) { // se curva chiusa... + if ( ! vCrvStepsToFill[0]->GetParamAtPoint( ptArcHelp, dUS_ref) + || ! vCrvStepsToFill[0]->GetParamAtPoint( ptFirstPoint, dUE_ref) + || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[0]->CopyParamRange( dUS_ref, dUE_ref)))) + return false ; + } + else { // se curva aperta... ( non ha importanza l'esistenza o meno degli archi...) + double dUS_cm ; + if ( ! vCrvStepsToFill[vCrvStepsToFill.size() - 1]->GetParamAtPoint( ptArcHelp, dUS_ref) + || ! vCrvStepsToFill[vCrvStepsToFill.size() - 1]->GetDomain( dUS_cm, dUE_ref) + || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[vCrvStepsToFill.size() - 1]->CopyParamRange( dUS_ref, dUE_ref)))) + return false ; + } + + // ripristino il punto inziale se la curva è chiusa + double dNewDU ; + if ( ! pCrv->IsClosed()) { + if( ! pCrvCO_temp->GetParamAtPoint( ptArcHelp, dNewDU)) + return false ; + pCrvCO_temp->ChangeStartPoint( dNewDU) ; + } + + pCrv->Clear() ; + pCrv->AddCurve( Release( pCrvCO_temp)) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffsCL, + ICRVCOMPOPOVECTOR& vFirstOffset, ICurveComposite* pCrvLink, double dLenPercS, double dLenPercE, int nMaxIter) { + + // controllo i parametri + if ( pCrvS == nullptr || pCrvE == nullptr ) + return false ; + pCrvLink->Clear() ; + + PtrOwner ptCrvFinal( CreateCurveComposite()) ; + if ( ptCrvFinal == nullptr) + 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; + + pCrvS->GetEndPoint( ptSE) ; + pCrvS->GetStartPoint( ptSS); + pCrvE->GetStartPoint( ptES); + pCrvE->GetEndPoint( ptEE) ; + pCrvS->GetEndDir( vS) ; + pCrvE->GetStartDir( vE) ; + pCrvS->GetDomain( dUSS, dUSE) ; + pCrvE->GetDomain( dUES, dUEE) ; + pCrvS->GetLength( dLenS) ; + pCrvE->GetLength( dLenE) ; + + // se ho una curva di primo Offset allora non devo accorciarla ... + bool bCut = true ; + for ( int i = 0 ; i < vFirstOffset.size() ; i++ ) { + if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE)) + dLenPercS = 0 ; + if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE)) + dLenPercE = 0 ; + } + + + double dLStepS = dLenPercS * dLenS ; + double dLStepE = dLenPercE * dLenE ; + dLenE = 0 ; + + // calcolo i possibili BiArchi tra le due curve + int nIter = 0; + + while ( nIter < nMaxIter) { + + // calcolo il BiArco + PtrOwner ptBiArc( CreateCurveComposite()) ; + if ( ! CalcBoundedSmootedLink( ptSE, vS, ptES, vE, 0.5, vFirstOffset, ptBiArc) + || ptBiArc->GetCurveCount() == 0) + return false ; + + ptCrvFinal->Clear() ; + ptCrvFinal.Set( ptBiArc->Clone()) ; + + if ( dLenPercE == 0 && dLenPercS == 0 ) + break ; + + // se il BiArco creato interseca le altre curve di Offset allora mi fermo... + bool bInterr = false ; + for ( int i = 0 ; i < vOffsCL.size() && ! bInterr ; i++) { + if ( vOffsCL[i]->IsPointOn( ptSE) || vOffsCL[i]->IsPointOn( ptES)) + continue ; + + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *ptBiArc, *vOffsCL[i]) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ccClass.size() > 1) // se intersezione + bInterr = true ; + } + if ( bInterr) + break ; // così come ultimo arco ho quello precedente (valido) + + // se ho trovato un BiArco valido, allora accorcio le due curve di Offset + dLenS -= dLStepS ; + dLenE += dLStepE ; + + if ( ! pCrvS->GetParamAtLength( dLenS, dUSE) + || ! pCrvS->GetPointD1D2( dUSE, ICurve::FROM_MINUS, ptSE) + || ! pCrvE->GetParamAtLength( dLenE, dUES) + || ! pCrvE->GetPointD1D2( dUES, ICurve::FROM_PLUS, ptES)) + return false ; + ICurveComposite* pCrvS_clone( pCrvS->Clone()) ; // curva di Offset iniziale accorciata + ICurveComposite* pCrvE_clone( pCrvE->Clone()) ; // curva di Offset finale accorciata + pCrvS_clone->ChangeStartPoint( dUSE) ; + pCrvE_clone->ChangeStartPoint( dUES) ; + + if ( ! pCrvS_clone->GetStartDir( vS) || ! pCrvE_clone->GetStartDir( vE)) + return false ; + + nIter++ ; + } + + pCrvLink->AddCurve( ptCrvFinal->Clone()) ; // ultimo arco valido trovato return true ; } //---------------------------------------------------------------------------- bool -Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICurve* pCrvBound, - ICurveComposite* pCrvLink) -{ - // recupero il vettore estrusione - Vector3d vtExtr ; - pCrvBound->GetExtrusion( vtExtr) ; - // determino il riferimento naturale della svuotatura (OCS con il vettore estrusione come asse Z) - Frame3d frLoc ; - frLoc.Set( ORIG, vtExtr) ; - // porto la curva di contenimento in locale a questo riferimento - CurveLocal CrvOutLoc( pCrvBound, GLOB_FRM, frLoc) ; +Pocketing::RemoveExtraParts( ISurfFlatRegion* pSrfToCut, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffsClosedCurves, ICRVCOMPOPOVECTOR& vOffsFirstCurve, ICURVEPOVECTOR& vLinks) { - // creo la retta che li unisce - PtrOwner pLine( CreateCurveLine()) ; - if ( IsNull( pLine) || ! pLine->Set( ptStart, ptEnd)) - return false ; - pLine->SetExtrusion( vtExtr) ; - // la porto in locale al riferimento della svuotatura - CurveLocal LineLoc( pLine, GLOB_FRM, frLoc) ; - - // classifico la curva di collegamento rispetto a quella di contenimento - CRVCVECTOR ccClass ; - IntersCurveCurve intCC( *LineLoc, *CrvOutLoc) ; - intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; - // se nessuno o un solo tratto e interno, la retta è il collegamento - if ( ccClass.empty() || ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN)) { - pCrvLink->AddCurve( Release( pLine)) ; + if ( pSrfToCut == nullptr || vOffs.size() == 0) return true ; - } - // altrimenti combino i tratti interni di retta con tratti opportuni della curva di contenimento - else { - PtrOwner pCompo( CreateCurveComposite()) ; - if ( IsNull( pCompo)) + + // ciclo tutti i chunk della regione da tagliare + for ( int i = 0 ; i < pSrfToCut->GetChunkCount() ; i++ ) { + + // prendo il bordo del chunk + PtrOwner pCrvChunkBorder( pSrfToCut->GetLoop( i, 0)) ; + if ( IsNull( pCrvChunkBorder)) return false ; - for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { - if ( ccClass[j].nClass == CRVC_IN || ccClass[j].nClass == CRVC_ON_P || ccClass[j].nClass == CRVC_ON_M) - pCompo->AddCurve( pLine->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; - else if ( ccClass[j].nClass == CRVC_OUT) { - Point3d ptS ; - pLine->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; - double dOffS ; - pCrvBound->GetParamAtPoint( ptS, dOffS) ; - Point3d ptE ; - pLine->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; - double dOffE ; - pCrvBound->GetParamAtPoint( ptE, dOffE) ; - // recupero i due possibili percorsi e uso il più corto - PtrOwner pCrvA( pCrvBound->CopyParamRange( dOffS, dOffE)) ; - PtrOwner pCrvB( pCrvBound->CopyParamRange( dOffE, dOffS)) ; - if ( IsNull( pCrvA) || IsNull( pCrvB)) + + // 1) regione i-esima da rimuovere + PtrOwner pSrfChunkToCut( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfChunkToCut)) + return false ; + if ( ! pSrfChunkToCut->AddExtLoop( pCrvChunkBorder->Clone())) + return false ; + + // 2) Curva nel caso la regione si svuoti con MedialAxis + PtrOwner pCrvPath( CreateCurveComposite()) ; + if ( IsNull( pCrvPath)) + return false ; + + // 3) Punto nel caso la regione si svuoti con un centroide + Point3d ptGoTo, ptGoToI ; + int nOptFlag ; + + if ( ! RemoveExtraPartByMedialAxis( pSrfChunkToCut, vOffsFirstCurve, nOptFlag, ptGoTo, pCrvPath) + || nOptFlag == 0) + continue ; + + if ( nOptFlag == 2 ) + if ( ! pCrvPath->GetStartPoint( ptGoTo) + || ! pCrvPath->GetEndPoint( ptGoToI)) + continue ; + + // 1) cerco la curva più vicina al punto trovato (ptGoTo) + PtrOwner pCrvH1( CreateCurveComposite()) ; + PtrOwner pCrvH2( CreateCurveComposite()) ; + PtrOwner pCrvH1I( CreateCurveComposite()) ; + PtrOwner pCrvH2I( CreateCurveComposite()) ; + + if ( pCrvH1 == nullptr || pCrvH2 == nullptr) + return false ; + int nIndexO = -1 ; + int nIndexOI = -1 ; + Point3d ptS, ptSI ; + + if ( ! GetClosestOffsetToAPoint( vOffs, ptGoTo, ptS, pCrvH1, pCrvH2, nIndexO)) + continue ; + if( nOptFlag == 2) + if ( ! GetClosestOffsetToAPoint( vOffs, ptGoToI, ptSI, pCrvH1I, pCrvH2I, nIndexOI)) + continue ; + + // A) SE SONO SU UN ESTREMO DELLA CURVA DI OFFSET -> Cerco un punto sui collegamenti + if ( pCrvH1 == nullptr || pCrvH2 == nullptr) { + bool bFound, bFoundI ; int nIndexL, nIndexLI ; + if ( ! GetClosestLinkToAPoint( vLinks, vOffs, ptGoTo, ptS, pCrvH1, pCrvH2, bFound, nIndexL)) + continue ; + if( nOptFlag == 2) + if ( ! GetClosestLinkToAPoint( vLinks, vOffs, ptGoToI, ptSI, pCrvH1I, pCrvH2I, bFoundI, nIndexLI)) + continue ; + + PtrOwner ptCrvNewLink( CreateCurveComposite()) ; + if ( ptCrvNewLink == nullptr) + return false ; + + if ( nOptFlag == 1) { + if ( ! GetNewCurvetWithCentroid( pCrvH1, pCrvH2, ptGoTo, bFound, vOffsFirstCurve, ptCrvNewLink)) + continue ; + } else if ( nOptFlag == 2) { + + bool bSucc = true; bool bSuccI = true ; + + if ( ! GetNewCurvetWithPath( pCrvH1, pCrvH2, pCrvPath, vOffsFirstCurve, vOffsClosedCurves, ptCrvNewLink)) + bSucc = false; + + double dLen, dLenI ; + PtrOwner pCrvPathI( pCrvPath->Clone()) ; + pCrvPathI->Invert() ; + PtrOwner ptCrvNewLinkI( CreateCurveComposite()) ; + if ( ptCrvNewLinkI == nullptr) return false ; - double dLenA ; pCrvA->GetLength( dLenA) ; - double dLenB ; pCrvB->GetLength( dLenB) ; - if ( dLenA < dLenB) { - pCompo->AddCurve( Release( pCrvA)) ; + + if ( ! GetNewCurvetWithPath( pCrvH1I, pCrvH2I, pCrvPathI, vOffsFirstCurve, vOffsClosedCurves, ptCrvNewLinkI)) + bSuccI = false; + + int nC = 0 ; + if ( bSucc && bSuccI) { + if ( ChoosePath( ptCrvNewLink, ptCrvNewLinkI, 0, 0.25, 5 * 1000 * EPS_SMALL, nC) && nC == 1) { + ptCrvNewLink.Set( Release( ptCrvNewLinkI)) ; + nIndexL = nIndexLI ; + } } - else { - pCrvB->Invert() ; - pCompo->AddCurve( Release( pCrvB)) ; + else if ( ! bSucc) { + ptCrvNewLink.Set( Release( ptCrvNewLinkI)) ; + nIndexL = nIndexLI ; + } + } + vLinks[nIndexL].Set( Release( ptCrvNewLink)) ; + } + else { // B) SE NON SONO AD UN ESTREMO DELLA CURVA DI OFFSET + PtrOwner ptCrvNewOffs( CreateCurveComposite()) ; + if ( ptCrvNewOffs == nullptr) + return false ; + + if ( nOptFlag == 1) { + if ( ! GetNewCurvetWithCentroid( pCrvH1, pCrvH2, ptGoTo, true, vOffsFirstCurve, ptCrvNewOffs)) + continue ; + } + else if ( nOptFlag == 2) { // nel caso aggiungo un medial Axis non agli estremi di un Offset + + bool bSucc = true; bool bSuccI = true; + + if ( ! GetNewCurvetWithPath( pCrvH1, pCrvH2, pCrvPath, vOffsFirstCurve, vOffsClosedCurves, ptCrvNewOffs)) + bSucc == false ; + + double dLen, dLenI ; + PtrOwner pCrvPathI( pCrvPath->Clone()) ; + pCrvPathI->Invert() ; + PtrOwner ptCrvNewOffsI( CreateCurveComposite()) ; + if ( ptCrvNewOffsI == nullptr) + return false ; + + if ( ! GetNewCurvetWithPath( pCrvH1I, pCrvH2I, pCrvPathI, vOffsFirstCurve, vOffsClosedCurves, ptCrvNewOffsI)) + bSuccI = false ; + + int nC = 0 ; // se entrambi i percorsi sono validi allora li confronto + if ( bSucc && bSuccI) { + if ( ChoosePath( ptCrvNewOffs, ptCrvNewOffsI, 0, 0.5, 5 * 1000 * EPS_SMALL, nC) && nC == 1) { + ptCrvNewOffs.Set( Release( ptCrvNewOffsI)) ; + nIndexO = nIndexOI ; + } + } + else if ( ! bSucc) { + ptCrvNewOffs.Set( Release( ptCrvNewOffsI)) ; + nIndexO = nIndexOI ; + } + } + vOffs[nIndexO].Set( Release( ptCrvNewOffs)) ; + } + } + + return true ; +} + +//--------------------------------------------------------------------------- +bool +Pocketing::GetCurveWeightInfo( ICurveComposite* pCrvCompo, double dMaxLen, double& dToTRot, int& nSmallArcs, int& nSmallLines) { + + dToTRot = 0 ; nSmallArcs = 0 ; nSmallLines = 0 ; + if ( pCrvCompo == nullptr) + return true ; + + int nLines = 0 ; + PtrOwner pCrvLineOld( CreateCurveLine()) ; + + // scorro tutte le curve trovate + const ICurve* pMyCrv = pCrvCompo->GetFirstCurve() ; + while ( pMyCrv != nullptr) { + GeoObjType GeoType = pMyCrv->GetType() ; + if ( GeoType == CRV_ARC) { + nLines = 0 ; + PtrOwner pCrvArc( GetCurveArc(pMyCrv->Clone())) ; + double dAngCenter = abs( pCrvArc->GetAngCenter()) ; + dToTRot += dAngCenter ; + double dLen = 0 ; + if ( pCrvArc->GetLength( dLen) && dLen < dMaxLen) + nSmallArcs++ ; + } + else if ( GeoType == CRV_LINE) { // check nel caso non sia riuscito a smussare... + nLines++ ; + if ( nLines == 1) + pCrvLineOld.Set( GetCurveLine( pMyCrv->Clone())) ; + else { + PtrOwner pNewMyCrv( GetCurveLine( pMyCrv->Clone())) ; + Vector3d vtNew, vtOld ; + pCrvLineOld->GetEndDir( vtOld) ; + pNewMyCrv->GetStartDir( vtNew) ; + double dAngCorner ; vtOld.GetAngle( vtNew, dAngCorner) ; + dToTRot += abs( dAngCorner) ; + pCrvLineOld.Set( GetCurveLine( Release( pNewMyCrv))) ; + } + + double dLen = 0 ; + if ( pMyCrv->GetLength( dLen) && dLen < dMaxLen) + nSmallLines++ ; + } + pMyCrv = pCrvCompo->GetNextCurve() ; + } + + return true ; +} + +//--------------------------------------------------------------------------- +bool +Pocketing::ChoosePath( ICurveComposite* pCrv1, ICurveComposite* pCrv2, int nP, double dPerP, double dMaxLen, int& nC) { + + // controllo dei parametri + if ( pCrv1 == nullptr || pCrv2 == nullptr + || ! ( nP == 0 || nP == 1) + || dPerP > 1 || dPerP < 0 + || dMaxLen < EPS_SMALL) + return false ; + + // lunghezze... + double dLen1 = 0 ; double dLen2 = 0 ; + pCrv1->GetLength( dLen1) ; + pCrv2->GetLength( dLen2) ; + + double CL1, CL2 ; + + if ( dLen1 < EPS_SMALL && dLen2 < EPS_SMALL) { + CL1 = 0 ; + CL2 = 0 ; + } + else { + CL1 = dLen1 / max( dLen1, dLen2) ; + CL2 = dLen2 / max( dLen1, dLen2) ; + } + + // rotazioni... + double dRot1 = 0; double dRot2 = 0 ; int dSmallArcs1 = 0 ; int dSmallArcs2 = 0 ; int dSmallLines1 = 0 ; int dSmallLines2 = 0 ; + if ( ! GetCurveWeightInfo( pCrv1, dMaxLen, dRot1, dSmallArcs1, dSmallLines1) + || ! GetCurveWeightInfo( pCrv2, dMaxLen, dRot2, dSmallArcs2, dSmallLines2)) + return false ; + + double CR1, CR2 ; + + if ( dRot1 == 0 && dRot2 == 0) { + CR1 == 0 ; + CR2 == 0 ; + } + else { + CR1 = dRot1 / max( dRot1, dRot2) ; + CR2 = dRot2 / max( dRot1, dRot2) ; + } + + double Fp1 = ( nP == 0 ? dPerP : ( 1 - dPerP)) * (CL1 + dSmallLines1) + ( nP == 0 ? ( 1 - dPerP) : dPerP) * ( CR1 + dSmallArcs1) ; + double Fp2 = ( nP == 0 ? dPerP : ( 1 - dPerP)) * (CL2 + dSmallLines2) + ( nP == 0 ? ( 1 - dPerP) : dPerP) * ( CR2 + dSmallArcs2) ; + + nC = ( Fp1 > Fp2 ? 1 : 0) ; + return true ; +} + +//--------------------------------------------------------------------------- +bool +GetClosestOffsetToAPoint( ICRVCOMPOPOVECTOR& vCurves, Point3d& ptFocus, Point3d& ptCL, ICurveComposite* pCrv1, ICurveComposite* pCrv2, int& nIndex, bool bFirst) { + + // check paramtri + if ( vCurves.size() == 0) + return false ; + + // cerco il punto più vicino a ptFocus su ogni curva e scelgo quello a distanza minimia (da ptFocus) + Point3d ptCl_H ; + double dDistance = INFINITO ; + int nFlag ; + pCrv1->Clear() ; + pCrv2->Clear() ; + + if (vCurves.size() == 1) { + nIndex = 0 ; + if ( ! DistPointCurve( ptFocus, *vCurves[0]).GetMinDistPoint( EPS_SMALL, ptCL, nFlag)) + return false ; + } + + for ( int j = 1; j < vCurves.size(); j++ ) { + if ( ! DistPointCurve( ptFocus, *vCurves[j]).GetMinDistPoint( EPS_SMALL, ptCl_H, nFlag)) + return false ; + + if ( dDistance > Dist( ptCl_H, ptFocus)) { + dDistance = Dist( ptCl_H, ptFocus) ; + ptCL = ptCl_H ; + nIndex = j ; + } + } + if ( ! bFirst && vCurves.size() > 1) { + int nindexOld = nIndex ; dDistance = INFINITO ; + for ( int j = 1; j < vCurves.size(); j++ ) { + if ( j != nindexOld) { + if ( ! DistPointCurve( ptFocus, *vCurves[j]).GetMinDistPoint( EPS_SMALL, ptCl_H, nFlag)) + return false ; + + if ( dDistance > Dist( ptCl_H, ptFocus) ) { + dDistance = Dist( ptCl_H, ptFocus) ; + ptCL = ptCl_H ; + nIndex = j ; } } } - pCrvLink->AddCurve( Release( pCompo)) ; + } + + if ( nIndex < 0) + return false ; + + PtrOwner pCrv_H( vCurves[nIndex]->Clone()) ; + + // 2) Sulle curve di Offset ricavo: vettore iniziale, finale | punto iniziale, finale + Vector3d vtTanS, vtTanE, vtHelp ; double dUTan, dLenHelp, dUS, dUE ; bool bMustUseBiArcs = false ; + + if ( ! pCrv_H->GetParamAtPoint( ptCL, dUTan) || ! pCrv_H->GetDomain( dUS, dUE)) + return false ; + + pCrv1->AddCurve( GetCurveComposite( pCrv_H->CopyParamRange( dUS, dUTan))) ; + pCrv2->AddCurve( GetCurveComposite( pCrv_H->CopyParamRange( dUTan, dUE))) ; + + return true ; +} + +//--------------------------------------------------------------------------- +bool +GetClosestLinkToAPoint( ICURVEPOVECTOR& vCurves, ICRVCOMPOPOVECTOR& vOffs, Point3d& ptFocus, Point3d& ptCL, ICurveComposite* pCrv1, ICurveComposite* pCrv2, bool& bfound, int& nIndex) { + + double dDistance = INFINITO; + Point3d ptCl_H ; + int nFlag ; + pCrv1->Clear() ; + pCrv2->Clear() ; + bfound = false ; + + for ( int j = 1; j < vCurves.size(); j++ ) { + if ( ! DistPointCurve( ptFocus, *vCurves[j]).GetMinDistPoint( EPS_SMALL, ptCl_H, nFlag)) + return false ; + + if ( dDistance > Dist( ptCl_H, ptFocus) && ! ( vOffs[j-1]->IsPointOn( ptCl_H) || vOffs[j]->IsPointOn( ptCl_H))) { + dDistance = Dist( ptCl_H, ptFocus) ; + ptCL = ptCl_H ; + nIndex = j ; + bfound = true ; + } + } + + double dUS, dUE, dUTan ; + if ( ! vCurves[nIndex]->GetDomain( dUS, dUE) || ! vCurves[nIndex]->GetParamAtPoint( ptCL, dUTan)) + return false ; + pCrv1->AddCurve( GetCurve( vCurves[nIndex]->CopyParamRange( dUS, dUTan))) ; + pCrv2->AddCurve( GetCurve( vCurves[nIndex]->CopyParamRange( dUTan, dUE))) ; + + return true ; +} + + +//---------------------------------------------------------------------------- +bool +Pocketing::GetNewCurvetWithCentroid( ICurveComposite* pCrvH1, ICurveComposite* pCrvH2, Point3d& ptC, bool bCir, ICRVCOMPOPOVECTOR& VFirstOff, ICurveComposite* pCrvNewCurve) { + + ICurveComposite* pPath1( CreateCurveComposite()) ; + ICurveComposite* pPath2( CreateCurveComposite()) ; + if ( pPath1 == nullptr || pPath2 == nullptr) + return false ; + pCrvNewCurve->Clear() ; + Point3d ptS, ptE = ptC ; + Vector3d vtTanS, vtTanE ; + + if ( bCir) { // creo una circonferenza + // prendo il punto iniziale + if ( pCrvH1 == nullptr || pCrvH1->GetFirstCurve() == nullptr) { + if ( ! pCrvH2->GetStartPoint( ptS)) + return false ; + } + else { + if ( ! pCrvH1->GetEndPoint( ptS)) + return false ; + } + + // creo la circonferenza + if ( ! CalcBoundedSmootedLink( ptS, vtTanS, ptE, vtTanE, 0, VFirstOff, pPath1)) + return false ; + + // controllo che la circonferenza sia ammissibile ( solo che non esca dalle prime curve di Offset ) + Point3d ptCrvS ; pPath1->GetStartPoint( ptCrvS) ; + if ( ! CutCurveByOffsets( pPath1, VFirstOff)) { // taglio la curva sugli Offsets + return false ; + } + double dUCrvS ; + ModifyCurveToSmooted( pPath1, 0.075, 0.075) ; + if ( pPath1->IsClosed()) { + pPath1->GetParamAtPoint( ptCrvS, dUCrvS) ; + pPath1->ChangeStartPoint( dUCrvS) ; + } + + // creo la nuova curva con la circonferenza + if ( pCrvH1 != nullptr && pCrvH1->GetFirstCurve() != nullptr) + if ( ! pCrvNewCurve->AddCurve( pCrvH1->Clone())) // aggiungo inizio + return false ; + if ( ! pCrvNewCurve->AddCurve( pPath1->Clone())) // aggiungo la circonferenza + return false ; + if ( pCrvH2 != nullptr && pCrvH2->GetFirstCurve() != nullptr) + if ( !pCrvNewCurve->AddCurve(( pCrvH2->Clone()))) // aggiungo la fine + return false ; + } + else { // creo un BiArco + + // prendo il vettore tangente e il punto iniziale + if ( pCrvH1 == nullptr || pCrvH1->GetFirstCurve() == nullptr) { + if ( ! pCrvH2->GetStartDir( vtTanS) + || ! pCrvH2->GetStartPoint( ptS)) + return false ; + } + else { + if ( ! pCrvH1->GetEndDir( vtTanS) + || ! pCrvH1->GetEndPoint( ptS)) + return false ; + } + + // creo i due Biarchi + if ( ! CalcBoundedSmootedLink( ptS, vtTanS, ptE, vtTanS, 0.5, VFirstOff, pPath1) + || ! CalcBoundedSmootedLink( ptE, vtTanS, ptS, vtTanS, 0.5, VFirstOff, pPath2)) + return false ; + + // creo la nuova curva con il doppio Biarco + if ( pCrvH1 != nullptr && pCrvH1->GetFirstCurve() != nullptr) + if ( ! pCrvNewCurve->AddCurve( pCrvH1->Clone())) // aggiungo inizio + return false ; + if ( ! pCrvNewCurve->AddCurve( pPath1->Clone()) || ! pCrvNewCurve->AddCurve( pPath2->Clone())) // aggiungo i due BiArchi + return false ; + if ( pCrvH2 != nullptr && pCrvH2->GetFirstCurve() != nullptr) + if ( ! pCrvNewCurve->AddCurve(( pCrvH2->Clone()))) // aggiungo la fine + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::GetNewCurvetWithPath( ICurveComposite* pCrvH1, ICurveComposite* pCrvH2, ICurveComposite* pCrvPath, ICRVCOMPOPOVECTOR& VFirstOff, ICRVCOMPOPOVECTOR& VoffsCl, ICurveComposite* pCrvNewCurve) { + + PtrOwner pPath1( CreateCurveComposite()) ; + PtrOwner pPath2( CreateCurveComposite()) ; + if ( pPath1 == nullptr || pPath2 == nullptr || pCrvPath == nullptr) + return false ; + pCrvNewCurve->Clear() ; + Point3d ptS, ptE, ptH ; + Vector3d vtTanS, vtTanE, vtH ; + + if ( ! pCrvPath->GetStartPoint( ptE) + || ! pCrvPath->GetStartDir( vtTanE) + || ! pCrvPath->GetEndPoint( ptH) + || ! pCrvPath->GetEndDir( vtH)) + return false ; + + if ( pCrvH1 == nullptr || pCrvH1->GetFirstCurve() == nullptr) { + if ( ! pCrvH2->GetStartPoint( ptS) + || ! pCrvH2->GetStartDir( vtTanS)) + return false ; + } + else { + if ( ! pCrvH1->GetEndPoint( ptS) + || ! pCrvH1->GetEndDir( vtTanS)) + return false ; + } + + // creo i due Biarchi + if ( ! CalcBoundedSmootedLink( ptS, vtTanS, ptE, vtTanE, 0.5, VFirstOff, pPath1)) + if( ! CalcBoundedLink( ptS, ptE, VFirstOff, pPath1)) + return false ; + if( ! CalcBoundedSmootedLink( ptH, vtH, ptS, vtTanS, 0.5, VFirstOff, pPath2)) + if( ! CalcBoundedLink( ptH, ptS, VFirstOff, pPath2)) + return false ; + + // creo la curva formata da BiArco1 - Path - BiArco 2 + PtrOwner pCrvToAdd( CreateCurveComposite()) ; + if ( pCrvToAdd == nullptr + || ! pCrvToAdd->AddCurve( pPath1->Clone()) + || ! pCrvToAdd->AddCurve( pCrvPath->Clone()) + || ! pCrvToAdd->AddCurve( pPath2->Clone())) + return false ; + + if ( ! ManageSmoothAndAutoInters( pCrvToAdd, pCrvPath, pPath1, pPath2, VoffsCl)) + return false ; + + // curva finale + if ( pCrvH1 != nullptr && pCrvH1->GetFirstCurve() != nullptr) + if ( ! pCrvNewCurve->AddCurve( pCrvH1->Clone())) // aggiungo inizio + return false ; + + if ( ! pCrvNewCurve->AddCurve( pCrvToAdd->Clone())) { // aggiungo BiArco - Path - BiArco + Vector3d vtHS, vtHE ; + Point3d ptHS, ptHE ; + pCrvNewCurve->GetEndPoint( ptHS) ; + pCrvNewCurve->GetEndDir( vtHS) ; + pCrvToAdd->GetStartPoint( ptHE) ; + pCrvToAdd->GetStartDir( vtHE) ; + PtrOwner pCrvBiArcHelper( CreateCurveComposite()) ; + if ( ! CalcBoundedSmootedLink( ptHS, vtHS, ptHE, vtHE, 0.5, VFirstOff, pCrvBiArcHelper)) + if ( ! CalcBoundedLink( ptHS, ptHE, VFirstOff, pCrvBiArcHelper)) + return false ; + if ( ! pCrvNewCurve->AddCurve( Release( pCrvBiArcHelper)) + || ! pCrvNewCurve->AddCurve( pCrvToAdd->Clone())) + return false ; + } + if ( pCrvH2 != nullptr && pCrvH2->GetFirstCurve() != nullptr) { + if ( ! pCrvNewCurve->AddCurve( pCrvH2->Clone())) { // aggiungo fine + int nTry = 1; int nMaxTry = 10 ; bool bFound = false; + while ( nTry < nMaxTry && ! bFound) { + Vector3d vtHS, vtHE ; + Point3d ptHS, ptHE ; + pCrvNewCurve->GetEndPoint( ptHS) ; + pCrvNewCurve->GetEndDir( vtHS) ; + pCrvH2->GetStartPoint( ptHE) ; + pCrvH2->GetStartDir( vtHE) ; + PtrOwner pCrvBiArcHelper( CreateCurveComposite()) ; + if ( ! CalcBoundedSmootedLink( ptHS, vtHS, ptHE, vtHE, 0.5, VFirstOff, pCrvBiArcHelper)) + if ( ! CalcBoundedLink( ptHS, ptHE, VFirstOff, pCrvBiArcHelper) ) + return false ; + if ( ! pCrvNewCurve->AddCurve( pCrvBiArcHelper->Clone()) + || ! pCrvNewCurve->AddCurve( pCrvH2->Clone())) { + nTry++; + } + else { + bFound = true ; + } + } + if ( ! bFound) + return false ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pCrvPath, ICurveComposite* pPath1, ICurveComposite* pPath2, ICRVCOMPOPOVECTOR& vOffsCL) { + + // controllo parametri + if ( pCrv == nullptr) + return false ; + + // check AutoIntersezioni... + SelfIntersCurve SICrv( *pCrv) ; + if ( SICrv.GetCrossOrOverlapIntersCount() > 0) { // se ci sono autointersezioni + + Vector3d vTanE ; Point3d ptHS ; + pCrvPath->GetEndDir( vTanE) ; + pCrvPath->GetEndPoint( ptHS) ; + + bool bFound = false ; + int nIter = -45 ; + + while ( ! bFound && nIter < 45) { + vTanE.Rotate( Z_AX, 90 - nIter) ; // vettore perpendicolare + PtrOwner pLine( CreateCurveLine()) ; + pLine->SetPVL( ptHS, vTanE, m_TParams.m_dDiam / 3 - 5 * EPS_SMALL) ; // segmento uscente + + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pLine, *pCrv) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ccClass.size() > 1) // se intersezione con parte precedente inverto la direzione + pLine->SetPVL( ptHS, - vTanE, m_TParams.m_dDiam / 3 - 5 * EPS_SMALL) ; + + if ( pLine == nullptr) + break ; + + // punto finale segmento uscente + Point3d ptEndLine ; + pLine->GetEndPoint( ptEndLine) ; + + + Point3d ptNear ; + double dUS, dUE ; + pPath2->GetDomain( dUS, dUE) ; + PtrOwner pCrvHelper( GetCurve( pPath2->CopyParamRange( dUS, dUE - 0.5))); + pCrvHelper->GetEndPoint( ptNear) ; + PtrOwner pLine1( GetLinePointTgCurve( ptEndLine, *pPath2, ptNear)) ; // segmento tangente + + if ( pLine1 == nullptr) + break ; + + // creo la nuova curva formata da BiArco 1 - Path - Segmento uscente - Segmento tangente - parte restante di Biarco 2 + Point3d ptELine1 ; + pLine1->GetEndPoint( ptELine1) ; + pPath2->GetParamAtPoint( ptELine1, dUS) ; + PtrOwner pNewPath2(( ICurveComposite*) GetCurve( pPath2->CopyParamRange( dUS, dUE))) ; + + + // creo la curva formata dai due segmenti ma smussati tra loro... + PtrOwner pCrvTwoSeg( CreateCurveComposite()) ; + if ( ! pCrvTwoSeg->AddCurve( pCrvPath->Clone()) + || ! pCrvTwoSeg->AddCurve( pLine->Clone()) + || ! pCrvTwoSeg->AddCurve( pLine1->Clone())) + return false ; + + ModifyCurveToSmooted( pCrvTwoSeg, 0.2, 0.2) ; + + PtrOwner ptNewCrv( CreateCurveComposite()); + if ( ptNewCrv->AddCurve( pPath1->Clone()) + && ptNewCrv->AddCurve( pCrvTwoSeg->Clone()) + && ptNewCrv->AddCurve( pNewPath2->Clone())) { + + SelfIntersCurve SICrvLoop( *ptNewCrv) ; + + if ( SICrvLoop.GetCrossOrOverlapIntersCount() == 0) { + pCrv->Clear() ; + pCrv->AddCurve( Release( ptNewCrv)) ; + bFound = true ; + } + else { // se trovo autointersezioni, ripeto cambiando l'angolo del segmento uscente + nIter++ ; + } + } + else + break ; + } + } + + // smusso questa curva sulle varie curve di offsets + Point3d ptCheck1, ptCheck2 ; + PtrOwner pCrvH( pCrv->Clone()) ; // copia della curva + + if ( ! CutCurveByOffsets( pCrv, vOffsCL)) { // taglio la curva sugli Offsets + pCrv->Clear() ; + pCrv->AddCurve( Release( pCrvH)) ; + } + else { // controllo che i punti iniziali coincidano + pCrv->GetStartPoint( ptCheck1) ; + pCrvH->GetStartPoint( ptCheck2) ; + if ( ! AreSamePointApprox( ptCheck1, ptCheck2)) { // se i punti iniziali della curva prima e dopo lo smusso non coincidono ... + pCrv->Clear() ; + pCrv->AddCurve ( Release( pCrvH)) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +RemoveFirstLoopFromSrfFlatRgn( ISurfFlatRegion* pSrfOrig) { + + if ( pSrfOrig == nullptr) + return true ; + + PtrOwner pSrfRes( CreateSurfFlatRegion()) ; + if ( pSrfRes == nullptr) + return false ; + + for ( int c = 1; c < pSrfOrig->GetChunkCount(); c++) { + PtrOwner pSrfHelp( CreateSurfFlatRegion()) ; + if ( pSrfHelp == nullptr) + return false ; + PtrOwner pCrvMiniChunkBorder( GetCurve( pSrfOrig->GetLoop(c, 0)->Clone())) ; + pSrfHelp->AddExtLoop( pCrvMiniChunkBorder->Clone()) ; + if ( c == 1) + pSrfRes.Set( pSrfHelp->Clone()) ; + else + pSrfRes->Add(*( pSrfHelp->Clone())) ; + } + + pSrfOrig->Clear() ; + pSrfOrig->CopyFrom( Release( pSrfRes)) ; + + return true ; +} + + + +//---------------------------------------------------------------------------- +bool +Pocketing::RemoveExtraPartByMedialAxis( ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECTOR& vOffsFirstCurve, int& nOptFlag, Point3d& ptCentroid, ICurveComposite* pCrvPath) { + + nOptFlag = 2 ; + bool bForceCentroid = false ; + + if ( pChunkToCut == nullptr) + return false ; + + ICurveComposite* pCrvStepByStepPath( CreateCurveComposite()) ; // curva che l'utensile dovrà seguire per svuotare la regione + ICurveArc* pCrvToolShape( CreateCurveArc()) ; // superifice di ingobro del tool + if ( pCrvToolShape == nullptr || pCrvStepByStepPath == nullptr) + return false ; + + // copie del chunk che devo svuotare + ISurfFlatRegion* pSrfChunkToCutClone( pChunkToCut->Clone()) ; + double dArea = INFINITO ; + ICRVCOMPOPVECTOR vCrvCoMedAxi ; // vettore dei medial Axis + PNTVECTOR vPtCentroid ; // vettore di centroidi + int nIter = 0 ; // numero di iterazioni + + while ( pSrfChunkToCutClone != nullptr && pSrfChunkToCutClone->GetChunkCount() != 0 && pSrfChunkToCutClone->GetArea( dArea) && dArea > 10 * EPS_SMALL) { // finchè restano parti non svuotate la cui area totale è suffcientemente grande... + + if ( nIter > 25) + return false ; + + nIter++ ; + ISurfFlatRegion* pSrfBiggerChunk( CreateSurfFlatRegion()) ; + if ( pSrfBiggerChunk == nullptr || ! pSrfBiggerChunk->AddExtLoop( pSrfChunkToCutClone->GetLoop(0, 0))) + return false ; + + double dAreaExt ; + if ( pSrfBiggerChunk->GetArea( dAreaExt) && dAreaExt < 10 * EPS_SMALL) // se l'area del chunk è piccola... rimuovo il chunk dalla superficie da svuotare + { + if ( ! RemoveFirstLoopFromSrfFlatRgn( pSrfChunkToCutClone)) + return false ; + continue ; + } + + // prendo il centroide del chunk + Point3d ptC ; + if ( ! pSrfBiggerChunk->GetCentroid( ptC)) + return false ; + + // creo la superificie che racchiude il mio tool + pCrvToolShape->SetXY( ptC, m_TParams.m_dDiam / 2 + 5 * EPS_SMALL) ; + ISurfFlatRegion* pSrfTool( CreateSurfFlatRegion()) ; + if ( pSrfTool == nullptr || ! pSrfTool->AddExtLoop( pCrvToolShape)) + return false ; + + ISurfFlatRegion* pSrfChunkToCutCloneTest( pSrfBiggerChunk->Clone()) ; + if ( bForceCentroid || pSrfChunkToCutCloneTest->Subtract( *pSrfTool) && ! pSrfChunkToCutCloneTest->GetArea( dArea) && dArea < 10 * EPS_SMALL) { + if ( nIter == 1) { // se alla prima iterazione svuoto tutto con il centroide ... + nOptFlag = 1 ; + ptCentroid = ptC; + return true ; + } + else { // ... altrimenti devo prendere il centroide (che poi unirò al medil axis più vicino...) + for ( int cen = 0 ; cen < vPtCentroid.size(); cen++) { + if ( AreSamePointApprox( vPtCentroid[cen], ptC)) { + pSrfChunkToCutClone->Clear() ; + break ; + } + } + vPtCentroid.push_back( ptC) ; + if ( bForceCentroid) + pSrfChunkToCutClone->Subtract( *pSrfTool) ; + if ( ! pSrfChunkToCutClone->Subtract( *pSrfTool)) // o la pSrfBiggerChunk + return false ; + continue ; + } + } + bForceCentroid = false ; + + // 1) ricavo il bordo della regione + ICurve* pCrvBorder( pSrfBiggerChunk->GetLoop( 0, 0)) ; + if ( pCrvBorder == nullptr) + return false ; + + // 2) ricavo il medial Axis del bordo + PolyLine PlMedAx ; + if ( ! CurveSimpleMedialAxis( pCrvBorder, PlMedAx)) + return false ; + + ICurveComposite* pCrvMedAx( CreateCurveComposite()) ; + if ( pCrvMedAx == nullptr ) + return false; + + pCrvMedAx->Clear() ; + if ( ! pCrvMedAx->FromPolyLine( PlMedAx)) { // se non riesco ad aggiungere il medial axis non faccio nulla + //if ( ! RemoveFirstLoopFromSrfFlatRgn( pSrfChunkToCutClone)) + // return false ; + //continue ; + bForceCentroid = true ; + nIter --; + continue ; + } + + pCrvMedAx->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; + PolyArc PlMedAxArc ; + pCrvMedAx->ApproxWithArcsEx( 500 * EPS_SMALL, ANG_TOL_STD_DEG, LIN_FEA_STD, PlMedAxArc) ; + pCrvMedAx->Clear(); + pCrvMedAx->FromPolyArc( PlMedAxArc) ; + + // smusso la curva + ModifyCurveToSmooted( pCrvMedAx, 0.025, 0.025) ; + // la inserisco nel vettore + vCrvCoMedAxi.push_back( pCrvMedAx->Clone()) ; + + // 3) guardo quale regione svuoto con questa curva + ISurfFlatRegion* pSrfRemoved = GetSurfFlatRegionFromFatCurve( pCrvMedAx->Clone(), m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, false, false) ; + if ( pSrfRemoved == nullptr ) + break ; + + // 4) aggiorno la regione togliendo la parte percorsa dal tool + if ( ! pSrfChunkToCutClone->Subtract( *pSrfRemoved)) + break ; + if ( pSrfChunkToCutClone == nullptr) + break ; + + } + + // Se il vettore è dei medial axis è vuoto allora l'area originaria era più piccola di 10 * EPS_SMALL + if ( vCrvCoMedAxi.size() == 0 && vPtCentroid.size() == 0) { + nOptFlag = 0 ; return true ; } + + // ora collego la varie curve medial Axis trovate tra loro (ottenendo quindi una curva che svuota tutta la regione) + ICurveComposite* pCrvCoBackLink( CreateCurveComposite()) ; + if ( pCrvCoBackLink == nullptr) + return false ; + Point3d ptSOriginal, ptEOriginal ; + Vector3d vtSOriginal, vtEOriginal ; + + if ( ! vCrvCoMedAxi[0]->GetStartPoint( ptSOriginal) // parametri iniziali del primo e ultimo medial Axis trovato + || ! vCrvCoMedAxi[vCrvCoMedAxi.size() -1]->GetEndPoint( ptEOriginal) + || ! vCrvCoMedAxi[0]->GetStartDir( vtEOriginal) + || ! vCrvCoMedAxi[vCrvCoMedAxi.size() - 1]->GetEndDir( vtSOriginal)) + return false ; + + pCrvPath->AddCurve( vCrvCoMedAxi[0]->Clone()) ; // inserisco il primo medial Axis nel percorso finale + + for ( int i = 1; i < vCrvCoMedAxi.size(); i++) { // scorro i restanti + Point3d ptS, ptE ; Vector3d vtS, vtE ; // parametri iniziali del medialAxis iesimo e (i-1)esimo + if ( ! vCrvCoMedAxi[i]->GetStartPoint( ptE) + || ! vCrvCoMedAxi[i-1]->GetEndPoint( ptS) + || ! vCrvCoMedAxi[i]->GetStartDir( vtE) + || ! vCrvCoMedAxi[i-1]->GetEndDir( vtS)) + return false ; + + ICurveComposite* pCrvCoLink( CreateCurveComposite()) ; + if ( pCrvCoLink == nullptr) + return false ; + + if ( ! CalcBoundedSmootedLink( ptS, vtS, ptE, vtE, 0.5, vOffsFirstCurve, pCrvCoLink)) + if ( ! CalcBoundedLink( ptS, ptE, vOffsFirstCurve, pCrvCoLink)) + return false ; + + if ( ! pCrvPath->AddCurve( pCrvCoLink) || ! pCrvPath->AddCurve( vCrvCoMedAxi[i]->Clone())) + return false ; + + } + + if ( ! AreSamePointEpsilon( ptEOriginal, ptSOriginal, EPS_SMALL)) + if ( ! CalcBoundedSmootedLink( ptEOriginal, vtSOriginal, ptSOriginal, vtEOriginal, 0.5, vOffsFirstCurve, pCrvCoBackLink)) + if ( ! CalcBoundedLink( ptEOriginal, ptSOriginal, vOffsFirstCurve, pCrvCoBackLink)) + return false ; + + pCrvPath->AddCurve( pCrvCoBackLink->Clone()) ; // percorso con tutti i medial Axis Collegati + // questa curva è chiusa e ha come punto iniziale/finale il punto finale del link della la curva di offset più vicina a questa regione svuotata + // la tengo chiusa in modo da unire facilmente le circonferenze che collegheranno i vari centroidi a questa curva + + // se ho trovato dei centroidi li unisco nei punti più vicino a questo percorso + for ( int i = 0; i < vPtCentroid.size(); i++) { + + // 1) cerco il punto sulla curva più vicino al centroide i + Point3d ptClosestOnPath ; int nFlag ; + if ( ! DistPointCurve( vPtCentroid[i], *pCrvPath).GetMinDistPoint( EPS_SMALL, ptClosestOnPath, nFlag)) + return false ; + // 2) imposto come punto iniziale della curva chiusa quest'ultimo punto + double dU; + if ( ! pCrvPath->GetParamAtPoint( ptClosestOnPath, dU)) + return false ; + pCrvPath->ChangeStartPoint( dU) ; + + // 3) prendo il vettore tangente al percorso nel punto PtClosestOnPath + Vector3d vtTanCpt ; + double dParClosest ; + ICurveComposite* pCrvCoHelpToTan( pCrvPath->Clone()) ; + if ( ! pCrvCoHelpToTan->GetStartDir( vtTanCpt)) + return false ; + + // 4) collego i due punti (centroide e punto più vicino alla curva) + ICurveComposite * pCrvPath1(CreateCurveComposite()) ; + if ( pCrvPath1 == nullptr) + return false ; + + if( ! CalcBoundedSmootedLink( ptClosestOnPath, vtTanCpt, vPtCentroid[i], vtTanCpt, 0, vOffsFirstCurve, pCrvPath1)) + if( ! CalcBoundedLink( ptClosestOnPath, vPtCentroid[i], vOffsFirstCurve, pCrvPath1)) + return false ; + if ( ! pCrvPath->AddCurve( pCrvPath1)) { + return false ; + } + } + + // riprendo il punto iniziale + double dU ; + if ( ! pCrvPath->GetParamAtPoint( ptSOriginal, dU)) + return false ; + pCrvPath->ChangeStartPoint( dU) ; + + // spezzo la curva nel punto PTEORIGINAL + if ( ! pCrvPath->GetParamAtPoint( ptEOriginal, dU)) + return false ; + PtrOwner ptCrvPathWithCut( GetCurve( pCrvPath->CopyParamRange(0, dU))) ; + if ( ptCrvPathWithCut == nullptr) + return false ; + pCrvPath->Clear(); + pCrvPath->AddCurve( Release( ptCrvPathWithCut)) ; + + // la curva resitituita è una curva aperta che ha come primo punto il punto iniziale del primo medialAxis + // la curva restituita collega tutti i medial Axis tra di loro + // la curva restitutita collega tutti i centroidi con delle circonferenze + // la curva restituita ha come punto finale l'ultimo punto dell'ultimo medial Axis + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) +{ + pCrvLink->Clear() ; + + // recupero il vettore estrusione dal bordo esterno offsettato della superficie + Vector3d vtExtr ; + vOffIslands[0]->GetExtrusion( vtExtr) ; + + // determino il riferimento naturale della svuotatura (OCS con il vettore estrusione come asse Z) + Frame3d frLoc ; + frLoc.Set( ORIG, vtExtr) ; + + // non serve collegare (può capitare nel tagliare percorsi con isole complesse) + if ( AreSamePointApprox( ptStart, ptEnd)) + return true ; + + // porto la curva di contenimento in locale a questo riferimento + vector vOffsExtr ; + for ( int i = 0 ; i < vOffIslands.size(); i++) { + CurveLocal CrvOutLoc( vOffIslands[i], GLOB_FRM, frLoc) ; + vOffsExtr.push_back( CrvOutLoc) ; + } + + // creo la retta che li unisce + PtrOwner pLine( CreateCurveComposite()) ; + if ( ! pLine->AddPoint( ptStart) || ! pLine->AddLine( ptEnd)) + return false ; + pLine->SetExtrusion( vtExtr) ; + // la porto in locale al riferimento della svuotatura + CurveLocal LineLoc( pLine, GLOB_FRM, frLoc) ; // ... per le intersezioni + + // creo la nuova curva formata dai tratti di linee INTERNI alle isole e dai tratti sul bordo degli offset + PtrOwner pCompo( pLine->Clone()) ; + if ( IsNull( pCompo) ) + return false ; + if ( ! pCompo->LocToLoc( GLOB_FRM, frLoc) ) + return false; + + PtrOwner pCompoHelp( pLine->Clone()) ; + if ( IsNull( pCompoHelp)) + return false ; + if ( ! pCompoHelp->LocToLoc( GLOB_FRM, frLoc)) + return false ; + + // scorro il vettore degli indici degli offset delle isole intersecati + for ( int i = 0 ; i < vOffIslands.size(); i++ ) { + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCompo, *vOffIslands[i]) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ! pCompoHelp->Clear()) + return false ; + + for ( int j = 0 ; j < int( ccClass.size()) ; ++j ) { // per ogni intersezione j con l'offset dell'isola i + if ( ccClass[j].nClass == CRVC_OUT) { // se ho intersezione spezzo il segmento + Point3d ptS ; + pCompo->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; + double dOffS ; + vOffIslands[i]->GetParamAtPoint( ptS, dOffS) ; + Point3d ptE ; + pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; + double dOffE ; + vOffIslands[i]->GetParamAtPoint( ptE, dOffE) ; + // recupero i due possibili percorsi e uso il più corto + PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; + PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; + + if ( IsNull( pCrvA) || IsNull( pCrvB) ) + return false ; + double dLenA ; pCrvA->GetLength( dLenA) ; + double dLenB ; pCrvB->GetLength( dLenB) ; + if ( dLenA < dLenB ) { + pCompoHelp->AddCurve( Release( pCrvA)) ; + } + else { + pCrvB->Invert() ; + pCompoHelp->AddCurve( Release( pCrvB)) ; + } + } + else { // se non interseco + pCompoHelp->AddCurve( pCompo->Clone()->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + } + } + + pCompo->Clear() ; + pCompo->AddCurve( pCompoHelp->Clone()) ; + + } + + // riporto pCompo nel sistema di riferimento originale + if ( ! pCompo->LocToLoc( frLoc, GLOB_FRM)) + return false ; + pCrvLink->AddCurve( Release( pCompo)) ; + + return true ; + +} + +//------------------------------------------------------------------------------ +bool +Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, double dParMeet, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) { + + // creo il BiArc che unisce i due punti + double dAngStart, dAngEnd ; + vtStart.GetAngleXY( X_AX, dAngStart) ; + vtEnd.GetAngleXY( X_AX, dAngEnd) ; + PtrOwner pBiArcLink ; + if ( dParMeet != 0) + pBiArcLink.Set( GetBiArc( ptStart, -dAngStart, ptEnd, -dAngEnd, dParMeet)) ; + else { + ICurveArc* pCrvCir( CreateCurveArc()) ; + if ( pCrvCir == nullptr) + return false ; + pCrvCir->SetCPAN( Media( ptStart, ptEnd), ptStart, 360, 0, Z_AX) ; + pBiArcLink.Set( pCrvCir->Clone()) ; + pCrvLink->AddCurve( pBiArcLink->Clone()) ; + return true ; + } + if ( IsNull( pBiArcLink)) + return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ; + + // se BiArco troppo grande allora lo modifico + double dLenBiArc ; + pBiArcLink->GetLength( dLenBiArc) ; + if ( dLenBiArc > 200 * 1000 * EPS_SMALL) { + PtrOwner pCrvNewBiArcS( CreateCurveComposite()) ; + ModifyBiArc( pBiArcLink, 0.2, pCrvNewBiArcS) ; + pBiArcLink.Set( Release( pCrvNewBiArcS)) ; + } + + // creo la nuova curva formata inizialmente dai tratti di archi + PtrOwner pCompo( GetCurveComposite( pBiArcLink->Clone())) ; + if ( IsNull( pCompo)) + return false ; + + PtrOwner pCompoHelp( GetCurveComposite( pBiArcLink->Clone())) ; + if ( IsNull( pCompoHelp)) + return false ; + + // scorro tutte le curve per controllare le intersezioni ... + for ( int i = 0 ; i < vOffIslands.size(); i++) { + + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCompo, *vOffIslands[i]) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ! pCompoHelp->Clear()) + return false ; + + for ( int j = 0 ; j < int( ccClass.size()) ; ++j ) { // per ogni intersezione j con l'offset dell'isola i + + if ( ccClass[j].nClass == CRVC_OUT && ccClass.size() > 1) { // se ho intersezione spezzo il segmento + Point3d ptS ; + pCompo->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; + double dOffS ; + vOffIslands[i]->GetParamAtPoint( ptS, dOffS) ; + Point3d ptE ; + pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; + double dOffE ; + vOffIslands[i]->GetParamAtPoint( ptE, dOffE) ; + // recupero i due possibili percorsi e uso il più corto + PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; + PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; + + if (IsNull(pCrvA) || IsNull(pCrvB)) { + m_pGeomDB->AddGeoObj(GDB_ID_NULL, GDB_ID_ROOT, vOffIslands[i]->Clone()); + m_pGeomDB->AddGeoObj(GDB_ID_NULL, GDB_ID_ROOT, pCompo->Clone()); + IGeoPoint3d* PTS(CreateGeoPoint3d()); IGeoPoint3d* PTE(CreateGeoPoint3d()); + PTS->Set( ptS) ; PTE->Set( ptE) ; + m_pGeomDB->AddGeoObj(GDB_ID_NULL, GDB_ID_ROOT, PTS); + m_pGeomDB->AddGeoObj(GDB_ID_NULL, GDB_ID_ROOT, PTE); + return false; + } + + double dLenA ; pCrvA->GetLength( dLenA) ; + double dLenB ; pCrvB->GetLength( dLenB) ; + + if ( j != 0) { + if ( dLenA < dLenB) { + if ( ! pCompoHelp->AddCurve( Release( pCrvA))) + return false ; + } + else { + pCrvB->Invert() ; + if ( ! pCompoHelp->AddCurve( Release( pCrvB))) + return false ; + } + } + else { + pCrvB->Invert() ; + if ( ! pCompoHelp->AddCurve( Release( pCrvB))) + return false ; + } + } + else { // se non interseco + if ( ! pCompoHelp->AddCurve( pCompo->Clone()->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) + return false ; + } + } + + pCompo->Clear() ; + if ( ! pCompo->AddCurve( pCompoHelp->Clone())) + return false ; + + } + + // se il BiArco è troppo piccolo allora lo approssimo con un segmento + BBox3d bBox3 ; + if ( pCompo->GetLocalBBox( bBox3)) { + double dRadBB ; + if ( bBox3.GetRadius( dRadBB) && dRadBB < 500 * EPS_SMALL) { + if ( ! CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink)) + return false ; + return true ; + } + } + + ModifyCurveToSmooted( pCompo, 0.05, 0.05) ; + pCrvLink->AddCurve( Release( pCompo)) ; + + return true ; +} + +//----------------------------------------------------------------------------- +bool +Pocketing::ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) { + + if ( pBiArcLink == nullptr) + return false ; + if ( dToll > 0.99 || dToll < 0.01) + return false ; + pNewBiArc->Clear() ; + + double dUS, dUE ; + pBiArcLink->GetDomain( dUS, dUE) ; + + PtrOwner pArc1( GetCurve( pBiArcLink->CopyParamRange( dUS, (dUS + dUE) / 2))) ; + PtrOwner pArc2( GetCurve( pBiArcLink->CopyParamRange(( dUS + dUE ) / 2, dUE))) ; + if ( pArc1 == nullptr || pArc2 == nullptr) + return false ; + + double dUTollS, dUTollE ; + + // primo pezzo + pArc1->GetDomain( dUS, dUE) ; + PtrOwner pArc1A( GetCurve( pArc1->CopyParamRange( dUS, dUS + ( dUE - dUS ) * dToll))) ; // Arc1 + PtrOwner pArc1B( GetCurve( pArc1->CopyParamRange( dUE - ( dUE - dUS ) * dToll, dUE))) ; // Arc2 + Point3d pt1A, pt1B ; + pArc1A->GetEndPoint( pt1A) ; + pArc1B->GetStartPoint( pt1B) ; + PtrOwner pLine1( CreateCurveLine()) ; + pLine1->Set( pt1A, pt1B) ; // Linea + + // secondo pezzo + pArc2->GetDomain(dUS, dUE) ; + PtrOwner pArc2A( GetCurve( pArc2->CopyParamRange( dUS, dUS + ( dUE - dUS ) * dToll))) ; // Arc1 + PtrOwner pArc2B( GetCurve( pArc2->CopyParamRange( dUE - ( dUE - dUS ) * dToll, dUE))) ; // Arc2 + Point3d pt2A, pt2B ; + pArc2A->GetEndPoint( pt2A) ; + pArc2B->GetStartPoint( pt2B) ; + PtrOwner pLine2( CreateCurveLine()) ; + pLine2->Set( pt2A, pt2B) ; // Linea + + if ( ! pNewBiArc->AddCurve( Release( pArc1A)) + || ! pNewBiArc->AddCurve( Release( pLine1)) + || ! pNewBiArc->AddCurve( Release( pArc1B)) + || ! pNewBiArc->AddCurve( Release( pArc2A)) + || ! pNewBiArc->AddCurve( Release( pLine2)) + || ! pNewBiArc->AddCurve( Release( pArc2B))) + return false ; + + return true ; +} + +//------------------------------------------------------------------------------ +bool +Pocketing::CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) { + + // controllo parametri ingresso + if ( vOffs.size() == 0) + return true ; + + ICRVCOMPOPOVECTOR vOffOrig( vOffs.size()); + for ( int i = 0; i < vOffs.size(); i++ ) { + vOffOrig[i].Set(vOffs[i]->Clone()) ; + } + + Point3d ptStart ; + if ( ! pCurve->GetStartPoint( ptStart)) + return false ; + + PtrOwner pCompo(( ICurveComposite* ) pCurve->Clone()) ; + PtrOwner pCompoHelp(( ICurveComposite* ) pCurve->Clone()) ; + PtrOwner pOffCheck( CreateCurveComposite()) ; + if ( pCompoHelp == nullptr || pCompo == nullptr || pOffCheck == nullptr) + return false ; + + int nTypeOfCut = -1 ; + bool bAttention = false ; + + for ( int i = 0; i < vOffOrig.size() ; i++) { + + if ( vOffOrig[i]->IsPointOn( ptStart)) + pOffCheck.Set( vOffOrig[i]->Clone()) ; + + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCompo, *vOffOrig[i]) ; + intCC.GetCurveClassification( 0, 10 * EPS_SMALL, ccClass) ; + + if ( ! pCompoHelp->Clear()) + return false ; + + if ( ccClass.size() > 1) { + if ( ccClass[0].nClass == CRVC_IN) + nTypeOfCut = CRVC_OUT ; + else + nTypeOfCut = CRVC_IN ; + + for ( int j = 0 ; j < int( ccClass.size()) ; ++j) { + if ( ccClass[j].nClass == nTypeOfCut) { + + Point3d ptS ; pCompo->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; + double dOffS ; vOffOrig[i]->GetParamAtPoint( ptS, dOffS) ; + Point3d ptE ; pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; + double dOffE ; vOffOrig[i]->GetParamAtPoint( ptE, dOffE) ; + // recupero i due possibili percorsi e uso il più corto + PtrOwner pCrvA( GetCurve( vOffOrig[i]->CopyParamRange( dOffS, dOffE))) ; + PtrOwner pCrvB( GetCurve( vOffOrig[i]->CopyParamRange( dOffE, dOffS))) ; + + if ( IsNull( pCrvA) || IsNull( pCrvB)) + return false ; + + double dLenA ; pCrvA->GetLength( dLenA) ; + double dLenB ; pCrvB->GetLength( dLenB) ; + + if ( dLenA < dLenB) { + + CRVCVECTOR ccClassA ; + IntersCurveCurve intCCA( *pCrvA, *pOffCheck) ; + intCCA.GetCurveClassification( 0, 10 * EPS_SMALL, ccClassA) ; + + if ( ccClassA.size() > 0 && i == vOffOrig.size() - 1 && ccClassA[0].nClass == CRVC_ON_M) { + if ( ! pCompoHelp->AddCurve( pCompo->Clone()->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) + return false ; + continue ; + } + + if ( ! pCompoHelp->AddCurve( Release( pCrvA))) + return false ; + } + else { + pCrvB->Invert() ; + + CRVCVECTOR ccClassB ; + IntersCurveCurve intCCB( *pCrvB, *pOffCheck) ; + intCCB.GetCurveClassification( 0, 10 * EPS_SMALL, ccClassB) ; + + if ( ccClassB.size() > 0 && i == vOffOrig.size() - 1 && ccClassB[0].nClass == CRVC_ON_M) { + if ( ! pCompoHelp->AddCurve( pCompo->Clone()->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) + return false ; + continue ; + } + + if ( ! pCompoHelp->AddCurve( Release( pCrvB))) + return false ; + } + } + else { + if ( ! pCompoHelp->AddCurve( pCompo->Clone()->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) + return false ; + } + } + + pCompo->Clear() ; + pCompo->AddCurve( pCompoHelp->Clone()) ; + } + } + + pCurve->Clear() ; + pCurve->AddCurve( Release( pCompo)) ; + + return true ; } //------------------------------------------------------------------------------ @@ -4046,7 +6551,7 @@ Pocketing::CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vt CRVCVECTOR ccClass ; IntersCurveCurve intCC( *pBiArcLink, *pCrvBound) ; intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; - // se nessuno o un solo tratto e interno, il biarco è il collegamento + // se nessuno o un solo tratto e interno, il biarco è il collegamento if ( ccClass.empty() || ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN)) { pCrvLink->AddCurve( Release( pBiArcLink)) ; } @@ -4219,7 +6724,7 @@ Pocketing::CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtD double dMaxLarg = b3Dim.GetDimY() ; // calcolo percorso di svuotatura - // se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale + // se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale if ( vnProp[0] != 0 && vnProp[2] != 0 && vnProp[3] == 0 && vnProp[1] == 0 && dMaxLarg > m_TParams.m_dDiam + 10 * EPS_SMALL && max( dLen0, dLen2) < 2 * m_TParams.m_dDiam + EPS_SMALL) { if ( ! SpecialAdjustTrapezoidSpiralForAngles( pMCrv, pCrvPocket)) { @@ -4232,7 +6737,7 @@ Pocketing::CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtD if ( vnProp[0] != 0) dYCoord -= GetOffsR() ; if ( vnProp[0] != 0 && vnProp[2] != 0) - dYCoord = 0.5 * dPocketSize ; // se entrambi i lati paralleli sono aperti mi posiziono a metà della svuotatura + dYCoord = 0.5 * dPocketSize ; // se entrambi i lati paralleli sono aperti mi posiziono a metà della svuotatura double dXCoordStart, dXCoordEnd ; if ( ! CalcTrapezoidSpiralXCoord( pCrvPocket, true, dYCoord, dXCoordStart, dPocketSize)) @@ -4248,7 +6753,7 @@ Pocketing::CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtD Vector3d vtDir1, vtDir3 ; pCrvPocket->GetCurve( 1)->GetStartDir( vtDir1) ; pCrvPocket->GetCurve( 3)->GetStartDir( vtDir3) ; - // gestisco il caso speciale di un parallelogramma in cui anche l'altra dimensione della svuotatura è pari al diametro utensile + // gestisco il caso speciale di un parallelogramma in cui anche l'altra dimensione della svuotatura è pari al diametro utensile if ( AreOppositeVectorApprox( vtDir1, vtDir3)) { PtrOwner pLine1( GetCurveLine( pCrvPocket->GetCurve( 1)->Clone())) ; PtrOwner pLine3( GetCurveLine( pCrvPocket->GetCurve( 3)->Clone())) ; @@ -4303,7 +6808,7 @@ Pocketing::CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtD pMCrv->ToGlob( frLoc) ; if ( ! m_Params.m_bInvert) { pMCrv->Invert() ; - // inverto le proprietà in modo che nProp3 sia sempre legata al punto iniziale e nProp1 a quello finale + // inverto le proprietà in modo che nProp3 sia sempre legata al punto iniziale e nProp1 a quello finale swap( vnProp[1], vnProp[3]) ; } // segno i lati aperti come temp prop della curva @@ -4458,7 +6963,7 @@ Pocketing::AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveC pMCrv->TrimStartAtParam( dPar) ; if ( ptP1.y > dPocketSize) { - // se ptP1 è esterno alla svuotatura scambio i punti in modo da usare ptP2 per il biarco ( così da non farlo fuoriuscire troppo) + // se ptP1 è esterno alla svuotatura scambio i punti in modo da usare ptP2 per il biarco ( così da non farlo fuoriuscire troppo) swap( ptP1, ptP2) ; pCompo->Invert() ; } @@ -4487,9 +6992,9 @@ Pocketing::AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveC } } - // caso 2 : pLine è completamente sopra/sotto la linea di svuotatura + // caso 2 : pLine è completamente sopra/sotto la linea di svuotatura else { - // se è sopra modifiche per ricondurmi al caso in cui è sotto + // se è sopra modifiche per ricondurmi al caso in cui è sotto if ( ptP2.y > dYCoord) { pLine->Invert() ; swap( ptP1, ptP2) ; @@ -4516,7 +7021,7 @@ Pocketing::AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveC } } - // se il lato opposto a quello di riferimento è chiuso ha senso aggiungere solo se il punto è sotto la linea di svuotatura + // se il lato opposto a quello di riferimento è chiuso ha senso aggiungere solo se il punto è sotto la linea di svuotatura else { if ( ptP2.y < dYCoord) { pCompo->AddPoint( ptP2) ; @@ -4526,7 +7031,7 @@ Pocketing::AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveC } } - // setto temp prop per ricordare che è curva aggiuntiva per pulire angoli + // setto temp prop per ricordare che è curva aggiuntiva per pulire angoli for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) pCompo->SetCurveTempProp( i, 1) ; @@ -4593,7 +7098,7 @@ Pocketing::SpecialAdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const } } - // se non è stato possibile creare raccordo, unisco linearmente + // se non è stato possibile creare raccordo, unisco linearmente if ( ! bUseBiArcs) pMCrv->AddCurve( Release( pLineLink)) ; @@ -4617,7 +7122,7 @@ Pocketing::AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite* pCompo, ICurv for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) { int nProp ; if ( pCompo->GetCurveTempProp( i, nProp) && nProp == 0) { - // se non è lato aggiuntivo per la pulitura angoli recupero la sua direzione + // se non è lato aggiuntivo per la pulitura angoli recupero la sua direzione pCompo->GetCurve( i)->GetStartDir( vtMainDir) ; break ; } @@ -4679,7 +7184,7 @@ Pocketing::ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const V double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; - // tento con allungamento se lato inclinato è aperto oppure se sto considerando un lato aggiuntivo per pulire angoli + // tento con allungamento se lato inclinato è aperto oppure se sto considerando un lato aggiuntivo per pulire angoli if ( bEdgeOpen || nExtraEdge == 1) { Vector3d vtDirP = ( bLeadIn ? -vtDir : vtDir) ; @@ -4715,7 +7220,7 @@ Pocketing::ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const V Point3d ptTest = ptP + vtDirP * ( dDist + ( m_TParams.m_dDiam / 2 + dSafeZ) * dCorr) ; ptTest += - vtTool * dDepth ; double dTestElev ; - // se è fuori dal grezzo + // se è fuori dal grezzo if ( ! GetElevation( m_nPhase, ptTest, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElev) || dTestElev < EPS_SMALL) { Point3d ptNewStart = ptP + vtDirP * ( dDist + ( m_TParams.m_dDiam / 2 + dSafeZ) * dCorr) ; pCompo->AddLine( ptNewStart, ! bLeadIn) ; @@ -4724,7 +7229,7 @@ Pocketing::ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const V } } - // tento con attacco ruotato di 90° se non sto considerando un tratto aggiuntivo per pulire angoli + // tento con attacco ruotato di 90° se non sto considerando un tratto aggiuntivo per pulire angoli if ( bBaseOpen && ! bIsOutsideRaw && nExtraEdge == 0) { Vector3d vtDirO = vtDir ; @@ -4740,7 +7245,7 @@ Pocketing::ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const V Point3d ptTestO = ptP + vtDirO * ( dDist + m_TParams.m_dDiam / 2 + dSafeZ) ; ptTestO += - vtTool * dDepth ; double dTestElevO ; - // se è fuori dal grezzo uso inizio ruotato + // se è fuori dal grezzo uso inizio ruotato if ( ! GetElevation( m_nPhase, ptTestO, vtTool, m_TParams.m_dDiam / 2, vtTool, dTestElevO) || dTestElevO < EPS_SMALL) { Point3d ptNewStart = ptP + vtDirO * ( dDist + m_TParams.m_dDiam / 2 + dSafeZ) ; pCompo->AddLine( ptNewStart, ! bLeadIn) ; @@ -4769,11 +7274,11 @@ Pocketing::ComputePolishingPath( ICurveComposite* pMCrv, ICurveComposite* pRCrv, if ( ! pMCrv->GetCurveTempProp( i, nProp)) return false ; - // se è un tratto di collegamento ho concluso percorso su cui aggiungere epicicli + // se è un tratto di collegamento ho concluso percorso su cui aggiungere epicicli if ( nProp == LINK_CURVE_PROP) { if ( pCompo->IsValid()) { PtrOwner pCrvEp( CreateCurveComposite()) ; - // la curva di bound è l'offset che calcolo in AddEpicycles per la prima curva compo trovata in pMCrv + // la curva di bound è l'offset che calcolo in AddEpicycles per la prima curva compo trovata in pMCrv bool bAddEp = ( ! pCrvBound->IsValid()) ? AddEpicycles( pCompo, pCrvEp, pCrvBound) : AddEpicycles( pCompo, pCrvEp) ; if ( ! bAddEp) return false ; @@ -4781,7 +7286,7 @@ Pocketing::ComputePolishingPath( ICurveComposite* pMCrv, ICurveComposite* pRCrv, pCompo.Set( CreateCurveComposite()) ; } } - // se non è tratto di collegamento lo aggiungo alla curva + // se non è tratto di collegamento lo aggiungo alla curva else { if ( ! pCompo->AddCurve( pMCrv->GetCurve(i)->Clone())) return false ; @@ -4953,7 +7458,7 @@ Pocketing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafe // se con aggregato da sotto o equivalente (rinvio a 90 gradi su testa 5 assi) bool bBottomOutStart = false ; if ( m_bAggrBottom) { - // distanza dal bordo del pezzo (se negativa il punto è fuori dal grezzo) + // distanza dal bordo del pezzo (se negativa il punto è fuori dal grezzo) double dDistBottom ; if ( ! GetDistanceFromRawSide( m_nPhase, ptP, m_vtAggrBottom, dDistBottom)) dDistBottom = 0 ; @@ -4983,7 +7488,7 @@ Pocketing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafe SetFlag( 0) ; } } - // se sopra attacco c'è spazio per sicurezza o approccio + // se sopra attacco c'è spazio per sicurezza o approccio double dSafeDist = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ; if ( ! bBottomOutStart && dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { // se distanza di sicurezza minore di distanza di inizio @@ -5029,7 +7534,7 @@ bool Pocketing::AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr, bool bOutStart) { - // se sopra attacco c'è spazio per approccio + // se sopra attacco c'è spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 1b -> punto appena sopra inizio Point3d ptP1b = ptP + vtTool * ( dElev + dAppr) ; @@ -5058,7 +7563,7 @@ bool Pocketing::AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr) { - // se sopra uscita c'è spazio per approccio + // se sopra uscita c'è spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 4 -> movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; @@ -5083,7 +7588,7 @@ Pocketing::AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ dDistBottom = 0 ; bBottomOutStart = ( dDistBottom < - 10 * EPS_SMALL) ; } - // se sopra uscita c'è spazio per sicurezza o approccio + // se sopra uscita c'è spazio per sicurezza o approccio double dSafeDist = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ; if ( ! bBottomOutStart && dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { if ( dSafeDist < dAppr + 10 * EPS_SMALL) { @@ -5149,7 +7654,7 @@ Pocketing::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, con case POCKET_LI_GLIDE : { double dLen, dU ; - if ( ! pRCrv->GetLength( dLen) || ! pRCrv->GetParamAtLength( dLen - m_Params.m_dLiTang, dU) || + if ( ! pRCrv->GetLength( dLen) || ! pRCrv->GetParamAtLength( dLen - m_Params.m_dLiTang, dU) || ! pRCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP1)) { if ( ! pRCrv->GetStartPoint( ptP1)) return false ; @@ -5165,7 +7670,7 @@ Pocketing::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, con //---------------------------------------------------------------------------- bool Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - const ICurveComposite* pCompo, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, + ISurfFlatRegion* pSrfChunk, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, bool bNoneForced, bool bSkipControl) { // Assegno il tipo @@ -5185,7 +7690,7 @@ Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3 double dDeltaN = ( ptStart - ptP1) * vtN ; double dAngCen = ceil( - dDeltaN / ( m_Params.m_dLiElev + 20 * EPS_SMALL)) * ( bAtLeft ? ANG_FULL : - ANG_FULL) ; // verifico se fattibile - if ( bSkipControl || VerifyLeadInHelix( pCompo, ptCen, dRad)) { + if ( bSkipControl || VerifyLeadInHelix( pSrfChunk, ptCen, dRad)) { // creo l'elica PtrOwner pArc( CreateCurveArc()) ; if ( IsNull( pArc) || ! pArc->Set( ptCen, vtN, dRad, - vtCen, dAngCen, dDeltaN)) @@ -5215,7 +7720,7 @@ Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3 Point3d ptPa = ptP1 + vtStart * 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam) ; Point3d ptPb = ptP1 - vtStart * 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam) ; // verifico se fattibile - if ( bSkipControl || VerifyLeadInZigZag( pCompo, ptPa, ptPb)) { + if ( bSkipControl || VerifyLeadInZigZag( pSrfChunk, ptPa, ptPb)) { for ( int i = 1 ; i <= nStep ; ++ i) { if ( AddLinearMove( ptPa - vtN * ( i - 0.75) * dStep, MCH_CL_LEADIN) == GDB_ID_NULL) return false ; @@ -5237,7 +7742,7 @@ Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3 if ( pRCrv->GetLength( dLen) && pRCrv->GetParamAtLength( dLen - m_Params.m_dLiTang, dU)) { double dParS, dParE ; pRCrv->GetDomain( dParS, dParE) ; - if ( ! pCrv.Set( CreateCurveComposite()) || ! pCrv->AddCurve( pRCrv->CopyParamRange( dU, dParE))) + if ( ! pCrv.Set( CreateCurveComposite()) || ! pCrv->AddCurve( pRCrv->CopyParamRange( dU, dParE))) return false ; } else { @@ -5370,7 +7875,7 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi } pMyCrv = pCompo->GetNextCurve() ; } - // richiedo lunghezza superiore a diametro utensile più doppio offset radiale + // richiedo lunghezza superiore a diametro utensile più doppio offset radiale double dRefLen = ( bAllOpen ? 0 : m_TParams.m_dDiam + 2 * GetOffsR() - EPS_SMALL) ; double dMaxLen = dRefLen ; // ciclo sulle singole curve @@ -5391,7 +7896,7 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi pNextCrv->GetLength( dLenNext) ; // verifico la curva corrente if ( pCrv->GetTempProp() == 1) { - // contributo dalle entità adiacenti (se non tutte aperte) + // contributo dalle entità adiacenti (se non tutte aperte) double dLenAgg = 0 ; if ( ! bAllOpen) { if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == 1) { @@ -5405,34 +7910,34 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi dLenAgg += max( 0.4, vtEnd * vtNextStart) * dLenNext ; } } - // entità corrente + // entità corrente double dLen = 0 ; - if ( pCrv->GetLength( dLen)) { - const double LEN_TOL = 1 ; - // se di lunghezza praticamente uguale - if ( bFound && dLen + dLenAgg > dRefLen && abs( dLen + dLenAgg - dMaxLen) < LEN_TOL) { - Point3d ptTest ; - pCrv->GetMidPoint( ptTest) ; - if ( ( m_bAboveHead && ptTest.z > ptMid.z + 100 * EPS_SMALL) || - ( ! m_bAboveHead && ptTest.z < ptMid.z - 100 * EPS_SMALL) || - ( abs( ptTest.z - ptMid.z) < 100 * EPS_SMALL && ptTest.y < ptMid.y - 100 * EPS_SMALL)) { - dMaxLen = max( dMaxLen, dLen + dLenAgg) ; - ptMid = ptTest ; - // vettore ortogonale verso l'esterno (ruotato -90deg attorno a estrusione) - pCrv->GetMidDir( vtMidOrt) ; - vtMidOrt.Rotate( vtExtr, 0, -1) ; + if (pCrv->GetLength(dLen)) { + const double LEN_TOL = 1; + // se di lunghezza praticamente uguale + if (bFound && dLen + dLenAgg > dRefLen && abs(dLen + dLenAgg - dMaxLen) < LEN_TOL) { + Point3d ptTest; + pCrv->GetMidPoint(ptTest); + if ((m_bAboveHead && ptTest.z > ptMid.z + 100 * EPS_SMALL) || + (!m_bAboveHead && ptTest.z < ptMid.z - 100 * EPS_SMALL) || + (abs(ptTest.z - ptMid.z) < 100 * EPS_SMALL && ptTest.y < ptMid.y - 100 * EPS_SMALL)) { + dMaxLen = max(dMaxLen, dLen + dLenAgg); + ptMid = ptTest; + // vettore ortogonale verso l'esterno (ruotato -90deg attorno a estrusione) + pCrv->GetMidDir(vtMidOrt); + vtMidOrt.Rotate(vtExtr, 0, -1); } } - // se più lunga - else if ( dLen + dLenAgg > dMaxLen) { - dMaxLen = dLen + dLenAgg ; - pCrv->GetMidPoint( ptMid) ; - // vettore ortogonale verso l'esterno (ruotato -90deg attorno a estrusione) - pCrv->GetMidDir( vtMidOrt) ; - vtMidOrt.Rotate( vtExtr, 0, -1) ; - bFound = true ; + // se pi� lunga + else if (dLen + dLenAgg > dMaxLen) { + dMaxLen = dLen + dLenAgg; + pCrv->GetMidPoint(ptMid); + // vettore ortogonale verso l'esterno (ruotato -90deg attorno a estrusione) + pCrv->GetMidDir(vtMidOrt); + vtMidOrt.Rotate(vtExtr, 0, -1); + bFound = true; } - dLenPrev = dLen ; + dLenPrev = dLen; } } else @@ -5455,7 +7960,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCompo) Frame3d frPocket ; Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; frPocket.Set( ptStart, vtExtr) ; - // sposto l'inizio a metà del tratto più lungo + // sposto l'inizio a metà del tratto più lungo AdjustContourStart( pCompo) ; // raggio di riferimento per offset double dRad = 0.5 * m_TParams.m_dDiam + GetOffsR() ; @@ -5574,7 +8079,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCompo) bool Pocketing::AdjustContourStart( ICurveComposite* pCompo) { - // cerco il tratto lineare più lungo che non sia aperto + // cerco il tratto lineare più lungo che non sia aperto int i = 0 ; int nMax = - 1 ; double dLenMax = 0 ; @@ -5588,7 +8093,7 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo) ++ i ; pCrv = pCompo->GetNextCurve() ; } - // se non trovato o troppo corto, cerco il tratto generico più lungo + // se non trovato o troppo corto, cerco il tratto generico più lungo if ( nMax < 0 || dLenMax < 2 * m_TParams.m_dDiam) { i = 0 ; pCrv = pCompo->GetFirstCurve() ; @@ -5612,28 +8117,70 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo) //---------------------------------------------------------------------------- bool -Pocketing::VerifyLeadInHelix( const ICurveComposite* pCompo, const Point3d& ptCen, double dRad) const +Pocketing::VerifyLeadInHelix( ISurfFlatRegion* pSrfChunk, const Point3d& ptCen, double dRad) const { + // controllo della superifice + if ( pSrfChunk == nullptr) + return false ; + + // vettore di tutte le curve della superficie + ICRVCOMPOPOVECTOR vCrv ; + for( int c = 0 ; c < pSrfChunk->GetChunkCount() ; c++) { + for ( int l = 0 ; l < pSrfChunk->GetLoopCount( c) ; l++) { + vCrv.emplace_back( CloneCurveComposite( pSrfChunk->GetLoop( c, l))) ; + } + } + if ( vCrv.size() == 0) + return false ; + + // estraggo il bordo esterno + PtrOwner pCompo( CloneCurveComposite( vCrv[0])) ; + if ( IsNull( pCompo)) + return false ; + // recupero il piano della curva di contorno Point3d ptStart ; Vector3d vtN ; - if ( pCompo == nullptr || ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) + if ( ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) return false ; // porto il centro sullo stesso piano del contorno Point3d ptCenL = ptCen - ( ptCen - ptStart) * vtN * vtN ; // calcolo la distanza del centro dal contorno double dMinDist ; - return ( DistPointCurve( ptCenL, *pCompo).GetDist( dMinDist) && dMinDist > dRad + 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL) ; + bool bOk = DistPointCurve( ptCenL, *pCompo).GetDist( dMinDist) && dMinDist > dRad + 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL ; + // se la curva per l'attacco è valida per tale, controllo che l'elica non intersechi eventuali isole + for ( int i = 1 ; bOk && i < vCrv.size() ; i++) + bOk = DistPointCurve( ptCenL, *vCrv[i]).GetDist( dMinDist) && dMinDist > dRad + 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL ; + return bOk ; } //---------------------------------------------------------------------------- bool -Pocketing::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptPa, const Point3d& ptPb) const +Pocketing::VerifyLeadInZigZag( ISurfFlatRegion* pSrfChunk, const Point3d& ptPa, const Point3d& ptPb) const { + // controllo della superificie + if ( pSrfChunk == nullptr) + return false ; + + // vettore di tutte le curve della superficie + ICRVCOMPOPOVECTOR vCrv ; + for ( int c = 0 ; c < pSrfChunk->GetChunkCount() ; c++) { + for ( int l = 0 ; l < pSrfChunk->GetLoopCount( c) ; l++) { + vCrv.emplace_back( CloneCurveComposite( pSrfChunk->GetLoop( c, l))) ; + } + } + if ( vCrv.size() == 0) + return false ; + + // estraggo il bordo esterno + PtrOwner pCompo( CloneCurveComposite( vCrv[0])) ; + if ( IsNull( pCompo)) + return false ; + // recupero il piano della curva di contorno Point3d ptStart ; Vector3d vtN ; - if ( pCompo == nullptr || ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) + if ( ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) return false ; // porto i punti sullo stesso piano del contorno Point3d ptPaL = ptPa - ( ptPa - ptStart) * vtN * vtN ; @@ -5645,7 +8192,17 @@ Pocketing::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptP double dMinDistPb ; if ( ! DistPointCurve( ptPbL, *pCompo).GetDist( dMinDistPb)) return false ; - return ( dMinDistPa > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL && dMinDistPb > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL) ; + bool bOk = dMinDistPa > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL && dMinDistPb > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL ; + // se la curva per l'attacco è valida per tale, controllo che lo ZigZag non intersechi eventuali isole + for ( int i = 1 ; bOk && i < vCrv.size() ; i++) { + if ( ! DistPointCurve( ptPaL, *vCrv[i]).GetDist( dMinDistPa)) + return false ; + if ( ! DistPointCurve( ptPbL, *vCrv[i]).GetDist( dMinDistPb)) + return false ; + bOk = dMinDistPa > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL && dMinDistPb > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL ; + } + return bOk ; + } //---------------------------------------------------------------------------- diff --git a/Pocketing.h b/Pocketing.h index 7afb60c..27d1dd3 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -19,6 +19,7 @@ #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkSurfFlatRegion.h" //---------------------------------------------------------------------------- class Pocketing : public Machining @@ -73,13 +74,18 @@ class Pocketing : public Machining bool Chain( int nGrpDestId) ; bool ProcessPath( int nPathId, int nPvId, int nClId) ; bool CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double& dElev) const ; - bool VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) ; - bool GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) ; - bool AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) ; - bool CalcZigZag( const ICurveComposite* pOffs, ICRVCOMPOPOVECTOR& vpCrvs) ; - bool OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, double dSafeZ, - Frame3d& frPocket, bool& bOptimizedZigZag, ICRVCOMPOPOVECTOR& vpCrvs) ; + bool VerifyPathFromBottom( const ISurfFlatRegion* pSrf, const Vector3d& vtTool) ; + bool GeneratePocketingPv( int nPathId, const ISurfFlatRegion* pSrfPock) ; + + bool ModifyCurveToSmooted( ICurveComposite* pCrvOffset, double dRightPer, double dleftPer) ; + + // ===== ZigZag ===== + bool AddZigZag( const ISurfFlatRegion* pSrfPock, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dOkStep, + bool bSplitArcs, int nPathId) ; + bool CalcZigZag( const ISurfFlatRegion* pSrfZigZag, ICRVCOMPOPOVECTOR& vpCrvs) ; + bool CalcBoundedZigZagLink( ICurveLine* pCrv1, ICurveLine* pCrv2, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink, int nIndexCut = 3) ; + bool OptimizedZigZag( ISurfFlatRegion* pSrf, const Vector3d & vtTool, double dDepth, double dSafeZ, Frame3d & frPocket, bool & bOptimizedZigZag, + ICRVCOMPOPOVECTOR & vpCrvs) ; bool ZigZagOptimizedNoClosedEdges( ICurveComposite* pCrvPocket, bool& bOptimizedZigZag, Vector3d& vtDir) ; bool ZigZagOptimizedOneClosedEdge( ICurveComposite* pCrvPocket, int nClosedId, bool& bOptimizedZigZag, Vector3d& vtDir) ; bool ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INTVECTOR& vnClosedIds, bool& bOptimizedZigZag, @@ -89,17 +95,38 @@ class Pocketing : public Machining bool ZigZagOptimizedComputeOffset( ICurveComposite* pCrvPocket, const Vector3d& vtMainDir, int nOffsettedEdgesOnY, const INTVECTOR& vnClosedIds) ; bool CutCurveWithLine( ICurveComposite* pCrvA, const ICurveLine* pCrvB) ; - bool AddOneWay( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs) ; - bool AddSpiralIn( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, bool bMidOpen, - const Point3d& ptMidOpen, const Vector3d& vtMidOut, int nPathId) ; - bool AddSpiralOut( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) ; - bool CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, - ICurveComposite* pMCrv, ICurveComposite* pRCrv, int nPathId, bool& bOptimizedTrap) ; - bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICurve* pCrvBound, - ICurveComposite* pCrvLink) ; + bool GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICURVEPOVECTOR& vLinks, ISurfFlatRegion* pSrfToCut) ; + // ================== + + // ==== OneWay ====== + bool AddOneWay( const ISurfFlatRegion* pSrfPock, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dOkStep, bool bSplitArcs) ; + // ================== + + // ==== SpiralIn/Out ==== + bool AddSpiralIn( const ISurfFlatRegion* pSrfPock, const PNTVECTOR vPtStart, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, + double dElev, double dOkStep, bool bSplitArcs, BOOLVECTOR vbMidOpen, PNTVECTOR vPtMidOpen, VCT3DVECTOR vVtMidOut, int nPathId) ; + bool AddSpiralOut( const ISurfFlatRegion* pSrfpock, const PNTVECTOR vPtStart, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, + double dOkStep, bool bSplitArcs, int nPathId) ; + bool CalcSpiral( const ISurfFlatRegion* pSrfChunk, int nReg, Point3d ptStart, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv, int nPathId, + bool& bOptimizedTrap) ; + bool RemoveExtraParts( ISurfFlatRegion* pSrfToCut, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffsClosedCurves, ICRVCOMPOPOVECTOR& vOffsFirstCurve, + ICURVEPOVECTOR& vLinks) ; + bool RemoveExtraPartByMedialAxis( ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECTOR& vOffsFirstCurve, int& nOptFlag, Point3d& ptCentroid, + ICurveComposite* pCrvPath) ; + bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ; + bool CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, double dParMeet, + ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ; + bool ModifyBiArc( ICurve* pCrvBiArc, double dCutToll, ICurveComposite* pNewCrv) ; + bool CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) ; + bool GetCurveWeightInfo( ICurveComposite* pCrvCompo, double dMaxLen, double& dToTRot, int& nSmallArcs, int& nSmallLines) ; + bool ChoosePath( ICurveComposite* pCrv1, ICurveComposite* pCrv2, int nP, double dPerP, double dMaxLen, int& nC) ; + bool CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffIslands, + ICurveComposite* pCrvLink, double dLenPercS = 0.01, double dLenPercE = 0.01, int nMaxIter = 2) ; + bool GetNewCurvetWithCentroid( ICurveComposite* pCrvH1, ICurveComposite* pCrvH2, Point3d& ptC, bool bCir, ICRVCOMPOPOVECTOR& VFirstOff, + ICurveComposite* pCrvNewCurve) ; + bool GetNewCurvetWithPath( ICurveComposite* pCrvH1, ICurveComposite* pCrvH2, ICurveComposite* pCrvPath, ICRVCOMPOPOVECTOR& VFirstOff, ICRVCOMPOPOVECTOR& VoffsCl, + ICurveComposite* pCrvNewCurve) ; + bool ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pCrvPath, ICurveComposite* pPath1, ICurveComposite* pPath2, ICRVCOMPOPOVECTOR& vOffsCL) ; bool CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, const ICurve* pCrvBound, ICurveComposite* pCrvLink) ; bool CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad, @@ -112,7 +139,10 @@ class Pocketing : public Machining bool SpecialAdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveComposite* pCrvPocket) ; bool AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite * pCompo, ICurveComposite * pRCrv, const Vector3d& vtTool, double dDepth, int& nOutsideRaw) ; - bool ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite * pCompo, const Vector3d& vtMainDir, bool bLeadIn, const Vector3d& vtTool, double dDepth, bool& bIsOutsideRaw) ; + bool ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite * pCompo, const Vector3d& vtMainDir, bool bLeadIn, const Vector3d& vtTool, double dDepth, + bool& bIsOutsideRaw) ; + // ================== + bool ComputePolishingPath( ICurveComposite* pMCrv, ICurveComposite* pRCrv, bool bSplitArcs) ; bool AddEpicycles( ICurveComposite * pCompo, ICurveComposite * pCrv, ICurveComposite * pCrvBound = nullptr) ; bool AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, @@ -125,8 +155,8 @@ class Pocketing : public Machining double dElev, double dAppr) ; bool CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, const ICurveComposite* pRCrv, Point3d& ptP1) const ; - bool AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - const ICurveComposite* pCompo, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, + bool AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, + ISurfFlatRegion* pSrfChunk, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, bool bNoneForced = false, bool bSkipControl = false) ; bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, const ICurveComposite* pRCrv, bool bSplitArcs, Point3d& ptP1, double& dElev, bool bNoneForced = false) ; @@ -134,8 +164,8 @@ class Pocketing : public Machining bool GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMid, Vector3d& vtMidOut) ; bool AdjustContourWithOpenEdges( ICurveComposite* pCompo) ; bool AdjustContourStart( ICurveComposite* pCompo) ; - bool VerifyLeadInHelix( const ICurveComposite* pCompo, const Point3d& ptCen, double dRad) const ; - bool VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptPa, const Point3d& ptPb) const ; + bool VerifyLeadInHelix( ISurfFlatRegion* pSrfChunk, const Point3d& ptCen, double dRad) const ; + bool VerifyLeadInZigZag( ISurfFlatRegion* pSrfChunk, const Point3d& ptPa, const Point3d& ptPb) const ; bool CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist, Vector3d& vtNorm) ; private : @@ -187,4 +217,5 @@ class Pocketing : public Machining Vector3d m_vtAggrBottom ; // vettore direzione ausiliaria aggregato da sotto AggrBottom m_AggrBottom ; // dati eventuale aggregato da sotto bool m_bOpenOutRaw ; // flag forzatura lati aperti sempre fuori dal grezzo + POLYLINEVECTOR m_VplIsland ; // vettore che contiene le curve che descrivono le isole } ; \ No newline at end of file