diff --git a/PocketingNT.cpp b/PocketingNT.cpp index 62e9bd4..155a90c 100644 --- a/PocketingNT.cpp +++ b/PocketingNT.cpp @@ -29,6 +29,8 @@ #include "/EgtDev/Include/EGkCurveAux.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" +#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkCurveLocal.h" #include "/EgtDev/Include/EGkDistPointCurve.h" @@ -39,8 +41,13 @@ #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkCalcPocketing.h" +#include "/EgtDev/Include/EGkSurfLocal.h" +#include "/EgtDev/Include/EGkDistPointSurfFr.h" #include + + using namespace std ; //------------------------------ Errors -------------------------------------- @@ -86,6 +93,7 @@ using namespace std ; //---------------------------------------------------------------------------- static string KEY_OPEN = "OPEN" ; +static string KEY_THICK = "THICK" ; static int LINK_CURVE_PROP = -3 ; //---------------------------------------------------------------------------- @@ -595,7 +603,7 @@ PocketingNT::Preview( bool bRecalc) else m_pGeomDB->EmptyGroup( nPvId) ; - // lavoro ogni singola catena + // lavoro ogni singola regione piana int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; while ( nPathId != GDB_ID_NULL) { if ( ! ProcessPath( nPathId, nPvId, GDB_ID_NULL)) @@ -1166,7 +1174,7 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) for ( auto pCrv : lstPC) pCrv->ToGlob( frGlob) ; // ritorno - return true ; + return true ; } // se altrimenti superficie else if ( pGObj->GetType() == SRF_TRIMESH) { @@ -1181,51 +1189,53 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) pSurf->GetFacetLoops( nFacet, vPL) ; if ( vPL.empty()) return false ; - // creo la curva a partire da quello esterno - PtrOwner pCrvCompo( CreateCurveComposite()) ; - pCrvCompo->FromPolyLine( vPL[0]) ; - if ( ! pCrvCompo->IsValid()) - return false ; - // reset proprietà temporanee - ResetCurveAllTempProp( pCrvCompo) ; - // 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 - 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) + // per ogni loop recupero le curve composite + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + PtrOwner pCrvCompo( CreateCurveComposite()) ; + pCrvCompo->FromPolyLine( vPL[i]) ; + if ( ! pCrvCompo->IsValid()) + return false ; + // reset 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) ; } - // passo al successivo - ++ nInd ; - bFound = vPL[0].GetNextU( dPar, true) ; + // recupero la normale esterna della faccia + Vector3d vtN ; + if ( ! pSurf->GetFacetNormal( nFacet, vtN)) + return false ; + // 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, V_NULL, 0) ; + // la restituisco + lstPC.emplace_back( Release( pCrvCompo)) ; } - // recupero la normale esterna della faccia - Vector3d vtN ; - if ( ! pSurf->GetFacetNormal( nFacet, vtN)) - return false ; - // 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, V_NULL, 0) ; - // la restituisco - lstPC.emplace_back( Release( pCrvCompo)) ; return true ; } // se altrimenti regione @@ -1310,6 +1320,35 @@ PocketingNT::SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, return true ; } +//---------------------------------------------------------------------------- +bool +PocketingNT::SetSfrLoopsAllTempProp( int nSfrId, ISurfFlatRegion* pSfr) +{ + if ( pSfr == nullptr) + return false ; + pSfr->SetTempProp( TEMP_PROP_INVALID, 0) ; + pSfr->SetTempProp( TEMP_PROP_INVALID, 1) ; + // recupero le info per lati aperti + int nCount = -1 ; + while ( m_pGeomDB->ExistsInfo( nSfrId, KEY_OPEN + ToString( ++ nCount))) { + // recupero info sui lati aperti + INTVECTOR vOpen ; + m_pGeomDB->GetInfo( nSfrId, KEY_OPEN + ToString( nCount), vOpen) ; + // se non ho lati aperti, passo al loop successivo + if ( vOpen.empty()) + continue ; + // assegno le properità di lato aperto + for ( int i = 0 ; i < pSfr->GetLoopCurveCount( 0, nCount) ; ++ i) { + pSfr->SetCurveTempProp( 0, nCount, i, TEMP_PROP_CLOSE_EDGE, 0) ; + pSfr->SetCurveTempProp( 0, nCount, i, TEMP_PROP_INVALID, 1) ; + } + for ( int& i : vOpen) + pSfr->SetCurveTempProp( 0, nCount, i, TEMP_PROP_OPEN_EDGE, 0) ; + } ; + + return true ; +} + //---------------------------------------------------------------------------- bool PocketingNT::ResetCurveAllTempProp( ICurve* pCurve) @@ -1372,8 +1411,8 @@ PocketingNT::Chain( int nGrpDestId) bFirst = false ; } } - // recupero i percorsi concatenati - int nCount = 0 ; + // recupero i percorsi concatenati e definisco la regione piana di svuotatura + SurfFlatRegionByContours SfrByC ; INTVECTOR vnId2 ; while ( chainC.GetChainFromNear( ptNear, false, vnId2)) { // creo una curva composita @@ -1411,42 +1450,546 @@ PocketingNT::Chain( int nGrpDestId) // se non sono state inserite curve, vado oltre if ( pCrvCompo->GetCurveCount() == 0) continue ; + // se la curva non è chiusa, errore + if ( ! pCrvCompo->IsClosed()) { + m_pMchMgr->SetLastError( 2402, "Error in PocketingNT : Open Contour") ; + return false ; + } // imposto estrusione e spessore pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; + // verifico sia piana e se necessario la appiattisco + PtrOwner pFlatCrv( FlattenCurve( *pCrvCompo, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ; + if ( IsNull( pFlatCrv)) { + Plane3d plPlane ; + if ( ! pCrvCompo->IsFlat( plPlane, true, 50 * EPS_SMALL)) + m_pMchMgr->SetLastError( 2403, "Error in PocketingNT : Contour Not Flat") ; + else + m_pMchMgr->SetLastError( 2404, "Error in PocketingNT : Tool Not Perpendicular to Flat Area") ; + return false ; + } + pFlatCrv->GetExtrusion( vtExtr) ; + pCrvCompo->Clear() ; + pCrvCompo->AddCurve( Release( pFlatCrv)) ; + // salvo vettore estrusione + pCrvCompo->SetExtrusion( vtExtr) ; + // salvo la thickness come seconda temp prop ( la Sfr rimuove la thick delle curve) + pCrvCompo->SetTempParam( dThick, 1) ; // aggiorno il nuovo punto vicino - pCrvCompo->GetEndPoint( ptNear) ; + pCrvCompo->GetEndPoint( ptNear) ; // se utile, approssimo con archi if ( ! ApproxWithArcsIfUseful( pCrvCompo, true)) return false ; - // recupero eventuali lati aperti - INTVECTOR vOpen ; - for ( int i = 0 ; i < int( pCrvCompo->GetCurveCount()) ; ++ i) { - int nProp = 0 ; - if ( pCrvCompo->GetCurveTempProp( i, nProp) && nProp == 1) - vOpen.emplace_back( i) ; - } - // 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) ; + // inserisco la curva nella regione piana + SfrByC.AddCurve( Release( pCrvCompo)) ; } + + // scorro le regioni piane ricavate dalle curve + int nGroupName = -1 ; + PtrOwner pSfrCurr( SfrByC.GetSurf()) ; + while ( ! IsNull( pSfrCurr) && pSfrCurr->IsValid()) { + // per ogni Chunk + for ( int nC = 0 ; nC < pSfrCurr->GetChunkCount() ; ++ nC) { + // 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( ++ nGroupName)) ; + m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( nGroupName)) ; + // recupero il Chunk corrente + PtrOwner pSfrChunk( pSfrCurr->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::CloneSurfFlatRegion( pSfrChunk)) ; + if ( nNewId == GDB_ID_NULL) + return false ; + // salvo eventuali lati aperti per il Chunk corrente + for ( int nL = 0 ; nL < pSfrChunk->GetLoopCount( 0) ; ++ nL) { + // recupero il Loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // memorizzo le proprietà di lato aperto nelle Info del gruppo + INTVECTOR vIndOpen ; + for ( int nU = 0 ; nU < pCrvLoop->GetCurveCount() ; ++ nU) { + int nTmpProp0 = TEMP_PROP_INVALID ; + if ( pCrvLoop->GetCurveTempProp( nU, nTmpProp0, 0) && nTmpProp0 == TEMP_PROP_OPEN_EDGE) + vIndOpen.emplace_back( nU) ; + } + if ( ! vIndOpen.empty()) + m_pGeomDB->SetInfo( nNewId, KEY_OPEN + ToString( nL), vIndOpen) ; + // memorizzo la Thickness e l'Estrusione nelle Info del gruppo + if ( nL == 0) { + double dThick = pCrvLoop->GetTempParam( 1) ; + m_pGeomDB->SetInfo( nNewId, KEY_THICK, dThick) ; + Vector3d vtExtr ; + pCrvLoop->GetExtrusion( vtExtr) ; + m_pGeomDB->SetInfo( nNewId, KEY_EXTR, vtExtr) ; + } + } + } + // aggiorno la regione piana con la successiva calcolata + pSfrCurr.Set( SfrByC.GetSurf()) ; + } + return true ; } +//---------------------------------------------------------------------------- +ISurfTriMesh* +PocketingNT::GetRaw( void) +{ + // controllo MachManager e database geometrico + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return nullptr ; + + // creo Stm del grezzo + PtrOwner pStmRaw( CreateSurfTriMesh()) ; + if ( IsNull( pStmRaw)) + return nullptr ; + pStmRaw->AdjustTopology() ; + + // Id prima RawPart + int nRawId = m_pMchMgr->GetFirstRawPart() ; + + while ( nRawId != GDB_ID_NULL) { + // verifico che il grezzo compaia nella fase + if ( m_pMchMgr->VerifyRawPartPhase( nRawId, m_nPhase)) { + // recupero l'oggetto dal database con tale Id + int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; + const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( nRawSolidId) ; + if ( pGObj == nullptr) + return nullptr ; + // recupero il frame in cui si trova + Frame3d frRaw ; + m_pGeomDB->GetGlobFrame( nRawSolidId, frRaw) ; + // controllo che sia una Trimesh + if ( pGObj->GetType() == SRF_TRIMESH) { + SurfLocal StmRawPart( GetSurfTriMesh( pGObj), frRaw, GLOB_FRM) ; + // lo aggiungo alla Trimesh complessiva + pStmRaw->Add( *GetSurfTriMesh( StmRawPart)) ; + } + } + // passo al grezzo successivo + nRawId = m_pMchMgr->GetNextRawPart( nRawId) ; + } + + return ( ( pStmRaw->IsValid() && pStmRaw->GetTriangleCount() > 0) ? Release( pStmRaw) : nullptr) ; +} + +//---------------------------------------------------------------------------- +ISurfTriMesh* +PocketingNT::GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtTrasl, const Vector3d& vtExtr) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + + /* + pSfr -> superficie da cui estrudere i lati chiusi + vtTrals -> vettore di traslazione della superficie, per posizionarla all'ultimo Step + vtExtrs -> vettore estrusione dei lati chiusi di pSfr + */ + + PtrOwner pMySfr( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pMySfr) || ! pMySfr->IsValid()) + return false ; + pMySfr->Translate( vtTrasl) ; + + // zuppa di triangoli + StmFromTriangleSoup stmSoup ; + stmSoup.Start() ; + + // scorro i Loop della superficie piana + bool bExistClose = false ; + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + // recupero il Loop come curva composita + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return nullptr ; + // recupero i tratti con proprietà uniformi + ICRVCOMPOPOVECTOR vpCrvs ; + int nCurrTempProp ; + int nParStart = 0 ; + for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) { + // ricavo la TmpProp + int nTempProp = TEMP_PROP_INVALID ; + pCompoLoop->GetCurveTempProp( nU, nTempProp) ; + if ( nU == 0) { + nCurrTempProp = nTempProp ; + nParStart = nU ; + } + // se TmpProp differiscono, ricavo il tratto di curva omogeneo + else if ( nCurrTempProp != nTempProp) { + PtrOwner pCrv( ConvertCurveToComposite( pCompoLoop->CopyParamRange( nParStart, nU))) ; + if ( IsNull( pCrv)) + return nullptr ; + pCrv->SetTempProp( nCurrTempProp) ; // globale, al tratto di curva nel vettore + vpCrvs.emplace_back( Release( pCrv)) ; + nCurrTempProp = nTempProp ; + nParStart = nU ; + } + } + // ultima curva... + PtrOwner pCrvLast( ConvertCurveToComposite( pCompoLoop->CopyParamRange( nParStart, pCompoLoop->GetCurveCount()))) ; + if ( ! IsNull( pCrvLast)) { + pCrvLast->SetTempProp( nCurrTempProp) ; + vpCrvs.emplace_back( Release( pCrvLast)) ; + } + if ( vpCrvs.size() > 1) { // unisco il primo e l'ultimo se estremi compatibili + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE) && vpCrvs[0]->GetTempProp() == vpCrvs.back()->GetTempProp()) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + // scorro i tratti omogenei chiusi + for ( int nP = 0 ; nP < int( vpCrvs.size()) ; ++ nP) { + if ( vpCrvs[nP]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) { + // approssimo la curva ad una PolyLine + PolyLine PL ; + vpCrvs[nP]->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) ; + // estrusione del tratto chiuso + PtrOwner pStm( CreateSurfTriMesh()) ; + if ( IsNull( pStm) || + ! pStm->AdjustTopology() || + ! pStm->CreateByExtrusion( PL, vtExtr)) + return nullptr ; + // aggiungo i triangoli ricavati alla zuppa + if ( ! IsNull( pStm) && pStm->IsValid()) { + for ( int nT = 0 ; nT < pStm->GetTriangleCount() ; ++ nT) { + Triangle3d myTria ; pStm->GetTriangle( nT, myTria) ; + stmSoup.AddTriangle( myTria) ; + } + bExistClose = true ; + } + } + } + } + } + + // inizializzo la superficie di estrusione + PtrOwner pStmExtrusion( CreateSurfTriMesh()) ; + if ( IsNull( pStmExtrusion)) + return nullptr ; + pStmExtrusion->AdjustTopology() ; + stmSoup.End() ; + if ( bExistClose) { + pStmExtrusion.Set( stmSoup.GetSurf()) ; + if ( IsNull( pStmExtrusion)) + return nullptr ; + return ( ( pStmExtrusion->IsValid() && pStmExtrusion->GetTriangleCount() > 0) ? Release( pStmExtrusion) : nullptr) ; + } + return ( Release( pStmExtrusion)) ; +} + +//---------------------------------------------------------------------------- +ISurfFlatRegion* +PocketingNT::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs) +{ + // interseco la superficie alla quota corrente + PNTVECTOR vPnt ; + BIPNTVECTOR vBpt ; + TRIA3DVECTOR vTria ; + if ( ! IPPStm.GetInters( dDist, vPnt, vBpt, vTria)) + return nullptr ; + + // se non c'è intersezione + if ( vBpt.empty()) + return CreateSurfFlatRegion() ; + + // definisco la tolleranza per i concatenamenti + double dToler = EPS_SMALL ; + + // costruisco la FlatRegion da ritornare + SurfFlatRegionByContours SfrByC ; + + // Considero l'intersezione solo con Curve ( escludo punti e superfici) + ChainCurves chainC ; + chainC.Init( false, dToler, int( vBpt.size())) ; + for ( int i = 0 ; i < int( vBpt.size()) ; ++ i) { + Vector3d vtDir = vBpt[i].second - vBpt[i].first ; + vtDir.Normalize() ; + if ( ! chainC.AddCurve( i + 1, vBpt[i].first, vtDir, vBpt[i].second, vtDir)) + return nullptr ; + } + // recupero i percorsi concatenati + Point3d ptNear = ( vBpt.empty() ? ORIG : vBpt[0].first) ; + INTVECTOR vId ; + while ( chainC.GetChainFromNear( ptNear, false, vId)) { + // creo una curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return nullptr ; + // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita + bool bAdded = true ; + for ( int i = 0 ; i < int( vId.size()) ; ++ i) { + // creo un segmento di retta + PtrOwner pLine( CreateCurveLine()) ; + if ( IsNull( pLine)) + return nullptr ; + // recupero gli estremi ( non vanno mai invertiti per opzione di concatenamento) + int nInd = abs( vId[i]) - 1 ; + Point3d ptStart = ( bAdded ? vBpt[nInd].first : ptNear) ; + Point3d ptEnd = vBpt[nInd].second ; + // provo ad accodarlo alla composita + bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && + pLine->Set( ptStart, ptEnd) && + pCrvCompo->AddCurve( Release( pLine), true, dToler)) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro + double dCrvLen ; + if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) + continue ; + // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene + Point3d ptStart, ptEnd ; + if ( pCrvCompo->GetStartPoint( ptStart) && + pCrvCompo->GetEndPoint( ptEnd) && + AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) && + ! AreSamePointApprox( ptStart, ptEnd)) { + // porto il punto finale a coincidere esattamente con l'inizio + pCrvCompo->ModifyEnd( ptStart) ; + } + // unisco segmenti allineati + pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; + pCrvCompo->Close() ; // per sicurezza... + // inserisco la curva nella FlatRegion + SfrByC.AddCurve( Release( pCrvCompo)) ; + } + + // recupero la regione da restituire + PtrOwner pSfrFromCrvs( SfrByC.GetSurf()) ; + return ( ( ! IsNull( pSfrFromCrvs) && pSfrFromCrvs->IsValid()) ? Release( pSfrFromCrvs) : nullptr) ; +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion) +{ + + // controllo parametri : + if ( pSfr == nullptr || ! pSfr->IsValid() || + pStmExtrusion == nullptr) + return false ; + + // se non ho una superificie di estrusione, allora è tutto aperto + if ( ! pStmExtrusion->IsValid() || pStmExtrusion->GetTriangleCount() == 0) { + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) + for ( int nU = 0 ; nU < pSfr->GetLoopCurveCount( nC, nL) ; ++ nU) + pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_OPEN_EDGE, 0) ; + return true ; + } + + // per ogni curva dei Loop della FlatRegion vengono presi 4 punti di controllo equidistanti. + // " IL LATO E' APERTO <=> TUTTI I PUNTI DI CONTROLLO NON SONO A CONTATTO CON pStmExtrusion " + const int NUM_POINTS = 4 ; + // scorro tutti i loop + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + // recupero la curva composita del Loop + PtrOwner pCrvCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + if ( IsNull( pCrvCompoLoop) || ! pCrvCompoLoop->IsValid()) + return false ; + // scorro ogni sua sottocurva + for ( int nU = 0 ; nU < pCrvCompoLoop->GetCurveCount() ; ++ nU) { + // la sottocurva viene messa chiusa ( condizione base) + pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_OPEN_EDGE, 0) ; + // recupero la sottocurva + const ICurve* pCrv = pCrvCompoLoop->GetCurve( nU) ; + if ( pCrv == nullptr) + return false ; + // recupero i NUM_POINTS punti + bool bIsOnStm = true ; + for ( int p = 0 ; p < NUM_POINTS + 1 && bIsOnStm ; ++ p) { + double dPar = ( 1. / ( 1. * NUM_POINTS)) * p ; + Point3d ptPar ; + if ( ! pCrv->GetPointD1D2( dPar, ICurve::FROM_PLUS, ptPar)) + return false ; + // scorro il vettore relativo alla regione di riferimento + DistPointSurfTm distCalculator( ptPar, *pStmExtrusion) ; + double dDist = 0. ; + distCalculator.GetDist( dDist) ; + bIsOnStm = ( dDist < 25 * EPS_SMALL) ; + } + if ( bIsOnStm) + pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_CLOSE_EDGE, 0) ; + } + } + } + + return true ; + +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, ISurfFlatRegion* pSfrLimit) +{ + // controllo dei parametri + if ( pSfrPock == nullptr || ! pSfrPock->IsValid() || + pSfrRaw == nullptr || ! pSfrRaw->IsValid()) + return false ; + pSfrLimit->Clear() ; + + // la superficie limite è data dalla sottrazione tra il grezzo e la superficie da svuotare + pSfrLimit->CopyFrom( pSfrRaw) ; + if ( pSfrLimit == nullptr || ! pSfrLimit->IsValid()) + return false ; + // piccolo Offset di correzione + PtrOwner pSfrOffs( pSfrPock->CreateOffsetSurf( 5 * EPS_SMALL, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) + return false ; + // sottrazione + pSfrLimit->Subtract( *pSfrOffs) ; + + // se richiesto non controllo dei lati aperti + if ( m_bOpenOutRaw && pSfrLimit->IsValid()) { + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { + // recupero la curva di bordo + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // recupero i tratti con proprietà omogenee + ICRVCOMPOPOVECTOR vpCrvs ; + int nCurrTempProp = TEMP_PROP_INVALID ; + int nParStart = 0 ; + for ( int i = 0 ; i < pCrvLoop->GetCurveCount() ; ++ i) { + // ricavo la TmpProp + int nTempProp = TEMP_PROP_INVALID ; + pCrvLoop->GetCurveTempProp( i, nTempProp) ; + if ( i == 0) { + nCurrTempProp = nTempProp ; + nParStart = i ; + } + // se TmpProp differiscono, ricavo il tratto di curva omogeneo + else if ( nCurrTempProp != nTempProp) { + PtrOwner pCrv( ConvertCurveToComposite( pCrvLoop->CopyParamRange( nParStart, i))) ; + if ( IsNull( pCrv)) + return false ; + pCrv->SetTempProp( nCurrTempProp) ; // globale, al tratto di curva nel vettore + vpCrvs.emplace_back( Release( pCrv)) ; + nCurrTempProp = nTempProp ; + nParStart = i ; + } + } + // ultima curva... + PtrOwner pCrvLast( ConvertCurveToComposite( pCrvLoop->CopyParamRange( nParStart, pCrvLoop->GetCurveCount()))) ; + if ( ! IsNull( pCrvLast)) { + pCrvLast->SetTempProp( nCurrTempProp) ; + vpCrvs.emplace_back( Release( pCrvLast)) ; + } + if ( vpCrvs.size() > 1) { // unisco il primo e l'ultimo se estremi compatibili + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE) && vpCrvs[0]->GetTempProp() == vpCrvs.back()->GetTempProp()) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + // scorro i tratti omogenei aperti + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + // regione da sottrarre + PtrOwner pSfrSubtract( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSubtract)) + return false ; + if ( vpCrvs[i]->IsClosed()) { + pSfrSubtract.Set( GetSurfFlatRegionFromFatCurve( vpCrvs[i]->Clone(), 4 * m_TParams.m_dDiam + EPS_SMALL, false, false)) ; + if ( IsNull( pSfrSubtract) || ! pSfrSubtract->IsValid()) + return false ; + } + else { + // creo la curva di Offset esterna ( deve esistere ed essere valida) + OffsetCurve OffsCrv ; + PtrOwner pOffsExt( CreateCurveComposite()) ; + if ( IsNull( pOffsExt) || + ! OffsCrv.Make( vpCrvs[i], 4 * m_TParams.m_dDiam, ICurve::OFF_FILLET) || + ! pOffsExt.Set( OffsCrv.GetLongerCurve()) || + IsNull( pOffsExt)) + return false ; + // creo la curva di Offset interna ( se esiste e valida...) + PtrOwner pOffsInt( CreateCurveComposite()) ; + if ( IsNull( pOffsInt)) + return false ; + if ( OffsCrv.Make( vpCrvs[i], - 4 * m_TParams.m_dDiam, ICurve::OFF_FILLET)) { + PtrOwner pMyCrv( OffsCrv.GetLongerCurve()) ; + if ( ! IsNull( pMyCrv) && pMyCrv->IsValid()) + pOffsInt.Set( pMyCrv) ; + } + // recupero gli estremi della curva aperta corrente + Point3d pt1 ; vpCrvs[i]->GetEndPoint( pt1) ; + Point3d pt4 ; vpCrvs[i]->GetStartPoint( pt4) ; + // verifico se una delle due curve esiste + bool bExistExt = ( ! IsNull( pOffsExt) && pOffsExt->IsValid()) ; + bool bExistInt = ( ! IsNull( pOffsInt) && pOffsInt->IsValid()) ; + PtrOwner pCrvExtLoopSurfInc( CreateCurveComposite()) ; + if ( IsNull( pCrvExtLoopSurfInc)) + return false ; + if ( bExistExt && bExistInt) { + Point3d pt2 ; pOffsInt->GetEndPoint( pt2) ; + Point3d pt3 ; pOffsInt->GetStartPoint( pt3) ; + Point3d pt5 ; pOffsExt->GetStartPoint( pt5) ; + if ( ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsExt)) || + ! pCrvExtLoopSurfInc->AddLine( pt1) || + ! pCrvExtLoopSurfInc->AddLine( pt2) || + ! pOffsInt->Invert() || + ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsInt)) || + ! pCrvExtLoopSurfInc->AddLine( pt4) || + ! pCrvExtLoopSurfInc->AddLine( pt5)) + return false ; + } + else if ( bExistExt) { + Point3d pt5 ; pOffsExt->GetStartPoint( pt5) ; + if ( ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsExt)) || + ! pCrvExtLoopSurfInc->AddLine( pt1) || + ! pCrvExtLoopSurfInc->AddLine( pt4) || + ! pCrvExtLoopSurfInc->AddLine( pt5)) + return false ; + } + else if ( bExistInt) { + Point3d pt5 ; pOffsInt->GetStartPoint( pt5) ; + if ( ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsInt)) || + ! pCrvExtLoopSurfInc->AddLine( pt1) || + ! pCrvExtLoopSurfInc->AddLine( pt4) || + ! pCrvExtLoopSurfInc->AddLine( pt5)) + return false ; + } + else + return false ; + // per sicurezza... + pCrvExtLoopSurfInc->Close() ; + if ( ! pSfrSubtract->AddExtLoop( Release( pCrvExtLoopSurfInc))) + return false ; + if ( pSfrSubtract->IsValid() && pSfrSubtract->GetChunkCount() > 0) { + Vector3d vtN = pSfrSubtract->GetNormVersor() ; + if ( AreOppositeVectorApprox( vtN, pSfrPock->GetNormVersor())) + pSfrSubtract->Invert() ; + } + } + if ( pSfrSubtract->IsValid()) + pSfrLimit->Subtract( *pSfrSubtract) ; + } + } + } + } + } + + return true ; + +} + //---------------------------------------------------------------------------- bool PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) { + // aggiorno la ProgressBar del 5% per simulare l'inizio della funzione + ExeProcessEvents( 5, 0) ; + // recupero gruppo per geometria temporanea const string GRP_TEMP = "Temp" ; int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; @@ -1464,95 +2007,37 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) 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) + // recupero la regione piana dal database geometrico + int nSfrId = m_pGeomDB->GetFirstInGroup( nPathId) ; + if ( m_pGeomDB->GetGeoType( nSfrId) != SRF_FLATRGN) return false ; - ICurve* pCrv = ::GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ; - if ( pCrv == nullptr || ! pCrv->IsClosed()) { - m_pMchMgr->SetLastError( 2402, "Error in PocketingNT : Open Contour") ; - return false ; - } - // copio la curva composita da elaborare - int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; + // copio la regione piana da elaborare + int nCopyId = m_pGeomDB->CopyGlob( nSfrId, GDB_ID_NULL, nTempId) ; if ( nCopyId == GDB_ID_NULL) return false ; - ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; + PtrOwner pSfr( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nCopyId))) ; + if ( IsNull( pSfr) || ! pSfr->IsValid()) + return false ; - // 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 ; - SetCurveAllTempProp( nCrvId, GetForcedClosed(), pCompo, &bSomeOpen) ; + // assegno le proprietà di lato aperto ai sui loops + SetSfrLoopsAllTempProp( nSfrId, pSfr) ; // recupero estrusione e spessore Vector3d vtExtr = Z_AX ; - pCompo->GetExtrusion( vtExtr) ; - double dThick ; - pCompo->GetThickness( dThick) ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_EXTR)) + m_pGeomDB->GetInfo( nSfrId, KEY_EXTR, vtExtr) ; + double dThick = 0. ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_THICK)) + m_pGeomDB->GetInfo( nSfrId, KEY_THICK, dThick) ; // eventuale inversione direzione utensile if ( m_Params.m_bToolInvert) { - vtExtr.Invert() ; - pCompo->SetExtrusion( vtExtr) ; + pSfr->Invert() ; + vtExtr.Invert() ; dThick = - dThick ; - pCompo->SetThickness( dThick) ; } - // 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 PocketingNT : Contour Not Flat") ; - else - m_pMchMgr->SetLastError( 2404, "Error in PocketingNT : 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 PocketingNT : adjust open edges failed") ; - 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) ; - - // recupero il punto di inizio (per poi salvarlo nelle info di CL path) - Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; - // recupero il box del grezzo in globale BBox3d b3Raw ; if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) { @@ -1589,12 +2074,17 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // assegno il versore fresa Vector3d vtTool = vtExtr ; + // recupero il Loop esterno della regione da svuotatare + PtrOwner pCrvLoopExt( ConvertCurveToComposite( pSfr->GetLoop( 0, 0))) ; + if ( IsNull( pCrvLoopExt) || ! pCrvLoopExt->IsValid()) + return false ; + // calcolo l'elevazione massima double dElev ; - if ( CalcRegionElevation( pCompo, vtTool, dDepth, 0.5 * m_TParams.m_dDiam, m_TParams.m_dLen, dElev)) { + if ( CalcRegionElevation( pCrvLoopExt, vtTool, dDepth, 0.5 * m_TParams.m_dDiam, m_TParams.m_dLen, dElev)) { if ( dElev < EPS_SMALL && AreSameVectorApprox( vtExtr, Z_AX)) { BBox3d b3Crv ; - pCompo->GetLocalBBox( b3Crv) ; + pCrvLoopExt->GetLocalBBox( b3Crv) ; dElev = max( 0., b3Raw.GetMax().z - b3Crv.GetMin().z + min( 0., dThick) + dDepth) ; } } @@ -1634,7 +2124,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) } // se lavorazione singola if ( dOkStep < EPS_SMALL || dOkStep > dElev) { - // se l'elevazione supera la capacità dell'utensile + // se l'elevazione supera la capacità dell'utensile if ( dElev > m_TParams.m_dMaxMat + EPS_SMALL) { string sInfo = "Warning in PocketingNT : machining depth (" + ToString( dElev, 1) + ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; @@ -1667,9 +2157,8 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // verifiche per svuotature dal basso m_bAggrBottom = false ; - if ( ! VerifyPathFromBottom( pCompo, vtTool)) { + if ( ! VerifyPathFromBottom( pCrvLoopExt, vtTool)) return false ; - } // recupero eventuale flag di lato aperto forzato fuori dal grezzo int nOpenOutRaw ; @@ -1687,8 +2176,17 @@ PocketingNT::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)) + int nRId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, CloneSurfFlatRegion( pSfr)) ; + if ( nRId == GDB_ID_NULL) return false ; + m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ; + m_pGeomDB->SetMaterial( nRId, Color( 255, 0, 0, 60)) ; + // la copio anche come regione ridotta + int nRrId = m_pGeomDB->Copy( nRId, GDB_ID_NULL, nPathId) ; + if ( nRrId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ; + m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ; } // se richiesta lavorazione @@ -1705,37 +2203,111 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // 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) ; // assegno l'elevazione massima m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; - // Imposto dati comuni + // recupero il grezzo + PtrOwner pStmRaw( GetRaw()) ; + if ( IsNull( pStmRaw)) { + m_pMchMgr->SetLastError( 3025, "Error in PocketingNT : RawPart not computable") ; + return false ; + } + pStmRaw->Translate( - vtTool * 510 * EPS_SMALL) ; // per tasche passanti + + // determino numero e affondamento degli step + int nStep = 1 ; + nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + double dStep = dElev / nStep ; + + // su tutti gli step ricavati, calcolo le PolyLine delle Silhouette + int nPocket = 0 ; // numero effettivo di Pocketing calcolate + int nProgressBarStep = 0 ; // step per progressBar + + // vettore per gli step + STEPINFOPOVECTOR vStepInfo ; + + // inizializzo la classe di intersezione tra grezzo e piani paralleli ( quelli di lavoro) + Frame3d frSfr ; + Point3d ptCen ; pSfr->GetCentroid( ptCen) ; + Frame3d frPocket ; + if ( ! frPocket.Set( ptCen, vtTool) || ! frPocket.IsValid()) + return false ; + IntersParPlanesSurfTm IPPStm( frPocket, *pStmRaw) ; + + // definisco una trimesh derivante dalla regione piana mediante estrusione dei lati chiusi + Vector3d vtSfrTrasl = - vtTool * ( dDepth - dElev + nStep * dStep) ; + Vector3d vtStmExtr = - vtTool * ( dDepth - dElev + dStep - 500 * EPS_SMALL) ; + PtrOwner pStmExtrusion( GetExtrusionStm( pSfr, vtSfrTrasl, vtStmExtr)) ; + if ( IsNull( pStmExtrusion)) + return false ; + + if ( _m_Debug) { + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStmExtrusion->Clone()) ; + m_pGeomDB->SetMaterial( _a, Color( 1., 0., 1., .75)) ; + } + + for ( int j = 1 ; j <= nStep ; ++ j) { + // per i contatori non controllo se effettivamente svuoto una superficie o meno + ++ nProgressBarStep ; // aggiorno step per progressBar + + // porto la superficie allo step corrente + PtrOwner pSfrPock( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfrPock) || ! pSfrPock->IsValid() || + ! pSfrPock->Translate( - vtTool * ( dDepth - dElev + j * dStep))) + return false ; + + // adatto la regione piana alla geometria del grezzo + PtrOwner pSfrRaw( GetSfrByStmIntersection( IPPStm, - ( dDepth - dElev + j * dStep), 0)) ; + if ( IsNull( pSfrRaw)) { + m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Slicing Raw failed") ; + return false ; + } + if ( pSfrRaw->IsValid() && pSfrRaw->GetChunkCount() > 0) + pSfrPock->Intersect( *pSfrRaw) ; + + // se regione risultante non vuota + if ( pSfrPock->IsValid() && pSfrPock->GetChunkCount() > 0) { + // determino i lati aperti + if ( ! ChooseCloseOrOpenEdge( pSfrPock, pStmExtrusion)) { + m_pMchMgr->SetLastError( 3026, "Error in PocketingNT : Detecting open edges failed") ; + return false ; + } + if ( _m_Debug) + _debug_draw_sfr( pSfrPock, false) ; + // determino la regione limite + PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrLimit) || + ! CalcLimitRegion( pSfrPock, pSfrRaw, pSfrLimit)) { + m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Calc limit region failed") ; + return false ; + } + + if ( _m_Debug) { + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrLimit->Clone()) ; + m_pGeomDB->SetMaterial( _a, Color( .5, .5, .5, .5)) ; + } + // inserisco le informazioni dello step nel vettore + vStepInfo.resize( vStepInfo.size() + 1) ; + vStepInfo.back().dDepth = - j * dStep ; + vStepInfo.back().dRelativeDepth = - dStep ; + vStepInfo.back().pSfrPock.Set( Release( pSfrPock)) ; + vStepInfo.back().pSfrLimit.Set( CreateSurfFlatRegion()) ; + if ( pSfrLimit->IsValid()) + vStepInfo.back().pSfrLimit.Set( pSfrLimit) ; + } + + ++ nPocket ; + // aggiorno la progressBar + ExeProcessEvents( 5 + nProgressBarStep * 45 / nStep, 100) ; + + } + + // imposto dati comuni SetPathId( nPxId) ; SetToolDir( vtTool) ; - // Eseguo la lavorazione a seconda del tipo - switch ( m_Params.m_nSubType) { - case POCKET_SUB_ZIGZAG : - case POCKET_SUB_CONFORMAL_ZIGZAG : - if ( ! AddZigZag( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) - return false ; - break ; - case POCKET_SUB_ONEWAY : - case POCKET_SUB_CONFORMAL_ONEWAY : - if ( ! AddOneWay( pCompo, 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)) - return false ; - break ; - case POCKET_SUB_SPIRALOUT : - if ( ! AddSpiralOut( pCompo, vtTool, vtExtr, dDepth, dElev, dOkStep, bSplitArcs, nPathId)) - return false ; - break ; - } + if ( ! AddPocket( vStepInfo, vtTool, dElev, dStep, bSplitArcs)) + return false ; } // incremento numero di svuotature @@ -1747,7 +2319,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) //---------------------------------------------------------------------------- bool PocketingNT::CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double dLen, - double& dElev) const + double& dElev) { // inizializzo l'elevazione dElev = 0 ; @@ -1948,6 +2520,315 @@ PocketingNT::GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) return true ; } +//---------------------------------------------------------------------------- +bool +PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) +{ + /* + funzione per calcolo dei percorsi di Pockets e delle loro proprietà + */ + + // punto finale di riferimento per il percorso attuale ( serve per trovare il punto iniziale + // del percorso successivo) + Point3d ptEndLastPath = P_INVALID ; + + // scorro gli indici delle superfici + for ( int i = 0 ; i < int( vStepInfo.size()) ; ++ i) { + // calcolo i percorsi di Pocketing + ICRVCOMPOPOVECTOR vCrvPaths ; + if ( ! CalcPocketing( vStepInfo[i].pSfrPock, m_TParams.m_dDiam / 2, 0., m_Params.m_dSideStep, + m_Params.m_dSideAngle, m_Params.m_nSubType, true, m_Params.m_bInvert, + false, true, ptEndLastPath, vStepInfo[i].pSfrLimit, vCrvPaths)) { + m_pMchMgr->SetLastError( 3028, "Error in PocketingNT : Error in CalcPocketing") ; + return false ; + } + // se non ho ottenuto percorsi, allora passo allo step successivo ( nInd non viene aggiornato!) + if ( vCrvPaths.empty()) + continue ; + // sistemo gli archi per massimo angolo al centro + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) + VerifyArcs( vCrvPaths[i]) ; + // recupero il punto finale del percorso per lo step successivo + vCrvPaths.back()->GetEndPoint( ptEndLastPath) ; + // inserisco i percorsi nel vettore dei Paths + vStepInfo[i].vPaths.resize( int( vCrvPaths.size())) ; + for ( int j = 0 ; j < int( vCrvPaths.size()) ; ++ j) { + // controllo se il percorso ha un ingresso presso un lato aperto + vStepInfo[i].vPaths[j].bOutStart = ( vCrvPaths[j]->GetCurveCount() > 0 && + vCrvPaths[j]->GetFirstCurve()->GetTempProp( 0) == TEMP_PROP_OUT_START) ; + + // controllo se il percorso è formato da una singola curva seguente il lato chiuso + vStepInfo[i].vPaths[j].bSingleCrv = ( vCrvPaths[j]->GetCurveCount() > 0 && + vCrvPaths[j]->GetTempProp( 0) == TEMP_PROP_SINGLE_CURVE) ; + + // controllo se caso ottimizzato a trapezio + vStepInfo[i].vPaths[j].bOptTrap = ( vCrvPaths[j]->GetCurveCount() > 0 && + vCrvPaths[j]->GetTempProp( 0) == TEMP_PROP_OPT_TRAPEZOID) ; + + // controllo se è un percorso a ZigZag/OneWay ( non curva di bordo) + vStepInfo[i].vPaths[j].bIsZigZagOneWayBorder = ( vCrvPaths[j]->GetCurveCount() > 0 && + ( m_Params.m_nSubType == POCKET_SUB_ONEWAY || m_Params.m_nSubType == POCKET_SUB_ZIGZAG) && + vCrvPaths[j]->GetTempProp( 0) == TEMP_PROP_BORDER_CURVE) ; + + // se LeadIn o LeadOut a guida recupero la curva di ritorno se necessaria + if ( ( GetLeadInType() == POCKET_LI_GLIDE || GetLeadOutType() == POCKET_LO_GLIDE) && + ( m_Params.m_nSubType == POCKET_SUB_SPIRALIN && + ! vStepInfo[i].vPaths[j].bSingleCrv && ! vStepInfo[i].vPaths[j].bOutStart)) + { + if ( vStepInfo[i].vPaths[j].bOptTrap) + vStepInfo[i].vPaths[j].pCrvRet.Set( ConvertCurveToComposite( vCrvPaths[i]->GetFirstCurve()->Clone())) ; + else { + Point3d ptStart ; vCrvPaths[j]->GetFirstCurve()->GetStartPoint( ptStart) ; + vStepInfo[i].vPaths[j].pCrvRet.Set( CreateCurveComposite()) ; + for ( int k = 0 ; k < vCrvPaths[j]->GetCurveCount() ; ++ k) { + const ICurve* pCrv = vCrvPaths[j]->GetCurve( k) ; + Point3d ptEnd ; + if ( pCrv == nullptr || + ! vStepInfo[i].vPaths[j].pCrvRet->AddCurve( *pCrv) || + ! pCrv->GetEndPoint( ptEnd)) + return false ; + if ( AreSamePointApprox( ptStart, ptEnd)) + break ; + } + } + } + + // assegno il percorso + vStepInfo[i].vPaths[j].pCrvPath.Set( vCrvPaths[j]) ; + } + // aggiorno la progressBar + ExeProcessEvents( 50 + i * 50 / int( vStepInfo.size()), 100) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, double dElev, double dStep, bool bSplitArcs) +{ + // se non ho superfici da svuotare, non faccio nulla + if ( vStepInfo.empty()) + return true ; + + // calcolo i percorsi di svuotatura per ogni Step/SubStep + if ( ! CalcPaths( vStepInfo)) + return false ; + + // recupero distanze di sicurezza + double dSafeZ = GetSafeZ() ; + double dSafeAggrBottZ = GetSafeAggrBottZ() ; + // lunghezza di approccio/retrazione + double dAppr = m_Params.m_dStartPos ; + // elevazione sopra al punto attuale + double dCurrElev ; + // punto finale del percorso precedente al corrente + Point3d ptEnd = P_INVALID ; + + // scorro il vettore dei piani di pocketing + for ( int i = 0 ; i < int( vStepInfo.size()) ; ++ i) { + + // riferimento alle informazioni relative allo step i-esimo + StepInfoPO& currStep = vStepInfo[i] ; + // scorro i percorsi calcolati per il piano di pocketing i-esimo + for ( int j = 0 ; j < int( currStep.vPaths.size()) ; ++ j) { + + // riferimento alle informazioni relative al percorso j-esimo del piano di pocketing i-esimo + PathInfoPO& currPath = currStep.vPaths[j] ; + // ciclo sulle curve elementari del percorso attuale + int nMaxInd = currPath.pCrvPath->GetCurveCount() - 1 ; + for ( int k = 0 ; k <= nMaxInd ; ++ k) { + + // curva corrente + const ICurve* pCrvC = currPath.pCrvPath->GetCurve( k) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) + return false ; + // coefficiente feed ( riduzione di feed per sezione di taglio superiore al previsto ) + double dTempParam ; currPath.pCrvPath->GetCurveTempParam( k, dTempParam) ; + double dCoeffFeed = min( 1., ( dTempParam > EPS_SMALL ? dTempParam /= 1000 : 1)) ; + + // se prima entità + if ( k == 0) { + // dati inizio entità + Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; pCurve->GetStartDir( vtStart) ; + // flag approccio libero in aria + if ( currPath.bOutStart) + dCoeffFeed = ( dTempParam > EPS_SMALL ? dTempParam : 1) ; + // calcolo ptP1 per LeadIn iniziale + Point3d ptP1 ; + if ( ! CalcLeadInStart( ptStart, vtTool, currPath.pCrvRet, ptP1)) { + m_pMchMgr->SetLastError( 3013, "Error in PocketingNT : LeadIn not computable") ; + return false ; + } + // determino l'elevazione sull'inizio dell'attacco della prima curva globale + bool bAbsFirst = ( i == 0 && j == 0) ; + if ( bAbsFirst) + dCurrElev = - currStep.dDepth ; + dCurrElev -= ( ptP1 - ptStart) * vtTool ; + // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco + if ( GetLeadInType() != POCKET_LI_NONE) { + double dMyLIO_ELEV_TOL = min( LIO_ELEV_TOL, dSafeZ) ; + // se prima entità in assoluto + if ( bAbsFirst) { + ptP1 += vtTool * ( dCurrElev + dMyLIO_ELEV_TOL) ; + dCurrElev = - min( LIO_ELEV_TOL, dSafeZ) ; + } + // altrimenti... + else if ( ! currPath.bOutStart) + ptP1 += vtTool * ( - currStep.dRelativeDepth + dMyLIO_ELEV_TOL) ; + } + // approccio al punto iniziale + double dMySafeZ = ( bAbsFirst ? dSafeZ : 0.) ; + Point3d ptMyPos ; GetCurrPos( ptMyPos) ; + double dMyElev = ( bAbsFirst ? dCurrElev : ( ptMyPos - ptP1) * vtTool) ; + double dMyAppr = ( bAbsFirst ? dAppr : 0.) ; + if ( ! AddApproach( ptP1, vtTool, dMySafeZ, dSafeAggrBottZ, dMyElev, dMyAppr, bSplitArcs, currPath.bOutStart)) { + m_pMchMgr->SetLastError( 3011, "Error in PocketingNT : Approach not computable") ; + return false ; + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + bool bNoneForced = ( currPath.bOutStart || currPath.bSingleCrv || + ( m_Params.m_nSubType == POCKET_SUB_ZIGZAG && ! currPath.bIsZigZagOneWayBorder) || + ( m_Params.m_nSubType == POCKET_SUB_ONEWAY && ! currPath.bIsZigZagOneWayBorder)) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtTool, currStep.pSfrPock, + ( ( m_Params.m_nSubType == POCKET_SUB_SPIRALIN || m_Params.m_nSubType == POCKET_SUB_SPIRALOUT)) ? Get( currPath.pCrvRet) : nullptr, + ( m_Params.m_nSubType == POCKET_SUB_SPIRALOUT) ? m_Params.m_bInvert : ! m_Params.m_bInvert, + bSplitArcs, bNoneForced, false)) { + m_pMchMgr->SetLastError( 3013, "Error in PocketingNT : LeadIn not computable") ; + return false ; + } + } + + // elaborazioni sulla curva corrente (sempre un segmento di retta) + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + Vector3d vtMove ; pLine->GetStartDir( vtMove) ; + SetFeed( dCoeffFeed * GetRightFeed( vtMove, vtTool)) ; + 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( dCoeffFeed * GetFeed()) ; + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + + // se ultima entità + if ( k == nMaxInd) { + // dati fine entità + pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; pCurve->GetEndDir( vtEnd) ; + // se sono l'ultima entità globale del percorso + if ( i == int( vStepInfo.size()) - 1 && j == int( currStep.vPaths.size()) - 1) { + // aggiungo LeadOut + Point3d ptP1 ; + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, vtTool, + ( ( m_Params.m_nSubType == POCKET_SUB_SPIRALIN || m_Params.m_nSubType == POCKET_SUB_SPIRALOUT)) ? Get( currPath.pCrvRet) : nullptr, + bSplitArcs, false, ptP1)) { + m_pMchMgr->SetLastError( 3014, "Error in PocketingNT : LeadOut not computable") ; + return false ; + } + // aggiungo retroazione finale + if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, - currStep.dDepth, dAppr, bSplitArcs)) { + m_pMchMgr->SetLastError( 3015, "Error in PocketingNT : Retract not computable") ; + return false ; + } + } + // se ho un percorso successivo + else { + // ricavo il punto che devo raggiungere e controllo la posizione del percorso successivo + bool bSamePlane = ( j < int( currStep.vPaths.size()) - 1) ; + bool bNextIsBelow = true ; + Point3d ptDest ; + if ( bSamePlane) + currStep.vPaths[j+1].pCrvPath->GetStartPoint( ptDest) ; + else { + vStepInfo[i+1].vPaths.front().pCrvPath->GetStartPoint( ptDest) ; + bNextIsBelow = ( ( ptDest - ptEnd) * vtTool < - 50 * EPS_SMALL) ; + } + // determino se un collegamento lineare tra i punti proiettati nel piano attuale è ammissibile + bool bSafe = false ; + if ( m_Params.m_nSubType != POCKET_SUB_ZIGZAG && m_Params.m_nSubType != POCKET_SUB_ONEWAY) { + if ( ! CheckSafetyLinearLink( ptEnd, + ( bSamePlane ? currStep.pSfrLimit : + ( bNextIsBelow ? currStep.pSfrLimit : vStepInfo[i+1].pSfrLimit)), + vtTool, ptDest, bSafe)) + return false ; + } + // determino l'elevazione sul punto corrente e sul punto di destinazione + dCurrElev = dSafeZ ; + double dNextElev = dSafeZ ; + if ( bSafe) { + if ( bSamePlane) { + if ( ( ( m_Params.m_nSubType == SURFROU_SUB_SPIRALIN || m_Params.m_nSubType == SURFROU_SUB_SPIRALOUT) && + ! vStepInfo[i].vPaths[j+1].bOutStart) || + ( m_Params.m_nSubType != SURFROU_SUB_SPIRALIN && m_Params.m_nSubType != SURFROU_SUB_SPIRALOUT)) { + dCurrElev -= currStep.dRelativeDepth ; + dNextElev = dCurrElev ; + } + } + else if ( bNextIsBelow) + dNextElev += ( ptEnd - ptDest) * vtTool ; + else { + dCurrElev += ( ptDest - ptEnd) * vtTool - currStep.dRelativeDepth ; + dNextElev -= currStep.dRelativeDepth ; + } + } + else { + dCurrElev -= currStep.dDepth ; + if ( bSamePlane) + dNextElev -= currStep.dDepth ; + else + dNextElev -= vStepInfo[i+1].dDepth ; + } + // tratto lineare sopra al punto corrente + SetFeed( GetEndFeed()) ; + AddLinearMove( ptEnd + vtTool * dCurrElev) ; + // tratto lineare sopra a ptDest + AddLinearMove( ptDest + vtTool * dNextElev) ; + // aggiorno le elevazioni + dCurrElev = dNextElev ; + } + } + } + } + } + + // aggiorno per sicurezza la ProgressBar nel caso di Step vuoti + ExeProcessEvents( 100, 100) ; + return true ; +} + +//---------------------------------------------------------------------------- +double +PocketingNT::GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) +{ + // Determino i versori + Vector3d vtM = vtMove ; + vtM.Normalize() ; + Vector3d vtT = vtTool ; + vtT.Normalize() ; + // Angolo tra movimento e versore utensile + double dCosMove = vtM * vtT ; + // Se l'utensile non ha movimento significativo di punta, si restituisce la feed standard + if ( dCosMove > - COS_ORTO_ANG_SMALL) + return GetFeed() ; + // Altrimenti non si deve superare la massima velocità di punta prevista + return min( GetFeed(), GetTipFeed() / abs( dCosMove)) ; +} + //---------------------------------------------------------------------------- static double GetCurveRadius( const ICurve* pCrv) @@ -1963,1058 +2844,8 @@ GetCurveRadius( const ICurve* pCrv) return dRad ; } -//---------------------------------------------------------------------------- +//------------------------------------------------------------------ bool -PocketingNT::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) -{ - // recupero distanze di sicurezza - double dSafeZ = GetSafeZ() ; - double dSafeAggrBottZ = GetSafeAggrBottZ() ; - // lunghezza di approccio/retrazione - double dAppr = m_Params.m_dStartPos ; - - // determino numero e affondamento degli step - int nStep = 1 ; - 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 ; - double dOptZigZagOffs ; - if ( ! OptimizedZigZag( nPathId, vtTool, dDepth, dSafeZ, frPocket, bOptimizedZigZag, vpCrvs, dOptZigZagOffs)) - 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 - dOptZigZagOffs + 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 - dOptZigZagOffs + 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 ( ! LeadInRawIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in PocketingNT : 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)) { - m_pMchMgr->SetLastError( 2412, "Error in PocketingNT : Offset not computable") ; - return false ; - } - nOffsCrvNbr = OffsCrv.GetCurveCount() ; - } - - // ciclo sulle curve risultanti - bool bStart = true ; - while ( nOffsCrvNbr > 0) { - - if ( bOptimizedZigZag) - nOffsCrvNbr = 0 ; // setto a zero per non rientrare nel while - else { - // recupero la prima curva di offset - PtrOwner pOffs ; - if ( ! pOffs.Set( ConvertCurveToComposite( OffsCrv.GetLongerCurve()))) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - 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) ; - } - } - } - - // se necessario, approssimo con rette - if ( bSplitArcs) { - for ( auto& pMCrv : vpCrvs) { - if ( ! ApproxWithLines( pMCrv)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - } - } - - // 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 entità - 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw) - 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 + LIO_ELEV_TOL) ; - dStElev = -LIO_ELEV_TOL ; - } - } - // se inizio, approccio globale al punto iniziale - if ( bStart) { - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs, bOutRawLeadIn || m_bOpenOutRaw)) { - m_pMchMgr->SetLastError( 2414, "Error in PocketingNT : Approach not computable") ; - return false ; - } - bStart = false ; - } - // altrimenti, approccio di collegamento - else { - if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs, bOutRawLeadIn || m_bOpenOutRaw)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : Link 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 PocketingNT : 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, bSplitArcs) == 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) { - // 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, true, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : LeadOut not computable") ; - return false ; - } - // 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, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : Retract not computable") ; - return false ; - } - } - // altrimenti, aggiungo retrazione di collegamento - else { - if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : 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 PocketingNT : Offset not computable") ; - return false ; - } - - // ciclo sulle curve risultanti - while ( OffsCrv2.GetCurveCount() > 0) { - - // recupero la prima curva di offset - PtrOwner pOffs2 ; - if ( ! pOffs2.Set( ConvertCurveToComposite( OffsCrv2.GetLongerCurve()))) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - - // se necessario, approssimo con rette - if ( bSplitArcs) { - if ( ! ApproxWithLines( pOffs2)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - } - // altrimenti verifico archi - else - 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) - 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 + LIO_ELEV_TOL) ; - dStElev = -LIO_ELEV_TOL ; - } - // approccio al punto iniziale - if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : 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 PocketingNT : 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 PocketingNT : 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, bSplitArcs) == 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, false, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : 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, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : Link not computable") ; - return false ; - } - } - // altrimenti retrazione finale - else { - if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : Retract not computable") ; - return false ; - } - } - } - } - } - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::CalcZigZag( const ICurveComposite* pOffs, - ICRVCOMPOPOVECTOR& vpCrvs) -{ - // ingombro del contorno offsettato - BBox3d b3Pocket ; - pOffs->GetLocalBBox( b3Pocket) ; - Point3d ptMin ; double dDimX, dDimY, dDimZ ; - b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; - - // lunghezza del contorno offsettato - double dLen ; pOffs->GetLength( dLen) ; - - // passi in Y - int nYStep = static_cast( 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) ; - - // tratto valido - struct Section { - bool bActive ; - Point3d ptS ; - Point3d ptE ; - double dOs ; - double dOe ; - } ; - // 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) { - // 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)) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - // calcolo la classificazione della curva rispetto al contorno esterno offsettato - IntersCurveCurve intCC( *pLine, *pOffs) ; - CRVCVECTOR ccClass ; - if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass)) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : 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)) ; - } - } - - // dominio del contorno - double dUmin, dUmax ; - pOffs->GetDomain( dUmin, dUmax) ; - double dUspan = dUmax - dUmin ; - - // 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 ( vvSec[k][l].bActive) { - nI = k ; - nJ = l ; - } - } - } - // se trovata, creo nuova curva composita - if ( nI >= 0 && nJ >= 0) { - // creo la curva - vpCrvs.emplace_back( CreateCurveComposite()) ; - // aggiungo punto iniziale - vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ; - } - // altrimenti, esco - else - break ; - } - // determino senso - bool bPlus = (( nI % 2) == nRef) ; - // aggiungo la sezione alla curva - Section& Sec = vvSec[nI][nJ] ; - Sec.bActive = false ; - vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ; - // cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno - double dUstart = Sec.dOe ; - 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) - continue ; - double dU = vvSec[k][l].dOs ; - if ( bPlus) { - if ( dU < dUstart) - dU += dUspan ; - if ( dU < dUref) { - dUref = dU ; - nNextI = k ; - nNextJ = l ; - } - } - else { - if ( dU > dUstart) - dU -= dUspan ; - if ( dU > dUref) { - dUref = dU ; - nNextI = k ; - nNextJ = l ; - } - } - } - li = 0 ; - } - // se trovato, aggiungo il tratto di contorno e continuo - if ( nNextI != -1) { - PtrOwner pCopy ; - if ( bPlus) { - if ( dUref > dUmax) - dUref -= dUspan ; - pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ; - if ( ! IsNull( pCopy)) { - double dCLen ; pCopy->GetLength( dCLen) ; - if ( dCLen > 0.5 * dLen) { - pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ; - if ( ! IsNull( pCopy)) - pCopy->Invert() ; - } - } - } - else { - if ( dUref < dUmin) - dUref += dUspan ; - pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ; - if ( ! IsNull( pCopy)) { - pCopy->Invert() ; - double dCLen ; pCopy->GetLength( dCLen) ; - if ( dCLen > 0.5 * dLen) - pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ; - } - } - BBox3d b3Copy ; - if ( ! IsNull( pCopy)) - pCopy->GetLocalBBox( b3Copy) ; - if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { - vpCrvs.back()->AddCurve( Release( pCopy)) ; - nI = nNextI ; - nJ = nNextJ ; - } - else { - nI = -1 ; - nJ = -1 ; - } - } - else { - nI = -1 ; - nJ = -1 ; - } - } - return true ; -} - -//---------------------------------------------------------- -bool -PocketingNT::OptimizedZigZag( int nPathId, const Vector3d& vtTool, double dDepth, double dSafeZ, - Frame3d& frPocket, bool& bOptimizedZigZag, ICRVCOMPOPOVECTOR& vpCrvs, double& dOffs) -{ - // recupero la curva originale che delimita la svuotatura - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; - PtrOwner pCrvPocket( CloneCurveComposite( m_pGeomDB->GetGeoObj( nCrvId))) ; - if ( IsNull( pCrvPocket)) - return false ; - pCrvPocket->ToLoc( frPocket) ; - SetCurveAllTempProp( nCrvId, GetForcedClosed(), 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 ; - pCrvPocket->GetArea( plPlane, dArea) ; - if ( plPlane.GetVersN() * vtPocket * dArea < 0) - pCrvPocket->Invert() ; - - // recupero gli id dei lati chiusi - INTVECTOR vnInfoClosed ; - for( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i ++) { - int nProp ; - if ( pCrvPocket->GetCurveTempProp( i, nProp) && nProp == 0) - vnInfoClosed.push_back( i) ; - } - int nClosedSides = vnInfoClosed.size() ; - - // modifico pCrvPocket per poterla passare a CalcZigZag - bool bTwoOpposite ; - Vector3d vtDir ; - switch ( nClosedSides) { - case 0 : - ZigZagOptimizedNoClosedEdges( pCrvPocket, bOptimizedZigZag, vtDir, dOffs) ; - break ; - case 1 : - ZigZagOptimizedOneClosedEdge( pCrvPocket, vnInfoClosed[0], bOptimizedZigZag, vtDir, dOffs) ; - break ; - case 2 : - ZigZagOptimizedTwoClosedEdges( pCrvPocket, vnInfoClosed, bOptimizedZigZag, bTwoOpposite, vtDir, dOffs) ; - break ; - case 3 : - ZigZagOptimizedThreeClosedEdges( pCrvPocket, vnInfoClosed, bOptimizedZigZag, bTwoOpposite, vtDir, dOffs) ; - break ; - default : - bOptimizedZigZag = false ; - break ; - } - - if ( ! bOptimizedZigZag) - return true ; - - // oriento il frame della svuotatura allineando asse X con vtDir - if ( vtDir.IsZero()) - pCrvPocket->GetStartDir( vtDir) ; - double dAng ; - vtDir.GetAngleXY( X_AX, dAng) ; - if ( nClosedSides == 0) - dAng += m_Params.m_dSideAngle ; - pCrvPocket->ToGlob( frPocket) ; - Point3d ptCen = frPocket.Orig() ; - Vector3d vtExtr = frPocket.VersZ() ; - frPocket.Rotate( ptCen, vtExtr, -dAng) ; - pCrvPocket->ToLoc( frPocket) ; - - // calcolo il percorso di svuotatura - if ( ! CalcZigZag( pCrvPocket, vpCrvs)) - return false ; - - // se un lato chiuso - if ( nClosedSides == 1) { - // inverto il percorso - vpCrvs[0]->Invert() ; - // verifico se attacco fuori dal grezzo - Point3d ptStart ; - vpCrvs[0]->GetStartPoint( ptStart) ; - Vector3d vtDir ; - vpCrvs[0]->GetStartDir( vtDir) ; - Point3d ptTest = ptStart + ( -vtDir) * ( m_TParams.m_dDiam / 2 - dOffs + dSafeZ) ; - ptTest.ToGlob( frPocket) ; - ptTest += - vtTool * dDepth ; - double dTestElev ; - // se è nel grezzo provo a ruotare di 90 gradi - if ( GetElevation( m_nPhase, ptTest, vtTool, m_TParams.m_dDiam / 2 - dOffs, vtTool, dTestElev) && dTestElev > EPS_SMALL) { - Vector3d vtDirO = vtDir ; - vtDirO.Rotate( Z_AX, ( m_Params.m_bInvert ? -90 : 90)) ; - Point3d ptTestO = ptStart + vtDirO * ( m_TParams.m_dDiam / 2 - dOffs + dSafeZ) ; - ptTestO.ToGlob( frPocket) ; - ptTestO += - vtTool * dDepth ; - double dTestElevO ; - // se è fuori dal grezzo uso inizio ruotato - if ( ! GetElevation( m_nPhase, ptTestO, vtTool, m_TParams.m_dDiam / 2 - dOffs, vtTool, dTestElevO) || dTestElevO < EPS_SMALL) { - Point3d ptNewStart = ptStart + vtDirO ; - vpCrvs[0]->AddLine( ptNewStart, false) ; - } - } - } - // se due lati chiusi consecutivi o tre lati chiusi... - else if ( ( nClosedSides == 2 || nClosedSides == 3) && ! bTwoOpposite) { - // inverto il percorso - vpCrvs[0]->Invert() ; - // allungo opportunamente inizio e fine - Point3d ptStart ; - vpCrvs[0]->GetStartPoint( ptStart) ; - Vector3d vtDir ; - vpCrvs[0]->GetStartDir( vtDir) ; - vtDir.Rotate( Z_AX, ( m_Params.m_bInvert ? -90 : 90)) ; - ptStart += vtDir ; - Point3d ptEnd ; - vpCrvs[0]->GetEndPoint( ptEnd) ; - ptEnd += OrthoCompo( ptStart - ptEnd, X_AX) ; - vpCrvs[0]->AddLine( ptEnd, true) ; - vpCrvs[0]->AddLine( ptStart, false) ; - } - - // estendo la fine del percorso - if ( ! ( nClosedSides == 3 && bTwoOpposite)) - vpCrvs[0]->ExtendEndByLen( max( m_TParams.m_dDiam / 4 - dOffs, 0.)) ; - - return true ; -} - -//------------------------------------------------------------------ -bool -PocketingNT::ZigZagOptimizedNoClosedEdges( ICurveComposite* pCrvPocket, bool& bOptimizedZigZag, Vector3d& vtDir, double& dOffs) -{ - // individuo il segmento di retta più lungo - int nMax = -1 ; - double dMaxLen = 0 ; - for ( int i = 0 ; i < int( pCrvPocket->GetCurveCount()) ; ++ i) { - const ICurve* pCrv = pCrvPocket->GetCurve( i) ; - if ( pCrv->GetType() == CRV_LINE) { - double dLen = 0 ; pCrv->GetLength( dLen) ; - if ( dLen > dMaxLen) { - dMaxLen = dLen ; - nMax = i ; - } - } - } - if ( nMax == -1) - return true ; - pCrvPocket->GetCurve( nMax)->GetStartDir( vtDir) ; - - // aggiorno pCrvPocket con eventuale offset per regioni residue - if ( ! ZigZagOptimizedComputeOffset( pCrvPocket, vtDir, 0, {}, dOffs)) - return true ; - - bOptimizedZigZag = true ; - return true ; -} - -//------------------------------------------------------------------ -bool -PocketingNT::ZigZagOptimizedOneClosedEdge( ICurveComposite* pCrvPocket, int nClosedId, bool& bOptimizedZigZag, Vector3d& vtDir, double& dOffs) -{ - // verifico che il lato chiuso sia una linea - PtrOwner pCrv( CloneCurveLine( pCrvPocket->GetCurve( nClosedId))) ; - if ( IsNull( pCrv)) - return true ; - - // aggiorno pCrvPocket con eventuale offset per regioni residue - pCrv->GetStartDir( vtDir) ; - if ( ! ZigZagOptimizedComputeOffset( pCrvPocket, vtDir, 1, {nClosedId}, dOffs)) - return true ; - - // setto il vettore estrusione per eseguire correttamente offset - Vector3d vtExtr ; - pCrvPocket->GetExtrusion( vtExtr) ; - pCrv->SetExtrusion( vtExtr) ; - - pCrv->SimpleOffset( -m_TParams.m_dDiam / 2 - GetOffsR() + 10 * EPS_SMALL) ; - pCrv->ExtendStartByLen( 300) ; - pCrv->ExtendEndByLen( 300) ; - - // sarà la prima curva del percorso - if ( ! CutCurveWithLine( pCrvPocket, pCrv)) - return false ; - - bOptimizedZigZag = true ; - return true ; -} - -//------------------------------------------------------------------ -bool -PocketingNT::ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INTVECTOR& vnClosedIds, bool& bOptimizedZigZag, - bool& bOpposite, Vector3d& vtDir, double& dOffs) -{ - // 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)) - return true ; - // verifico abbiano direzioni opposte - Vector3d vtDir1, vtDir2 ; - pCrv1->GetStartDir( vtDir1) ; - pCrv2->GetStartDir( vtDir2) ; - if ( AreOppositeVectorApprox( vtDir1, vtDir2)) - bOpposite = true ; - else { - // verifico siano consecutive - Point3d ptStart1 ; - pCrv1->GetStartPoint( ptStart1) ; - Point3d ptEnd1 ; - pCrv1->GetEndPoint( ptEnd1) ; - Point3d ptStart2 ; - pCrv2->GetStartPoint( ptStart2) ; - Point3d ptEnd2 ; - pCrv2->GetEndPoint( ptEnd2) ; - if ( AreSamePointApprox( ptEnd1, ptStart2) || AreSamePointApprox( ptEnd2, ptStart1)) - bOpposite = false ; - else - return true ; - } - - // setto il vettore estrusione per eseguire correttamente offset - Vector3d vtExtr ; - pCrvPocket->GetExtrusion( vtExtr) ; - pCrv1->SetExtrusion( vtExtr) ; - pCrv2->SetExtrusion( vtExtr) ; - - // determino la curva chiusa più lunga - double dLen1 ; pCrv1->GetLength( dLen1) ; - double dLen2 ; pCrv2->GetLength( dLen2) ; - - // se non opposti, verifico che almeno una delle due sia corta - if ( ! bOpposite && dLen1 > 1.5 * m_TParams.m_dDiam && dLen2 > 1.5 * m_TParams.m_dDiam) - return true ; - - // trovo la direzione principale della svuotatura - if ( dLen1 > dLen2) - pCrv1->GetStartDir( vtDir) ; - else - pCrv2->GetStartDir( vtDir) ; - - // aggiorno pCrvPocket con eventuale offset per regioni residue - if ( ! ZigZagOptimizedComputeOffset( pCrvPocket, vtDir, bOpposite ? 2 : 1, vnClosedIds, dOffs)) - return true ; - - double dMyOffs = m_TParams.m_dDiam / 2 + GetOffsR() - 10 * EPS_SMALL ; - pCrv1->SimpleOffset( -dMyOffs) ; - pCrv1->ExtendStartByLen( 300) ; - pCrv1->ExtendEndByLen( 300) ; - if ( ! CutCurveWithLine( pCrvPocket, pCrv1)) - return false ; - - // sarà la prima curva del percorso - pCrv2->SimpleOffset( -dMyOffs) ; - pCrv2->ExtendStartByLen( 300) ; - pCrv2->ExtendEndByLen( 300) ; - if ( ! CutCurveWithLine( pCrvPocket, pCrv2)) - return false ; - - bOptimizedZigZag = true ; - return true ; -} - -//------------------------------------------------------------------ -bool -PocketingNT::ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const INTVECTOR& vnClosedIds, bool& bOptimizedZigZag, - bool& bOpposite, Vector3d& vtDir, double& dOffs) -{ - // verifico che i lati chiusi siano linee - PtrOwner pCrv1( CloneCurveLine( pCrvPocket->GetCurve( vnClosedIds[0]))) ; - PtrOwner pCrv2( CloneCurveLine( pCrvPocket->GetCurve( vnClosedIds[1]))) ; - PtrOwner pCrv3( CloneCurveLine( pCrvPocket->GetCurve( vnClosedIds[2]))) ; - if ( IsNull( pCrv1) || IsNull( pCrv2) || IsNull( pCrv3)) - return true ; - // verifico siano consecutivi - Point3d ptStart1 ; - pCrv1->GetStartPoint( ptStart1) ; - Point3d ptEnd1 ; - pCrv1->GetEndPoint( ptEnd1) ; - Point3d ptStart2 ; - pCrv2->GetStartPoint( ptStart2) ; - Point3d ptEnd2 ; - pCrv2->GetEndPoint( ptEnd2) ; - Point3d ptStart3 ; - pCrv3->GetStartPoint( ptStart3) ; - Point3d ptEnd3 ; - pCrv3->GetEndPoint( ptEnd3) ; - if ( AreSamePointApprox( ptEnd1, ptStart2) && AreSamePointApprox( ptEnd2, ptStart3)) - ; - else if ( AreSamePointApprox( ptEnd2, ptStart3) && AreSamePointApprox( ptEnd3, ptStart1)) { - swap( pCrv1, pCrv2) ; - swap( pCrv2, pCrv3) ; - } - else if ( AreSamePointApprox( ptEnd3, ptStart1) && AreSamePointApprox( ptEnd1, ptStart2)) { - swap( pCrv1, pCrv3) ; - swap( pCrv3, pCrv2) ; - } - else - return true ; - // calcolo la direzione della svuotatura e verifico che lati non siano troppo lunghi - double dLen1 ; pCrv1->GetLength( dLen1) ; - double dLen2 ; pCrv2->GetLength( dLen2) ; - double dLen3 ; pCrv3->GetLength( dLen3) ; - if ( dLen2 > dLen1 && dLen2 > dLen3) { - if ( dLen1 > 1.5 * m_TParams.m_dDiam || dLen3 > 1.5 * m_TParams.m_dDiam) - return true ; - pCrv2->GetStartDir( vtDir) ; - bOpposite = false ; - } - else { - if ( dLen2 > 1.5 * m_TParams.m_dDiam) - return true ; - pCrv3->GetStartDir( vtDir) ; - bOpposite = true ; - } - - // aggiorno pCrvPocket con eventuale offset per regioni residue - if ( ! ZigZagOptimizedComputeOffset( pCrvPocket, vtDir, 1, vnClosedIds, dOffs)) - return true ; - - // setto il vettore estrusione per eseguire correttamente offset - Vector3d vtExtr ; - pCrvPocket->GetExtrusion( vtExtr) ; - pCrv1->SetExtrusion( vtExtr) ; - pCrv2->SetExtrusion( vtExtr) ; - pCrv3->SetExtrusion( vtExtr) ; - - double dMyOffs = m_TParams.m_dDiam / 2 + GetOffsR() - 10 * EPS_SMALL ; - pCrv1->SimpleOffset( -dMyOffs) ; - pCrv1->ExtendStartByLen( 300) ; - pCrv1->ExtendEndByLen( 300) ; - if ( ! CutCurveWithLine( pCrvPocket, pCrv1)) - return false ; - - pCrv3->SimpleOffset( -dMyOffs) ; - pCrv3->ExtendStartByLen( 300) ; - pCrv3->ExtendEndByLen( 300) ; - if ( ! CutCurveWithLine( pCrvPocket, pCrv3)) - return false ; - - // sarà la prima curva del percorso - pCrv2->SimpleOffset( -dMyOffs) ; - pCrv2->ExtendStartByLen( 300) ; - pCrv2->ExtendEndByLen( 300) ; - if ( ! CutCurveWithLine( pCrvPocket, pCrv2)) - return false ; - - bOptimizedZigZag = true ; - return true ; -} - -//------------------------------------------------------------------ - bool - PocketingNT::ZigZagOptimizedComputeOffset( ICurveComposite* pCrvPocket, const Vector3d& vtMainDir, int nOffsettedEdgesOnY, - const INTVECTOR& vnClosedIds, double& dOffs) - { - // calcolo il side step che verrà utilizzato in CalcZigZag - Frame3d frLoc ; - if ( ! frLoc.Set( ORIG, Z_AX, vtMainDir)) - return true ; - BBox3d b3Loc ; - pCrvPocket->ToLoc( frLoc) ; - pCrvPocket->GetLocalBBox( b3Loc) ; - pCrvPocket->ToGlob( frLoc) ; - Point3d pt ; - double dDimX, dDimY, dDimZ ; - b3Loc.GetMinDim( pt, dDimX, dDimY, dDimZ) ; - // riduco la DimY della svuotatura in base al numero di lati chiusi che saranno offsettati lungo quella direzione - dDimY -= nOffsettedEdgesOnY * ( 0.5 * m_TParams.m_dDiam + GetOffsR()) ; - int nYStep = static_cast( ceil( ( dDimY - 30 * EPS_SMALL) / GetSideStep())) ; - double dYSideStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ; - - // 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 nPrev = vnClosedIds[i] == 0 ? pCrvPocket->GetCurveCount() - 1 : vnClosedIds[i] - 1 ; - pCrvPocket->SetCurveTempProp( nNext, 1, 1) ; - pCrvPocket->SetCurveTempProp( nPrev, 1, 1) ; - } - - // verifico se resteranno aree residue e calcolo eventuale offset per pCrvPocket - dOffs = 0 ; - for ( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i ++) { - - double dOffsTmp = 0 ; - double dVal = 0 ; - - if ( pCrvPocket->GetCurve(i)->GetType() == CRV_LINE) { - Vector3d vtDir ; - if ( ! pCrvPocket->GetCurve( i)->GetStartDir( vtDir)) - return false ; - - int nProp ; - pCrvPocket->GetCurveTempProp( i, nProp, 1) ; - double dLen ; - pCrvPocket->GetCurve( i)->GetLength( dLen) ; - - if ( nProp == 1 && dLen > 1000 * EPS_SMALL) { - // gestione speciale se vicino al lato closed - double dCosAlpha = vtMainDir * vtDir ; - if ( abs( dCosAlpha) > EPS_SMALL && abs( dCosAlpha) < 1 - EPS_SMALL) - dOffsTmp = abs( 0.5 * m_TParams.m_dDiam * dCosAlpha) ; - } - else { - double dSinAlpha = ( vtMainDir ^ vtDir).Len() ; - if ( abs( dSinAlpha) > EPS_SMALL) - dVal = ( dYSideStep - 0.5 * m_TParams.m_dDiam) / dSinAlpha - 0.5 * m_TParams.m_dDiam ; - if ( dVal > EPS_SMALL) { - double dCosAlpha = vtMainDir * vtDir ; - dOffsTmp = abs( ( dYSideStep - 0.5 * m_TParams.m_dDiam) * dCosAlpha) ; - } - } - } - if ( dOffsTmp > dOffs) - dOffs = dOffsTmp ; - } - - // aggiusto offset - double dMinOffs = max( 0., 0.5 * m_TParams.m_dDiam - m_Params.m_dSideStep) ; - dOffs = max( dOffs, dMinOffs) ; - - if ( dOffs > EPS_SMALL) { - // calcolo offset - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCrvPocket, dOffs, ICurve::OFF_EXTEND)) { - m_pMchMgr->SetLastError( 2412, "Error in PocketingNT : Offset not computable") ; - return false ; - } - if ( OffsCrv.GetCurveCount() > 1) - return false ; - - // aggiorno pCrvPocket - pCrvPocket->Clear() ; - pCrvPocket->AddCurve( OffsCrv.GetCurve()) ; - } - - return true ; - } - -//------------------------------------------------------------------ -bool PocketingNT::CutCurveWithLine( ICurveComposite* pCrvA, const ICurveLine* pCrvB) { IntersCurveCurve IntersCC( *pCrvA, *pCrvB) ; @@ -3041,1829 +2872,6 @@ PocketingNT::CutCurveWithLine( ICurveComposite* pCrvA, const ICurveLine* pCrvB) return true ; } -//---------------------------------------------------------------------------- -bool -PocketingNT::AddOneWay( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs) -{ - // recupero distanze di sicurezza - double dSafeZ = GetSafeZ() ; - double dSafeAggrBottZ = 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 - if ( m_TParams.m_nType == TT_MILL_NOTIP) { - if ( ! LeadInRawIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in PocketingNT : 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 ; - - // 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 PocketingNT : Offset not computable") ; - return false ; - } - - // ciclo sulle curve risultanti - while ( OffsCrv.GetCurveCount() > 0) { - - // recupero la prima curva di offset - PtrOwner pOffs ; - if ( ! pOffs.Set( ConvertCurveToComposite( OffsCrv.GetLongerCurve()))) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - - // se richiesto, la inverto - if ( m_Params.m_bInvert) - pOffs->Invert() ; - - // sposto l'inizio a metà del tratto più lungo - AdjustContourStart( pOffs) ; - - // se necessario, approssimo con rette - if ( bSplitArcs) { - if ( ! ApproxWithLines( pOffs)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - } - // altrimenti verifico archi - else - VerifyArcs( pOffs) ; - - // 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 ; - // 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) - 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 + LIO_ELEV_TOL) ; - dStElev = -LIO_ELEV_TOL ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs, false)) { - m_pMchMgr->SetLastError( 2414, "Error in PocketingNT : 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 PocketingNT : 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 PocketingNT : Link not computable") ; - return false ; - } - } - } - // elaborazioni sulla curva corrente - if ( pCurve->GetType() == CRV_LINE) { - ICurveLine* pLine = GetCurveLine( pCurve) ; - Point3d ptP3 = pLine->GetEnd() ; - SetFeed( dFeedRid * GetFeed()) ; - if ( AddLinearMove( ptP3, bSplitArcs) == 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 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, false, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : LeadOut not computable") ; - return false ; - } - // aggiungo retrazione - if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : 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 PocketingNT : Offset not computable") ; - return false ; - } - - // ciclo sulle curve risultanti - while ( OffsCrv2.GetCurveCount() > 0) { - - PtrOwner pOffs2 ; - if ( ! pOffs2.Set( ConvertCurveToComposite( OffsCrv2.GetLongerCurve()))) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - - // determino il riferimento di base e il box della svuotatura - Frame3d frPocket ; - Point3d ptCen ; pCompo->GetCentroid( ptCen) ; - frPocket.Set( ptCen, vtExtr) ; - frPocket.Rotate( ptCen, vtExtr, m_Params.m_dSideAngle) ; - pOffs2->ToLoc( frPocket) ; - BBox3d b3Pocket ; - pOffs2->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())) ; - double dYStep = ( nYStep > 0 ? ( dDimY + 2 * dExtra) / nYStep : 0) ; - -- 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 - 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)) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : 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 PocketingNT : 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw) - dStElev = max( dStElev, j * dStep) ; - dStElev -= ( ptP - ptS) * vtExtr ; - // sempre approccio di collegamento - if ( ! AddLinkApproach( ptP, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : 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 PocketingNT : 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, bSplitArcs) == GDB_ID_NULL) - return false ; - // risalita - Point3d ptQ ; - double dEndElev = dElev ; - SetFeed( GetEndFeed()) ; - if ( ! AddLeadOut( ptE, frPocket.VersX(), vtExtr, nullptr, bSplitArcs, true, ptQ, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : 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, bSplitArcs)) { - m_pMchMgr->SetLastError( 2417, "Error in PocketingNT : Retract not computable") ; - return false ; - } - } - // altrimenti aggiungo retrazione di collegamento - else { - if ( ! AddLinkRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2418, "Error in PocketingNT : Link not computable") ; - return false ; - } - } - } - } - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::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) -{ - // recupero distanze di sicurezza - double dSafeZ = GetSafeZ() ; - double dSafeAggrBottZ = GetSafeAggrBottZ() ; - // 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 PocketingNT : toolpath allocation failed") ; - 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 PocketingNT : Toolpath not computable") ; - 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 PocketingNT : 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 + max( dSafeZ, m_dOpenMinSafe)) ; - // 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) ; - } - } - - // 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 = ( bMidOpen && 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 ( ! LeadInRawIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in PocketingNT : 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 ; - // 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) - 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 + LIO_ELEV_TOL) ; - dStElev = -LIO_ELEV_TOL ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs, bOutStart || bForcedOutStart)) { - m_pMchMgr->SetLastError( 2414, "Error in PocketingNT : 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 PocketingNT : 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 PocketingNT : 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, bSplitArcs) == 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 ; - } - } - // 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, false, ptP1, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : LeadOut not computable") ; - return false ; - } - // aggiungo retrazione - if ( ! AddRetract( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2417, "Error in PocketingNT : Retract not computable") ; - return false ; - } - } - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::AddSpiralOut( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr, - double dDepth, double dElev, double dOkStep, bool bSplitArcs, int nPathId) -{ - // recupero distanze di sicurezza - double dSafeZ = GetSafeZ() ; - double dSafeAggrBottZ = GetSafeAggrBottZ() ; - // 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'interno all'esterno - PtrOwner pMCrv( CreateCurveComposite()) ; - PtrOwner pRCrv( CreateCurveComposite()) ; - if ( IsNull( pMCrv) || IsNull( pRCrv)) { - m_pMchMgr->SetLastError( 2411, "Error in PocketingNT : toolpath allocation failed") ; - 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 PocketingNT : Toolpath not computable") ; - 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 PocketingNT : 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 ( ! LeadInRawIsOk()) { - m_pMchMgr->SetLastError( 2431, "Error in PocketingNT : 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 ; - // 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 PocketingNT : 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 bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtTool, dStElev) ; - if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) - 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 + LIO_ELEV_TOL) ; - dStElev = -LIO_ELEV_TOL ; - } - // approccio al punto iniziale - if ( ! AddApproach( ptP1, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, bSplitArcs, false)) { - m_pMchMgr->SetLastError( 2414, "Error in PocketingNT : 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 PocketingNT : 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 PocketingNT : 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, bSplitArcs) == 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 ; - } - } - // 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, false, ptQ, dEndElev)) { - m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : LeadOut not computable") ; - return false ; - } - // aggiungo retrazione - if ( ! AddRetract( ptQ, vtTool, dSafeZ, dSafeAggrBottZ, dEndElev, dAppr, bSplitArcs)) { - m_pMchMgr->SetLastError( 2417, "Error in PocketingNT : Retract not computable") ; - return false ; - } - } - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, - ICurveComposite* pMCrv, ICurveComposite* pRCrv, int nPathId, bool& bOptimizedTrap) -{ - // inizializzo i risultati - pMCrv->Clear() ; - pRCrv->Clear() ; - - // primo offset pari al raggio utensile + sovramateriale - 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 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 ; - bool bSomeOpen ; - SetCurveAllTempProp( nCrvId, GetForcedClosed(), pCrvPocket, &bSomeOpen) ; - 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() ; - double dMaxOptSize = m_Params.m_dSideStep ; - FromString( ExtractInfo( m_Params.m_sUserNotes, "MaxOptSize="), dMaxOptSize) ; - if ( ( ( bSomeOpen && dPocketSize < m_TParams.m_dDiam + EPS_SMALL) || abs( dPocketSize - m_TParams.m_dDiam) < EPS_SMALL) && - dPocketSize < dMaxOptSize + 10 * EPS_SMALL) { - if ( nReg == 0) { - CalcTrapezoidSpiral( pCrvPocket, vtDir, dPocketSize, pMCrv, pRCrv, bOptimizedTrap) ; - 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) ; - while ( nIter < MAX_ITER) { - // se l'offset richiesto è pari al valore limite per la curva ne modifico leggermente il valore per evitare problemi con - // le tolleranze di vroni - double dMaxOffs ; - if ( nIter == 0) - CalcCurveLimitOffset( *pCompo, dMaxOffs) ; - else - CalcCurveLimitOffset( *pOffs, dMaxOffs) ; - if ( dOffs > dMaxOffs - 10 * EPS_ZERO && dOffs < dMaxOffs + EPS_SMALL) - dOffs = dMaxOffs - 10 * EPS_ZERO ; - - // 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 PocketingNT : Offset not computable") ; - return false ; - } - // 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 ; - } - else - delete( pCrv) ; - pCrv = OffsCrv.GetCurve() ; - ++ nCount ; - } - // recupero la prossima curva di offset - PtrOwner pNextOffs ; - if ( ! vCrvStack.empty()) { - pNextOffs.Set( 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( pNextOffs) ; - // nuovo valore pari allo step - 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 - break ; - // incremento contatore iterazioni - ++ nIter ; - } - - // calcolo i collegamenti - 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( pCrvLink) ; - else { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - 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) ; - // calcolo il ritorno (garantendo che non esca dalla svuotatura) - PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) { - pRCrv->AddCurve( Release( pCrvLink)) ; - pRCrv->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false) ; - // se necessario, approssimo archi con rette - if ( bSplitArcs && ! ApproxWithLines( pRCrv)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - VerifyArcs( pRCrv) ; - } - else { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - } - - // 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 ( m_TParams.m_nType == TT_MILL_POLISHING) { - for ( int j = nCrvsCount0 ; j < pMCrv->GetCurveCount() ; j ++) - pMCrv->SetCurveTempProp( j, LINK_CURVE_PROP) ; - } - } - // se richiesta percorrenza invertita - if ( m_Params.m_bInvert) - vOffs[i]->Invert() ; - // aggiungo la curva - pMCrv->AddCurve( Release( vOffs[i])) ; - } - - // verifico il percorso di lavoro - if ( pMCrv->GetCurveCount() == 0) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - // se necessario, approssimo archi con rette - if ( bSplitArcs && ! ApproxWithLines( pMCrv)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - // eventuale sistemazione archi - VerifyArcs( pMCrv) ; - - // setto estrusione - Vector3d vtExtr ; - if ( pCompo->GetExtrusion( vtExtr)) - pMCrv->SetExtrusion( vtExtr) ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::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) ; - - // 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)) ; - return true ; - } - // altrimenti combino i tratti interni di retta con tratti opportuni della curva di contenimento - else { - PtrOwner pCompo( CreateCurveComposite()) ; - if ( IsNull( pCompo)) - 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)) - return false ; - double dLenA ; pCrvA->GetLength( dLenA) ; - double dLenB ; pCrvB->GetLength( dLenB) ; - if ( dLenA < dLenB) { - pCompo->AddCurve( Release( pCrvA)) ; - } - else { - pCrvB->Invert() ; - pCompo->AddCurve( Release( pCrvB)) ; - } - } - } - pCrvLink->AddCurve( Release( pCompo)) ; - return true ; - } -} - -//------------------------------------------------------------------------------ -bool -PocketingNT::CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, - const ICurve* pCrvBound, ICurveComposite* pCrvLink) -{ - double dAngStart, dAngEnd ; - vtStart.GetAngleXY( X_AX, dAngStart) ; - vtEnd.GetAngleXY( X_AX, dAngEnd) ; - PtrOwner pBiArcLink( GetBiArc( ptStart, -dAngStart, ptEnd, -dAngEnd, 0.5)) ; - if ( IsNull( pBiArcLink)) - return false ; - - // verifico se esce dalla svuotatura - CRVCVECTOR ccClass ; - IntersCurveCurve intCC( *pBiArcLink, *pCrvBound) ; - intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; - // 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)) ; - } - // altrimenti creo un percorso con biarchi e opportuni tratti della curva di contenimento - else { - PtrOwner pCompo( CreateCurveComposite()) ; - if ( IsNull( pCompo)) - return false ; - - double dPar1, dPar2 ; - Point3d ptMinDist1, ptMinDist2 ; - Vector3d vtDir1, vtDir2 ; - double dAng1, dAng2 ; - int nFlag ; - - DistPointCurve distPtSCrv( ptStart, *pCrvBound) ; - distPtSCrv.GetParamAtMinDistPoint( 0, dPar1, nFlag) ; - pCrvBound->GetPointTang( dPar1, ICurve::FROM_MINUS, ptMinDist1, vtDir1) ; - vtDir1.GetAngleXY( X_AX, dAng1) ; - - DistPointCurve distPtECrv( ptEnd, *pCrvBound) ; - distPtECrv.GetParamAtMinDistPoint( 0, dPar2, nFlag) ; - pCrvBound->GetPointTang( dPar2, ICurve::FROM_MINUS, ptMinDist2, vtDir2) ; - vtDir2.GetAngleXY( X_AX, dAng2) ; - - pCompo->AddCurve( GetBiArc( ptStart, -dAngStart, ptMinDist1, -dAng1, 0.5)) ; // primo biarco - pCompo->AddCurve( pCrvBound->CopyParamRange( dPar1, dPar2)) ; // tratto di pCrvBound - pCompo->AddCurve( GetBiArc( ptMinDist2, -dAng2, ptEnd, -dAngEnd, 0.5)) ; // secondo biarco - - pCrvLink->AddCurve( Release( pCompo)) ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad, - bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) -{ - // raggio della circonferenza esterna - if ( dOutRad < 10 * EPS_SMALL) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - - // imposto versore estrusione sulle curve composite - pMCrv->SetExtrusion( vtN) ; - pRCrv->SetExtrusion( vtN) ; - - // creo e inserisco la circonferenza esterna - PtrOwner pArc( CreateCurveArc()) ; - if ( IsNull( pArc) || ! pArc->Set( ptCen, vtN, dOutRad)) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - Vector3d vtDir = pArc->GetStartVersor() ; - pMCrv->AddCurve( Release( pArc)) ; - // se richiesta percorrenza invertita - if ( m_Params.m_bInvert) - pMCrv->Invert() ; - - // se raggio esterno maggiore dell'interno - if ( dOutRad > dIntRad + 10 * EPS_SMALL) { - - // aggiungo le semicirconferenze della spirale ( devono essere in numero dispari) - int nStep = int( ceil( ( dOutRad - dIntRad) / ( 0.5 * GetSideStep()))) ; - if ( IsEven( nStep)) - nStep += 1 ; - double dStep = ( dOutRad - dIntRad) / nStep ; - for ( int i = 1 ; i <= nStep ; ++ i) { - if ( ! IsEven( i)) - pMCrv->AddArcTg( ptCen - vtDir * ( dOutRad - i * dStep)) ; - else - pMCrv->AddArcTg( ptCen + vtDir * ( dOutRad - i * dStep)) ; - } - - // aggiungo la circonferenza interna - pMCrv->AddArcTg( ptCen + vtDir * dIntRad) ; - pMCrv->AddArcTg( ptCen - vtDir * dIntRad) ; - } - - // verifico il percorso di lavoro - if ( pMCrv->GetCurveCount() == 0) { - m_pMchMgr->SetLastError( 2413, "Error in PocketingNT : Toolpath not computable") ; - return false ; - } - // se necessario, approssimo con rette - if ( bSplitArcs && ! ApproxWithLines( pMCrv)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - // eventuale sistemazione archi - VerifyArcs( pMCrv) ; - - // calcolo l'eventuale percorso di ritorno - Point3d ptStart ; pMCrv->GetStartPoint( ptStart) ; - Point3d ptEnd ; pMCrv->GetEndPoint( ptEnd) ; - Vector3d vtStart ; pMCrv->GetStartDir( vtStart) ; - if ( ! AreSamePointApprox( ptStart, ptEnd)) { - PtrOwner pArc2( CreateCurveArc()) ; - if ( IsNull( pArc2) || ! pArc2->Set2PVN( ptStart, ptEnd, - vtStart, vtN)) { - m_pMchMgr->SetLastError( 2420, "Error in PocketingNT : Return toolpath not computable") ; - return false ; - } - pRCrv->AddCurve( Release( pArc2)) ; - // inverto - pRCrv->Invert() ; - // se necessario, approssimo con rette - if ( bSplitArcs && ! ApproxWithLines( pRCrv)) { - m_pMchMgr->SetLastError( 2419, "Error in PocketingNT : Linear Approx not computable") ; - return false ; - } - // eventuale sistemazione archi - VerifyArcs( pRCrv) ; - } - - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtDir, double dPocketSize, - ICurveComposite* pMCrv, ICurveComposite* pRCrv, bool& bOptimizedTrap) -{ - bOptimizedTrap = false ; - - Vector3d vtExtr ; pCrvPocket->GetExtrusion( vtExtr) ; - // eventuale approssimazione della curva con polyline per ottenere la stessa curva calcolata in ICurveComposite::IsATrapezoid - if ( pCrvPocket->GetCurveCount() > 4) { - PolyLine PL ; - if ( ! pCrvPocket->ApproxWithLines( 100 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) - return false ; - pCrvPocket->Clear() ; - pCrvPocket->FromPolyLine( PL) ; - pCrvPocket->SetExtrusion( vtExtr) ; - } - - // sistemo senso antiorario visto dalla direzione di estrusione - Plane3d plPlane ; double dArea ; - pCrvPocket->GetArea( plPlane, dArea) ; - if ( plPlane.GetVersN() * vtExtr * dArea < 0) - pCrvPocket->Invert() ; - - // passo in un sistema di riferimento locale avente asse X allineato con uno dei due lati paralleli (possibilmente aperto) e centro nel - // punto iniziale del lato - Frame3d frLoc ; - if ( ! CalcTrapezoidSpiralLocalFrame( pCrvPocket, vtDir, frLoc)) - return false ; - pCrvPocket->ToLoc( frLoc) ; - - // recupero flag aperto/chiuso dei lati (0=chiuso, 1=aperto) - INTVECTOR vnProp( 4, 0) ; - for ( int i = 0 ; i < 4 ; i++) - pCrvPocket->GetCurveTempProp( i, vnProp[i]) ; - - // verifico le dimensioni della svuotatura - double dLen0 = 0, dLen2 = 0 ; - pCrvPocket->GetCurve( 0)->GetLength( dLen0) ; - pCrvPocket->GetCurve( 2)->GetLength( dLen2) ; - if ( vnProp[0] == 0 && abs( dPocketSize - m_TParams.m_dDiam) > EPS_SMALL) - return false ; - if ( vnProp[1] == 0 && vnProp[3] == 0) { - if ( dLen0 < m_TParams.m_dDiam - EPS_SMALL || dLen2 < m_TParams.m_dDiam - EPS_SMALL) - return false ; - } - - // calcolo la larghezza massima della svuotatura (riferimento con X parallelo a primo lato chiuso) - Point3d ptOrig ; - pCrvPocket->GetCurve( 1)->GetStartPoint( ptOrig) ; - Vector3d vtX ; - pCrvPocket->GetCurve( 1)->GetStartDir( vtX) ; - Frame3d frDim ; frDim.Set( ptOrig, Z_AX, vtX) ; frDim.Invert() ; - BBox3d b3Dim ; - pCrvPocket->GetBBox( frDim, b3Dim, BBF_EXACT) ; - 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 - 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)) { - pMCrv->Clear() ; - return false ; - } - } - else { - double dYCoord = dPocketSize - 0.5 * m_TParams.m_dDiam ; - 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 - - double dXCoordStart, dXCoordEnd ; - if ( ! CalcTrapezoidSpiralXCoord( pCrvPocket, true, dYCoord, dXCoordStart, dPocketSize)) - return false ; - if ( ! CalcTrapezoidSpiralXCoord( pCrvPocket, false, dYCoord, dXCoordEnd, dPocketSize)) - return false ; - if ( dXCoordStart > dXCoordEnd + 500 * EPS_SMALL) - return false ; - Point3d ptStart( dXCoordStart, dYCoord) ; - Point3d ptEnd( dXCoordEnd, dYCoord) ; - - if ( AreSamePointEpsilon( ptStart, ptEnd, 500 * EPS_SMALL) && vnProp[0] != 0) { - 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 - if ( AreOppositeVectorApprox( vtDir1, vtDir3)) { - PtrOwner pLine1( GetCurveLine( pCrvPocket->GetCurve( 1)->Clone())) ; - PtrOwner pLine3( GetCurveLine( pCrvPocket->GetCurve( 3)->Clone())) ; - if ( IsNull( pLine1) || IsNull( pLine3)) - return true ; - if ( ! pLine1->SimpleOffset( - 0.5 * m_TParams.m_dDiam - GetOffsR()) || - ! pLine3->SimpleOffset( - 0.5 * m_TParams.m_dDiam - GetOffsR())) - return true ; - - Point3d ptS, ptE ; - if ( vtDir3 * X_AX > EPS_SMALL) { - pLine1->GetStartPoint( ptS) ; - pLine3->GetStartPoint( ptE) ; - } - else { - pLine1->GetEndPoint( ptE) ; - pLine3->GetEndPoint( ptS) ; - } - - pMCrv->AddPoint( ptS) ; - if ( vnProp[2] != 0) - pMCrv->AddLine( ptE) ; - else - pMCrv->AddLine( ptStart) ; - - pMCrv->SetCurveTempProp( 0, 1) ; - } - } - else { - if ( ! pMCrv->AddPoint( ptStart)) - return true ; - if ( ! pMCrv->AddLine( ptEnd)) - return true ; - - // aggiustamenti al percorso per rimuovere materiale residuo negli angoli - if ( vnProp[0] != 0) { - if ( vnProp[3] == 0 && ! AdjustTrapezoidSpiralForAngles( pMCrv, pCrvPocket, true)) { - pMCrv->Clear() ; - return false ; - } - if ( vnProp[1] == 0 && ! AdjustTrapezoidSpiralForAngles( pMCrv, pCrvPocket, false)) { - pMCrv->Clear() ; - return false ; - } - } - } - } - - if ( pMCrv->GetCurveCount() == 0) - return true ; - - 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 - swap( vnProp[1], vnProp[3]) ; - } - // segno i lati aperti come temp prop della curva - int nOpenEdges = vnProp[0] + vnProp[1] * 2 + vnProp[3] * 8 ; - pMCrv->SetTempProp( nOpenEdges, 0) ; - pMCrv->SetExtrusion( vtExtr) ; - - bOptimizedTrap = true ; - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::CalcTrapezoidSpiralLocalFrame( ICurveComposite* pCrvPocket, const Vector3d& vtDir, Frame3d& frLoc) -{ - // cerco i lati paralleli a vtDir - int nBaseId = -1 ; - for ( int i = 0 ; i < pCrvPocket->GetCurveCount() ; i ++) { - Vector3d vtEdge ; - pCrvPocket->GetCurve( i)->GetStartDir( vtEdge) ; - if ( AreSameOrOppositeVectorApprox( vtEdge, vtDir)) { - nBaseId = i ; - break ; - } - } - if ( nBaseId != 0 && nBaseId != 1) - return false ; - - // imposto come lato iniziale per la curva uno dei lati paralleli a vtDir (possibilmente aperto) - int nProp0, nProp2 ; - pCrvPocket->GetCurveTempProp( nBaseId, nProp0) ; - pCrvPocket->GetCurveTempProp( nBaseId + 2, nProp2) ; - if ( nProp0 == 0 && nProp2 != 0) - pCrvPocket->ChangeStartPoint( nBaseId + 2) ; - else - pCrvPocket->ChangeStartPoint( nBaseId) ; - - Point3d ptOrig ; - pCrvPocket->GetStartPoint( ptOrig) ; - Vector3d vtExtr ; - pCrvPocket->GetExtrusion( vtExtr) ; - Vector3d vtX ; - pCrvPocket->GetStartDir( vtX) ; - return frLoc.Set( ptOrig, vtExtr, vtX) ; -} - -//------------------------------------------------------ -bool -PocketingNT::CalcTrapezoidSpiralXCoord( const ICurveComposite* pCrvPocket, bool bStart, double dYCoord, double& dXCoord, double dPocketSize) -{ - // se open - int nCrvId = ( bStart ? 3 : 1) ; - int nProp ; - if ( pCrvPocket->GetCurveTempProp( nCrvId, nProp) && nProp != 0) { - Point3d pt1, pt2 ; - pCrvPocket->GetCurve( nCrvId)->GetStartPoint( pt1) ; - pCrvPocket->GetCurve( nCrvId)->GetEndPoint( pt2) ; - if ( bStart) - dXCoord = min( pt1.x, pt2.x) ; - else - dXCoord = max( pt1.x, pt2.x) ; - } - // se closed - else { - double dRad = 0.5 * m_TParams.m_dDiam + GetOffsR() ; - double dVal ; - Vector3d vtRef ; - pCrvPocket->GetCurve( nCrvId)->GetStartDir( vtRef) ; - double dCosAlpha = vtRef * X_AX ; - - if ( dRad * dCosAlpha < dYCoord && dYCoord < dPocketSize + dRad * dCosAlpha) { - double dSinAlpha = ( vtRef ^ X_AX).Len() ; - if ( abs( dSinAlpha) < EPS_SMALL) - return false ; - dVal = 1.0 / dSinAlpha * ( dRad - dYCoord * dCosAlpha) ; - } - else if ( dYCoord < dRad * dCosAlpha) - dVal = sqrt( dRad * dRad - dYCoord * dYCoord) ; - else { - double dLen ; - pCrvPocket->GetCurve( nCrvId)->GetLength( dLen) ; - dVal = - dLen * dCosAlpha + sqrt( dRad * dRad - dYCoord * dYCoord) ; - } - - Point3d ptRef ; - if ( bStart) { - pCrvPocket->GetCurve( nCrvId)->GetEndPoint( ptRef) ; - dXCoord = ptRef.x + dVal ; - } - else { - pCrvPocket->GetCurve( nCrvId)->GetStartPoint( ptRef) ; - dXCoord = ptRef.x - dVal ; - } - } - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveComposite* pCrvPocket, bool bStart) -{ - PtrOwner pCompo( CreateCurveComposite()) ; - if ( ! bStart) - pMCrv->Invert() ; - - Point3d ptTmp ; - pMCrv->GetStartPoint( ptTmp) ; - double dYCoord = ptTmp.y ; // quota verticale del percorso di svuotatura - pCrvPocket->GetCurve( 2)->GetStartPoint( ptTmp) ; - double dPocketSize = ptTmp.y ; - - int nCrvId = ( bStart ? 3 : 1) ; - PtrOwner pLine( GetCurveLine( pCrvPocket->GetCurve( nCrvId)->Clone())) ; - pLine->SimpleOffset( - 0.5 * m_TParams.m_dDiam - GetOffsR()) ; - - Point3d ptP1, ptP2 ; - pLine->GetStartPoint( ptP1) ; - pLine->GetEndPoint( ptP2) ; - if ( ! bStart) - swap( ptP1, ptP2) ; - - int nProp2 ; - // lato opposto a quello di riferimento aperto - if ( pCrvPocket->GetCurveTempProp( 2, nProp2) && nProp2 != 0) { - - // caso 1 : pLine ha un estremo sopra e uno sotto il percorso di svuotatura pMCrv - if ( ptP2.y < dYCoord && dYCoord < ptP1.y) { - - // creo tratto da ptP2 a ptP1 - pCompo->AddPoint( ptP2) ; - pCompo->AddLine( ptP1) ; - - // trovo il punto di pMCrv da cui ripartire per non lasciare aree residue - pLine->SimpleOffset( - 0.5 * m_TParams.m_dDiam) ; - pLine->ExtendStartByLen( EPS_SMALL) ; - pLine->ExtendEndByLen( EPS_SMALL) ; - IntersCurveCurve intCC( *pLine, *pCrvPocket) ; - if ( intCC.GetIntersCount() == 0) - return false ; - IntCrvCrvInfo aInfo ; - intCC.GetIntCrvCrvInfo( 0, aInfo) ; - double dDeltaX = sqrt( m_TParams.m_dDiam * m_TParams.m_dDiam / 4 - dYCoord * dYCoord) ; - if ( ! bStart) - dDeltaX *= -1 ; - Point3d ptCrv( aInfo.IciA[0].ptI.x + dDeltaX, dYCoord) ; - - double dPar = 0 ; - if ( ! pMCrv->GetParamAtPoint( ptCrv, dPar)) { - dPar = 0.5 ; - pMCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptCrv) ; - } - 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) - swap( ptP1, ptP2) ; - pCompo->Invert() ; - } - - // creo biarco fra ptP1 e ptCrv - Vector3d vtDir ; - pCompo->GetStartDir( vtDir) ; - double dAng ; - vtDir.GetAngleXY( X_AX, dAng) ; - PtrOwner pBiArc( GetBiArc( ptP1, - dAng, ptCrv, bStart ? 0 : 180, 0.8)) ; - - bool bUseBiArc = false ; - if ( ! IsNull( pBiArc)) { - // verifico che con il biarco non si oltrepassi il lato obliquo chiuso della svuotatura - IntersCurveCurve intCC2( *pBiArc, *pCompo) ; - if ( intCC2.GetIntersCount() == 1) - bUseBiArc = true ; - } - if ( bUseBiArc) - pCompo->AddCurve( Release( pBiArc)) ; - else { - double dParLine = ( dYCoord - ptP2.y) / ( ptP1.y - ptP2.y) ; - Point3d ptOnLine = Media( ptP2, ptP1, dParLine) ; - pCompo->AddLine( ptOnLine) ; - pCompo->AddLine( ptCrv) ; - } - } - - // caso 2 : pLine è completamente sopra/sotto la linea di svuotatura - else { - // se è sopra modifiche per ricondurmi al caso in cui è sotto - if ( ptP2.y > dYCoord) { - pLine->Invert() ; - swap( ptP1, ptP2) ; - } - - // trovo l'intersezione fra il prolungamento della linea e pMCrv - if ( bStart) - pLine->ExtendStartByLen( 1000) ; - else - pLine->ExtendEndByLen( 1000) ; - IntersCurveCurve intCC ( *pLine, *pMCrv) ; - if ( intCC.GetIntersCount() == 0) - return false ; - IntCrvCrvInfo aInfo ; - intCC.GetIntCrvCrvInfo( 0, aInfo) ; - Point3d ptInt ; - ptInt = aInfo.IciA[0].ptI ; - double dPar = 0 ; - pMCrv->GetParamAtPoint( ptInt, dPar) ; - pMCrv->TrimStartAtParam( dPar) ; - - pCompo->AddPoint( ptP2) ; - pCompo->AddLine( ptInt) ; - } - } - - // se il lato opposto a quello di riferimento è chiuso bisogna distinguere i casi - else { - bool bStartPnt = false ; - if ( ptP2.y < dYCoord) { - bStartPnt = pCompo->AddPoint( ptP2) ; - } - else { - Vector3d vtDir ; - pLine->GetStartDir( vtDir) ; - if ( bStart) - vtDir.Invert() ; - Point3d ptP2N = ptP2 - m_TParams.m_dDiam / 2 * abs( vtDir.x / vtDir.y) * vtDir ; - if ( ptP2N.y < dYCoord) - bStartPnt = pCompo->AddPoint( ptP2N) ; - } - if ( bStartPnt) { - Point3d ptCrv ; - pMCrv->GetStartPoint( ptCrv) ; - pCompo->AddLine( ptCrv) ; - } - } - - // setto temp prop per ricordare che è curva aggiuntiva per pulire angoli - for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) - pCompo->SetCurveTempProp( i, 1) ; - - pMCrv->AddCurve( Release( pCompo), false) ; - if ( ! bStart) - pMCrv->Invert() ; // ripristino la direzione originaria - - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::SpecialAdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveComposite* pCrvPocket) -{ - // calcolo gli offset dei lati obliqui - PtrOwner pLineS( GetCurveLine( pCrvPocket->GetCurve( 3)->Clone())) ; - pLineS->SimpleOffset( - 0.5 * m_TParams.m_dDiam - GetOffsR()) ; - pLineS->Invert() ; - PtrOwner pLineE( GetCurveLine( pCrvPocket->GetCurve( 1)->Clone())) ; - pLineE->SimpleOffset( - 0.5 * m_TParams.m_dDiam - GetOffsR()) ; - pLineE->Invert() ; - - Point3d ptS, ptE ; - pLineS->GetEndPoint( ptS) ; - pLineE->GetStartPoint( ptE) ; - Vector3d vtS, vtE ; - pLineS->GetStartDir( vtS) ; - pLineE->GetStartDir( vtE) ; - - PtrOwner pLineLink( CreateCurveLine()) ; - pLineLink->Set( ptS, ptE) ; - - pMCrv->Clear() ; - if ( ! pMCrv->AddCurve( Release( pLineS))) - return false ; - - // creo raccordi - bool bUseBiArcs = false ; - Vector3d vtDir, vtDir2 ; - pLineLink->GetStartDir( vtDir) ; - pCrvPocket->GetStartDir( vtDir2) ; - - if ( Dist( ptS, ptE) > 500 * EPS_SMALL && AreSameOrOppositeVectorApprox( vtDir, vtDir2)) { - - Point3d ptCrv1, ptCrv2 ; - pLineLink->GetPointD1D2( 0.3, ICurve::FROM_MINUS, ptCrv1) ; - pLineLink->GetPointD1D2( 0.7, ICurve::FROM_MINUS, ptCrv2) ; - - // primo raccordo - double dAng ; - vtS.GetAngleXY( X_AX, dAng) ; - PtrOwner pBiArc1( GetBiArc( ptS, - dAng, ptCrv1, 0, 0.5)) ; - - // secondo raccordo - vtE.GetAngleXY( X_AX, dAng) ; - PtrOwner pBiArc2( GetBiArc( ptE, dAng, ptCrv2, 180, 0.5)) ; - pBiArc2->Invert() ; - - if ( ! IsNull( pBiArc1) && ! IsNull( pBiArc2)) { - bUseBiArcs = true ; - pMCrv->AddCurve( Release( pBiArc1)) ; - pMCrv->AddLine( ptCrv2) ; - pMCrv->AddCurve( Release( pBiArc2)) ; - } - } - - // se non è stato possibile creare raccordo, unisco linearmente - if ( ! bUseBiArcs) - pMCrv->AddCurve( Release( pLineLink)) ; - - if ( ! pMCrv->AddCurve( Release( pLineE))) - return false ; - - // setto temp prop per ricordare curve aggiuntive per pulire angoli - pMCrv->SetCurveTempProp( 0, 1) ; - pMCrv->SetCurveTempProp( pMCrv->GetCurveCount() - 1, 1) ; - - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite* pCompo, ICurveComposite* pRCrv, const Vector3d& vtTool, double dDepth, - int& nOutsideRaw) -{ - // recupero la direzione principale della svuotatura - Vector3d vtMainDir ; - 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 - pCompo->GetCurve( i)->GetStartDir( vtMainDir) ; - break ; - } - } - - // start point - bool bStartOutside = false ; - ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, true, vtTool, dDepth, bStartOutside) ; - // end point - bool bEndOutside = false ; - ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, false, vtTool, dDepth, bEndOutside) ; - - // eventuale inversione della curva per partire sempre dall'esterno del grezzo - if ( bEndOutside && ! bStartOutside) - pCompo->Invert() ; - - nOutsideRaw = 0 ; - if ( bStartOutside && bEndOutside) - nOutsideRaw = 2 ; - else if ( bStartOutside || bEndOutside) { - nOutsideRaw = 1 ; - - // calcolo percorso di ritorno - pRCrv->Clear() ; - pRCrv->AddCurve( pCompo->Clone()) ; - pRCrv->Invert() ; - } - - return true ; -} - -//---------------------------------------------------- -bool -PocketingNT::ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const Vector3d& vtMainDir, bool bLeadIn, const Vector3d& vtTool, double dDepth, bool& bIsOutsideRaw) -{ - bIsOutsideRaw = false ; - - Point3d ptP ; - Vector3d vtDir ; - if ( bLeadIn) { - pCompo->GetStartPoint( ptP) ; - pCompo->GetStartDir( vtDir) ; - } - else { - pCompo->GetEndPoint( ptP) ; - pCompo->GetEndDir( vtDir) ; - } - Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ; - - // recupero info sui lati aperti - int nPropOpen = pCompo->GetTempProp( 0) ; - bool bEdgeOpen = (( nPropOpen & ( bLeadIn ? 8 : 2)) > 0) ; - bool bBaseOpen = (( nPropOpen & 1) > 0) ; - - // recupero info per capire se sto considerando un lato aggiuntivo per pulire angoli - int nIdCrv = ( bLeadIn ? 0 : pCompo->GetCurveCount() - 1) ; - int nExtraEdge ; - pCompo->GetCurveTempProp( nIdCrv, nExtraEdge) ; - - double dSafeZ = GetSafeZ() ; - - // 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) ; - - // se forzato come fuori dal grezzo - if ( m_bOpenOutRaw) { - Point3d ptNewStart = ptP + vtDirP * ( m_TParams.m_dDiam / 2 + max( dSafeZ, m_dOpenMinSafe)) ; - pCompo->AddLine( ptNewStart, ! bLeadIn) ; - bIsOutsideRaw = true ; - return true ; - } - - // recupero la distanza dal bordo del grezzo lungo la direzione di allungamento - double dDist ; - Vector3d vtNorm ; - if ( ! CalcDistanceFromRawSurface( m_nPhase, ptP, vtDirP, dDist, vtNorm)) - return false ; - if ( abs( dDist) < EPS_SMALL) { - ptP -= vtDirP ; - if ( ! CalcDistanceFromRawSurface( m_nPhase, ptP, vtDirP, dDist, vtNorm)) - return false ; - } - - // calcolo eventuali fattori correttivi (se uscita approx. con fianco utensile) - double dCorr = 1 ; - double dDistRef = dDist ; - double dDistMin ; - Vector3d vtNormMin ; - if ( abs( vtTool * vtNorm) < 0.5 && CalcDistanceFromRawSurface( m_nPhase, ptP, vtNorm, dDistMin, vtNormMin)) { - if ( abs( dDistMin) < abs( dDist) && abs( dDistMin) > EPS_SMALL) { - dDistRef = dDistMin ; - dCorr = dDist / dDistMin ; - } - } - - // se vicino al bordo del grezzo - if ( dDistRef < m_TParams.m_dDiam / 2 + EPS_SMALL) { - Point3d ptTest = ptP + vtDirP * ( dDist + ( m_TParams.m_dDiam / 2 + max( dSafeZ, m_dOpenMinSafe)) * dCorr) ; - ptTest += - vtTool * dDepth ; - double dTestElev ; - // 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 + max( dSafeZ, m_dOpenMinSafe)) * dCorr) ; - pCompo->AddLine( ptNewStart, ! bLeadIn) ; - bIsOutsideRaw = true ; - } - } - } - - // tento con attacco ruotato di 90° se non sto considerando un tratto aggiuntivo per pulire angoli - if ( bBaseOpen && ! bIsOutsideRaw && nExtraEdge == 0) { - - Vector3d vtDirO = vtDir ; - vtDirO.Rotate( vtExtr, ( m_Params.m_bInvert ? -90 : 90)) ; - // calcolo distanza dal bordo del grezzo lungo vtDirO - double dDist ; - Vector3d vtNorm ; - if ( ! CalcDistanceFromRawSurface( m_nPhase, ptP, vtDirO, dDist, vtNorm)) - return false ; - - // se vicino al bordo del grezzo - if ( dDist < m_TParams.m_dDiam / 2 + EPS_SMALL) { - Point3d ptTestO = ptP + vtDirO * ( dDist + m_TParams.m_dDiam / 2 + max( dSafeZ, m_dOpenMinSafe)) ; - ptTestO += - vtTool * dDepth ; - double dTestElevO ; - // 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 + max( dSafeZ, m_dOpenMinSafe)) ; - pCompo->AddLine( ptNewStart, ! bLeadIn) ; - bIsOutsideRaw = true ; - } - } - } - return true ; -} - //---------------------------------------------------------------------------- bool PocketingNT::ComputePolishingPath( ICurveComposite* pMCrv, ICurveComposite* pRCrv, bool bSplitArcs) @@ -5057,10 +3065,62 @@ PocketingNT::AddEpicycles( ICurveComposite* pCompo, ICurveComposite * pCrv, ICur return true ; } +//------------------------------------------------------------------------------ +bool +PocketingNT::CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, + const ICurve* pCrvBound, ICurveComposite* pCrvLink) +{ + double dAngStart, dAngEnd ; + vtStart.GetAngleXY( X_AX, dAngStart) ; + vtEnd.GetAngleXY( X_AX, dAngEnd) ; + PtrOwner pBiArcLink( GetBiArc( ptStart, -dAngStart, ptEnd, -dAngEnd, 0.5)) ; + if ( IsNull( pBiArcLink)) + return false ; + + // verifico se esce dalla svuotatura + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pBiArcLink, *pCrvBound) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + // 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)) ; + } + // altrimenti creo un percorso con biarchi e opportuni tratti della curva di contenimento + else { + PtrOwner pCompo( CreateCurveComposite()) ; + if ( IsNull( pCompo)) + return false ; + + double dPar1, dPar2 ; + Point3d ptMinDist1, ptMinDist2 ; + Vector3d vtDir1, vtDir2 ; + double dAng1, dAng2 ; + int nFlag ; + + DistPointCurve distPtSCrv( ptStart, *pCrvBound) ; + distPtSCrv.GetParamAtMinDistPoint( 0, dPar1, nFlag) ; + pCrvBound->GetPointTang( dPar1, ICurve::FROM_MINUS, ptMinDist1, vtDir1) ; + vtDir1.GetAngleXY( X_AX, dAng1) ; + + DistPointCurve distPtECrv( ptEnd, *pCrvBound) ; + distPtECrv.GetParamAtMinDistPoint( 0, dPar2, nFlag) ; + pCrvBound->GetPointTang( dPar2, ICurve::FROM_MINUS, ptMinDist2, vtDir2) ; + vtDir2.GetAngleXY( X_AX, dAng2) ; + + pCompo->AddCurve( GetBiArc( ptStart, -dAngStart, ptMinDist1, -dAng1, 0.5)) ; // primo biarco + pCompo->AddCurve( pCrvBound->CopyParamRange( dPar1, dPar2)) ; // tratto di pCrvBound + pCompo->AddCurve( GetBiArc( ptMinDist2, -dAng2, ptEnd, -dAngEnd, 0.5)) ; // secondo biarco + + pCrvLink->AddCurve( Release( pCompo)) ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool PocketingNT::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, - double dElev, double dAppr, bool bSplitArcs, bool bOutStart) + double dElev, double dAppr, bool bSplitArcs, bool bOutStart) { SetFlag( 1) ; // se con aggregato da sotto o equivalente (rinvio a 90 gradi su testa 5 assi) @@ -5263,21 +3323,21 @@ PocketingNT::AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSaf //---------------------------------------------------------------------------- bool -PocketingNT::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - const ICurveComposite* pRCrv, Point3d& ptP1) const +PocketingNT::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtTool, + const ICurveComposite* pRCrv, Point3d& ptP1) { // Assegno tipo e parametri int nType = GetLeadInType() ; - if ( nType == POCKET_LI_GLIDE && ( pRCrv == nullptr || pRCrv->GetCurveCount() == 0)) - nType = POCKET_LI_NONE ; + if ( nType == SURFROU_LI_GLIDE && ( pRCrv == nullptr || pRCrv->GetCurveCount() == 0)) + nType = SURFROU_LI_NONE ; // Calcolo punto iniziale switch ( nType) { - case POCKET_LI_NONE : - case POCKET_LI_ZIGZAG : - case POCKET_LI_HELIX : + case SURFROU_LI_NONE : + case SURFROU_LI_ZIGZAG : + case SURFROU_LI_HELIX : ptP1 = ptStart ; return true ; - case POCKET_LI_GLIDE : + case SURFROU_LI_GLIDE : { double dLen, dU ; if ( ! pRCrv->GetLength( dLen) || ! pRCrv->GetParamAtLength( dLen - m_Params.m_dLiTang, dU) || @@ -5285,7 +3345,7 @@ PocketingNT::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, c if ( ! pRCrv->GetStartPoint( ptP1)) return false ; } - ptP1 += vtN * ( vtN * ( ptStart - ptP1)) ; + ptP1 += vtTool * ( vtTool * ( ptStart - ptP1)) ; return true ; } default : @@ -5296,8 +3356,8 @@ PocketingNT::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, c //---------------------------------------------------------------------------- bool PocketingNT::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - const ICurveComposite* pCompo, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, - bool bNoneForced, bool bSkipControl) + const ISurfFlatRegion* pSfr, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, + bool bNoneForced, bool bSkipControl) { // Assegno il tipo int nType = GetLeadInType() ; @@ -5316,7 +3376,7 @@ PocketingNT::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vecto 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( pSfr, ptStart, ptCen, dRad)) { // creo l'elica PtrOwner pArc( CreateCurveArc()) ; if ( IsNull( pArc) || ! pArc->Set( ptCen, vtN, dRad, - vtCen, dAngCen, dDeltaN)) @@ -5337,7 +3397,7 @@ PocketingNT::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vecto 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( pSfr, ptStart, ptPa, ptPb)) { for ( int i = 1 ; i <= nStep ; ++ i) { if ( AddLinearMove( ptPa - vtN * ( i - 0.75) * dStep, bSplitArcs, MCH_CL_LEADIN) == GDB_ID_NULL) return false ; @@ -5402,18 +3462,8 @@ PocketingNT::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vecto //---------------------------------------------------------------------------- bool PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, - const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, - Point3d& ptP1, double& dElev) -{ - bool bOppositeHome ; - return AddLeadOut( ptEnd, vtEnd, vtN, pRCrv, bSplitArcs, bNoneForced, ptP1, dElev, bOppositeHome) ; -} - -//---------------------------------------------------------------------------- -bool -PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, - const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, - Point3d& ptP1, double& dElev, bool& bOppositeHome) + const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, + Point3d& ptP1) { // assegno i parametri int nType = GetLeadOutType() ; @@ -5426,19 +3476,6 @@ PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vect { // nessuna uscita ptP1 = ptEnd ; - // determino elevazione su fine uscita - double dEndElev ; - if ( GetElevation( m_nPhase, ptP1 - 10 * EPS_SMALL * vtN, vtN, GetRadiusForStartEndElevation(), vtN, dEndElev)) - dElev = dEndElev ; - // correzione per punto sotto il grezzo con testa normale da sopra - double dSafeZ = GetSafeZ() ; - bool bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtN, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtN, dElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtN, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtN, dElev) ; - bOppositeHome = ( bAhUnderRaw || bUhAboveRaw) ; return true ; } case POCKET_LO_GLIDE : @@ -5465,22 +3502,9 @@ PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vect AddCurveMove( pCrv, bSplitArcs, MCH_CL_LEADOUT) ; // determino elevazione su fine uscita ptP1 = ptFin ; - double dEndElev ; - if ( GetElevation( m_nPhase, ptP1 - 10 * EPS_SMALL * vtN, vtN, GetRadiusForStartEndElevation(), vtN, dEndElev)) - dElev = dEndElev ; - // correzione per punto sotto il grezzo con testa normale da sopra - double dSafeZ = GetSafeZ() ; - bool bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1, vtN, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtN, dElev) ; - bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1, vtN, 0, GetRadiusForStartEndElevation(), - m_TParams.m_dLen, false, dSafeZ, vtN, dElev) ; - bOppositeHome = ( bAhUnderRaw || bUhAboveRaw) ; return true ; } default : - bOppositeHome = false ; return false ; } @@ -5488,7 +3512,7 @@ PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vect //---------------------------------------------------------------------------- double -PocketingNT::GetRadiusForStartEndElevation( void) const +PocketingNT::GetRadiusForStartEndElevation( void) { const double DELTA_ELEV_RAD = 4.0 ; double dDeltaRad = min( DELTA_ELEV_RAD, 0.5 * m_TParams.m_dTDiam) ; @@ -5802,45 +3826,87 @@ PocketingNT::AdjustContourStart( ICurveComposite* pCompo) //---------------------------------------------------------------------------- bool -PocketingNT::VerifyLeadInHelix( const ICurveComposite* pCompo, const Point3d& ptCen, double dRad) const +PocketingNT::CheckSafetyLinearLink( const Point3d& ptCurr, const ISurfFlatRegion* pSfrLimit, const Vector3d& vtTool, + const Point3d& ptDest, bool& bSafe) { - // recupero il piano della curva di contorno - Point3d ptStart ; - Vector3d vtN ; - if ( pCompo == nullptr || ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) + // controllo dei parametri + if ( ! ptCurr.IsValid() || ! ptDest.IsValid() || ! vtTool.IsValid()) 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) ; + bSafe = true ; + + // porto ptDest alla stessa quota di ptCurr secondo vtTool + Plane3d plProj ; + if ( ! plProj.Set( ptCurr, vtTool)) + return false ; + Point3d ptDestProj = ProjectPointOnPlane( ptDest, plProj) ; + + // controllo se la retta che collega ptCurr a ptDesProj è interna o esterna alla regione limite + // devo prima creare un frame Locale XY + if ( pSfrLimit != nullptr && pSfrLimit->IsValid()) { + PtrOwner pSfrLimitLoc( CloneSurfFlatRegion( pSfrLimit)) ; + PtrOwner pLineLoc( CreateCurveLine()) ; + Frame3d frLoc ; + if ( IsNull( pSfrLimitLoc) || ! frLoc.Set( ptCurr, vtTool) || + ! ptDestProj.ToLoc( frLoc) || ! pSfrLimitLoc->ToLoc( frLoc) || + ! pSfrLimitLoc->Offset( m_TParams.m_dDiam / 2 - 10 * EPS_SMALL, ICurve::OFF_FILLET) || + ! pLineLoc->Set( ORIG, ptDestProj)) + return false ; + for ( int nC = 0 ; nC < pSfrLimitLoc->GetChunkCount() && bSafe ; ++ nC) { + CRVCVECTOR ccClass ; + bSafe = ( pSfrLimitLoc->GetCurveClassification( *pLineLoc, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) ; + } + } + + return true ; } //---------------------------------------------------------------------------- bool -PocketingNT::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptPa, const Point3d& ptPb) const +PocketingNT::VerifyLeadInHelix( const ISurfFlatRegion* pSfr, const Point3d& ptStart, + const Point3d& ptCen, double dHelixRad) { - // recupero il piano della curva di contorno - Point3d ptStart ; - Vector3d vtN ; - if ( pCompo == nullptr || ! pCompo->GetStartPoint( ptStart) || ! pCompo->GetExtrusion( vtN)) + // controllo validità dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) return false ; + Vector3d vtN = pSfr->GetNormVersor() ; + // porto il centro sullo stesso piano del contorno + Point3d ptCenL = ptCen - ( ptCen - ptStart) * vtN * vtN ; + // Offset della regione + PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( - m_TParams.m_dDiam / 2 - dHelixRad + 10 * EPS_SMALL, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) + return false ; + // controllo se l'elica è valida + bool bIsInside ; + return ( IsPointInsideSurfFr( ptCenL, pSfrOffs, 0., bIsInside) && bIsInside) ; +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::VerifyLeadInZigZag( const ISurfFlatRegion* pSfr, const Point3d& ptStart, + const Point3d& ptPa, const Point3d& ptPb) +{ + // controllo validità dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + Vector3d vtN = pSfr->GetNormVersor() ; // porto i punti sullo stesso piano del contorno Point3d ptPaL = ptPa - ( ptPa - ptStart) * vtN * vtN ; Point3d ptPbL = ptPb - ( ptPb - ptStart) * vtN * vtN ; - // calcolo la distanza dei due punti dal contorno - double dMinDistPa ; - if ( ! DistPointCurve( ptPaL, *pCompo).GetDist( dMinDistPa)) + // Offset della regione + PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( - m_TParams.m_dDiam / 2 + 10 * EPS_SMALL, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) return false ; - 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) ; + // controllo se i due punti sono validi + bool bIsInside ; + return ( IsPointInsideSurfFr( ptPaL, pSfrOffs, 0., bIsInside) && bIsInside && + IsPointInsideSurfFr( ptPbL, pSfrOffs, 0., bIsInside) && bIsInside) ; } //---------------------------------------------------------------------------- bool -PocketingNT::CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist, Vector3d& vtNorm) +PocketingNT::CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, + double& dDist, Vector3d& vtNorm) { if ( ! GetElevation( nPhase, ptP, vtDir, dDist, vtNorm)) return false ; @@ -5858,3 +3924,39 @@ PocketingNT::CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const V return true ; } + +// debug functions +//---------------------------------------------------------------------------- +void +PocketingNT::_debug_draw_sfr( const ISurfFlatRegion* pSfr, bool bUniform) +{ + if ( pSfr == nullptr || ! pSfr->IsValid()) + return ; + + int nInd = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfr->Clone()) ; + m_pGeomDB->SetMaterial( nInd, Color( 0., 255., 0., .5)) ; + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCrvCompo( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + _debug_draw_loop( pCrvCompo->Clone(), bUniform) ; + } + } + + return ; +} + +void +PocketingNT::_debug_draw_loop( const ICurveComposite* pCrvCompo, bool bUniform) +{ + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return ; + + for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) { + int nProp0 ; pCrvCompo->GetCurveTempProp( nU, nProp0, 0) ; + int nProp1 ; pCrvCompo->GetCurveTempProp( nU, nProp1, 1) ; + int nInd = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvCompo->GetCurve( nU)->Clone()) ; + m_pGeomDB->SetMaterial( nInd, bUniform ? WHITE : ( nProp0 == 0 ? BLUE : RED)) ; + } + + return ; +} diff --git a/PocketingNT.h b/PocketingNT.h index 078a4dc..0b06644 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -17,8 +17,33 @@ #include "PocketingData.h" #include "ToolData.h" #include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkSurfFlatRegion.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h" + +// struttura informazioni sui singoli percorsi +struct PathInfoPO { + bool bOutStart ; // flag per entrata da fuori + bool bSingleCrv ; // se percorso formato da una curva singola ( in generale per SubSteps) + bool bOptTrap ; // flag per casi ottimizzati a trapezio ( per Spiral) + bool bIsZigZagOneWayBorder ; // curve di bordo dei lati chiusi ( per ZigZag e OneWay) + PtrOwner pCrvPath ; // percorso del centro utensile + PtrOwner pCrvRet ; // curva di ritorno per LeadIn/Out a guida +} ; +// tipo percorso +typedef std::vector PATHINFOPOVECTOR ; + +// struttura informazioni per Step/SubSteps complessivi +struct StepInfoPO { + double dDepth ; // profondità dello step attuale + double dRelativeDepth ; // profondità relativa allo step al di sopra + PtrOwner pSfrPock ; // regione piana di svuotatura + PtrOwner pSfrLimit ; // regione piana da non svuotare + PATHINFOPOVECTOR vPaths ; // percorsi di Pocketing +} ; +// tipo step +typedef std::vector STEPINFOPOVECTOR ; //---------------------------------------------------------------------------- class PocketingNT : public Machining @@ -69,79 +94,53 @@ class PocketingNT : public Machining bool VerifyGeometry( SelData Id, int& nSubs, int& nType) ; bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ; bool SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, bool* pbSomeOpen = nullptr) ; + bool SetSfrLoopsAllTempProp( int nSfrId, ISurfFlatRegion* pSfr) ; bool ResetCurveAllTempProp( ICurve* pCurve) ; bool Chain( int nGrpDestId) ; + ISurfTriMesh* GetRaw( void) ; + ISurfTriMesh* GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtTrasl, const Vector3d& vtExtr) ; + ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) ; + bool ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion) ; + bool CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, ISurfFlatRegion* pSfrLimit) ; bool ProcessPath( int nPathId, int nPvId, int nClId) ; - bool CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double dLen, double& dElev) const ; + bool CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double dLen, double& dElev) ; 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, double& dOffs) ; - bool ZigZagOptimizedNoClosedEdges( ICurveComposite* pCrvPocket, bool& bOptimizedZigZag, Vector3d& vtDir, double& dOffs) ; - bool ZigZagOptimizedOneClosedEdge( ICurveComposite* pCrvPocket, int nClosedId, bool& bOptimizedZigZag, Vector3d& vtDir, double& dOffs) ; - bool ZigZagOptimizedTwoClosedEdges( ICurveComposite* pCrvPocket, const INTVECTOR& vnClosedIds, bool& bOptimizedZigZag, - bool& bOpposite, Vector3d& vtDir, double& dOffs) ; - bool ZigZagOptimizedThreeClosedEdges( ICurveComposite* pCrvPocket, const INTVECTOR& vnClosedIds, bool& bOptimizedZigZag, - bool& bOpposite, Vector3d& vtDir, double& dOffs) ; - bool ZigZagOptimizedComputeOffset( ICurveComposite* pCrvPocket, const Vector3d& vtMainDir, int nOffsettedEdgesOnY, - const INTVECTOR& vnClosedIds, double& dOffs) ; + bool CalcPaths( STEPINFOPOVECTOR& vStepInfo) ; + bool AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, double dElev, double dStep, bool bSplitArcs) ; + double GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) ; 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 ComputePolishingPath( ICurveComposite* pMCrv, ICurveComposite* pRCrv, bool bSplitArcs) ; + bool AddEpicycles( ICurveComposite * pCompo, ICurveComposite * pCrv, ICurveComposite * pCrvBound = nullptr) ; 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, - bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) ; - bool CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Vector3d& vtDir, double dPocketSize, - ICurveComposite* pMCrv, ICurveComposite* pRCrv, bool& bOptimizedTrap) ; - bool CalcTrapezoidSpiralLocalFrame( ICurveComposite * pCrvPocket, const Vector3d& vtDir, Frame3d& frLoc) ; - bool CalcTrapezoidSpiralXCoord( const ICurveComposite * pCrvPocket, bool bStart, double dYCoord, double& dXCoord, double dPocketSize) ; - bool AdjustTrapezoidSpiralForAngles( ICurveComposite * pMCrv, const ICurveComposite * pCrvPocket, bool bStart) ; - 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 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, - double dElev, double dAppr, bool bSplitArcs, bool bOutStart) ; + double dElev, double dAppr, bool bSplitArcs, bool bOutStart) ; bool AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr, bool bSplitArcs, bool bOutStart = false) ; bool AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr, bool bSplitArcs) ; bool AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr, bool bSplitArcs) ; - bool CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - const ICurveComposite* pRCrv, Point3d& ptP1) const ; + bool CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtTool, const ICurveComposite* pCrvPath, Point3d& ptP1) ; 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 bNoneForced = false, bool bSkipControl = false) ; + const ISurfFlatRegion* pSfr, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, + bool bNoneForced, bool bSkipControl) ; bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, - const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, - Point3d& ptP1, double& dElev) ; - bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, - const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, - Point3d& ptP1, double& dElev, bool& bOppositeHome) ; - double GetRadiusForStartEndElevation( void) const ; + const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, Point3d& ptP1) ; + double GetRadiusForStartEndElevation( void) ; bool GetForcedClosed( void) ; 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 CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist, Vector3d& vtNorm) ; + bool CheckSafetyLinearLink( const Point3d& ptCurr, const ISurfFlatRegion* pSfrLimit, const Vector3d& vtTool, + const Point3d& ptDest, bool& bSafe) ; + bool VerifyLeadInHelix( const ISurfFlatRegion* pSfr, const Point3d& ptStart, const Point3d& ptCen, double dHelixRad) ; + bool VerifyLeadInZigZag( const ISurfFlatRegion* pSfr, const Point3d& ptStart, const Point3d& ptPa, const Point3d& ptPb) ; + bool CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist, Vector3d& vtNorm) ; + // debug + void _debug_draw_sfr( const ISurfFlatRegion* pSfr, bool bUniform) ; + void _debug_draw_loop( const ICurveComposite* pCrvCompo, bool bUniform) ; private : double GetSpeed( void) const @@ -177,7 +176,7 @@ class PocketingNT : public Machining return m_Params.m_nLeadOutType ; } private : - SELVECTOR m_vId ; // identificativi entità geometriche da lavorare + SELVECTOR m_vId ; // identificativi entità geometriche da lavorare PocketingData m_Params ; // parametri lavorazione ToolData m_TParams ; // parametri utensile double m_dTHoldBase ; // posizione base del porta-utensile @@ -194,4 +193,6 @@ class PocketingNT : public Machining AggrBottom m_AggrBottom ; // dati eventuale aggregato da sotto bool m_bOpenOutRaw ; // flag forzatura lati aperti sempre fuori dal grezzo double m_dOpenMinSafe ; // minima distanza di sicurezza di attacco su lato aperto + + bool _m_Debug = false ; // _debug } ; \ No newline at end of file diff --git a/SurfRoughing.cpp b/SurfRoughing.cpp index 77e5030..b63c2f7 100644 --- a/SurfRoughing.cpp +++ b/SurfRoughing.cpp @@ -1263,7 +1263,9 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) vSurfL.emplace_back( m_pGeomDB, vSurfId[i], GLOB_FRM) ; if ( vSurfL[i].Get() == nullptr) return false ; - vpStm.emplace_back( GetSurfTriMesh( vSurfL[i].Get())) ; + const ISurfTriMesh* pStm = GetSurfTriMesh( vSurfL[i].Get()) ; + if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) + vpStm.emplace_back( pStm) ; } Frame3d frPlanes ; frPlanes.Set( plPlane.GetPoint(), vtTool) ; @@ -1810,7 +1812,7 @@ SurfRoughing::GetActiveSurfaces( INTVECTOR& vSurfId) const // se entità superficie e visibile, la aggiungo int nStat ; if ( m_pGeomDB->GetGeoType( nEntId) == SRF_TRIMESH && - m_pGeomDB->GetCalcStatus( nEntId, nStat) && nStat != GDB_ST_OFF) + m_pGeomDB->GetCalcStatus( nEntId, nStat) && nStat != GDB_ST_OFF) vSurfId.emplace_back( nEntId) ; // passo alla entità successiva nEntId = m_pGeomDB->GetNext( nEntId) ;