diff --git a/EgtMachKernel.rc b/EgtMachKernel.rc index 6be67a2..529550a 100644 Binary files a/EgtMachKernel.rc and b/EgtMachKernel.rc differ diff --git a/OperUserNotesConst.h b/OperUserNotesConst.h index 4b1e293..7ca4a60 100644 --- a/OperUserNotesConst.h +++ b/OperUserNotesConst.h @@ -54,6 +54,7 @@ static const std::string UN_PROJEXT = "ExtProj" ; static const std::string UN_ADJUSTFEED = "AdjustFeed" ; static const std::string UN_MINFEED = "MinFeed" ; static const std::string UN_TOOL_COMPENSATION = "ToolCompensation" ; +static const std::string UN_START_PNT = "StartPoint" ; // Solo per Sawing static const std::string UN_DOWNSE = "DownSE" ; @@ -70,6 +71,8 @@ static const std::string UN_STEPNUMBER = "StepNumber" ; static const std::string UN_BITANGANG = "BiTangAng" ; static const std::string UN_OPTIMALTYPE = "OptimalType" ; static const std::string UN_ANGLETOL = "AngleTol" ; +static const std::string UN_THETA = "Theta" ; +static const std::string UN_PHI = "Phi" ; // Solo per SurfRoughing static const std::string UN_PLANEZ = "PlaneZ" ; diff --git a/PocketingNT.cpp b/PocketingNT.cpp index 22992e3..8fc7200 100644 --- a/PocketingNT.cpp +++ b/PocketingNT.cpp @@ -60,6 +60,7 @@ static double EXTRA_ELEV = 5. ; static double EXTRA_DEPTH = 5. ; static double SAFETY_LINK_COS = cos( - ( 175 * DEGTORAD)) ; static double TOOL_RAD_PTSTART = 20. ; +static double FEED_MAX_COEFF = 1000. ; //------------------------------ Errori/Warnings -------------------------------------- // 2401 = "Error in PocketingNT : UpdateToolData failed" @@ -105,6 +106,7 @@ static double TOOL_RAD_PTSTART = 20. ; // 2442 = "Error in PocketingNT : Error in CalcPocketing" // 2443 = "Error in PocketingNT : Calc Limit Region failed" // 2444 = "Error in PocketingNT : Slicing Raw failed" +// 2455 = "Error in PocketingNT : Error in Connecting Start Point" // 2451 = "Warning in PocketingNT : Skipped entity (xx)" // 2452 = "Warning in PocketingNT : No pocket" // 2453 = "Warning in PocketingNT : Tool name changed (xx)" @@ -133,10 +135,12 @@ static double TOOL_RAD_PTSTART = 20. ; #define DEBUG_ZIGZAG_LEADIN 0 // Debug per ZigZag LeadIn #define DEBUG_DOUBLE_PARALLEL 0 // Debug per Pocketing in Doppio con Parallelo #define DEBUG_TOOL_COMPENSATION 0 // Debug per Tool Compensation +#define DEBUG_SILHOUETTE 0 // Debug Silhouette +#define DEBUG_USER_PTSTART 0 // Debug punto iniziale stabilito dall'utente #define DEBUG 0 // Debug #if DEBUG_STM_TOPOLOGY || DEBUG_OPEN_EDGE_EXTENSION || DEBUG_OPEN_EDGE_IN_RAW || DEBUG_SFR_STEPS || DEBUG_SFR_RAW || DEBUG_SFR_GEO_EXT || \ DEBUG_GLIDE || DEBUG_SAFETY_LINK || DEBUG_FEED || DEBUG_START_POINT || DEBUG_PATH_CL || DEBUG_ZIGZAG_LEADIN || DEBUG_DOUBLE_PARALLEL || \ - DEBUG + DEBUG_SILHOUETTE || DEBUG #include "EgtDev/Include/EGkGeoPoint3d.h" #include "EgtDev/Include/EGkGeoVector3d.h" #include "EgtDev/Include/EGkFrame3d.h" @@ -1732,6 +1736,7 @@ PocketingNT::SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, *pbSomeOpen = false ; // reset proprietà temporanee ResetCurveAllTempProp( pCurve) ; + // se svuotatura tutta chiusa, allora esco if ( m_bAllClose) return true ; // se forzato chiuso o non presenti info per lati aperti, esco @@ -1740,6 +1745,11 @@ PocketingNT::SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, // recupero info sui lati aperti INTVECTOR vOpen ; m_pGeomDB->GetInfo( nCrvId, KEY_OPEN, vOpen) ; + // se curva da considerare come tutta aperta + if ( ! bForcedClose && ssize( vOpen) == 1 && vOpen[0] == -1) { + ResetCurveAllTempProp( pCurve, false) ; + return true ; + } // se curva composita ICurveComposite* pCC = GetCurveComposite( pCurve) ; if ( pCC != nullptr) { @@ -1791,7 +1801,7 @@ PocketingNT::SetSfrLoopsAllTempProp( int nSfrId, ISurfFlatRegion* pSfr) //---------------------------------------------------------------------------- bool -PocketingNT::ResetCurveAllTempProp( ICurve* pCurve) +PocketingNT::ResetCurveAllTempProp( ICurve* pCurve, bool bClose) { if ( pCurve == nullptr) return false ; @@ -1799,7 +1809,7 @@ PocketingNT::ResetCurveAllTempProp( ICurve* pCurve) ICurveComposite* pCC = GetCurveComposite( pCurve) ; if ( pCC != nullptr) { for ( int i = 0 ; i < pCC->GetCurveCount() ; ++ i) - pCC->SetCurveTempProp( i, TEMP_PROP_CLOSE_EDGE) ; + pCC->SetCurveTempProp( i, bClose ? TEMP_PROP_CLOSE_EDGE : TEMP_PROP_OPEN_EDGE) ; } return true ; } @@ -2141,11 +2151,7 @@ PocketingNT::GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExt if ( pSfr == nullptr || ! pSfr->IsValid()) return nullptr ; - /* - pSfr -> superficie da cui estrudere i lati chiusi - vtExtrs -> vettore estrusione dei lati chiusi di pSfr - */ - + // inizializzo la superficie di estrusione PtrOwner pMySfr( CloneSurfFlatRegion( pSfr)) ; if ( IsNull( pMySfr) || ! pMySfr->IsValid()) return nullptr ; @@ -2167,16 +2173,14 @@ PocketingNT::GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExt if ( ! GetHomogeneousParts( pCompoLoop, vpCrvs)) return nullptr ; // scorro i tratti omogenei chiusi - for ( int nP = 0 ; nP < int( vpCrvs.size()) ; ++ nP) { + for ( int nP = 0 ; nP < ssize( vpCrvs) ; ++ 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) ; + vpCrvs[nP]->ApproxWithLines( 10. * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ; // estrusione del tratto chiuso PtrOwner pStm( CreateSurfTriMesh()) ; - if ( IsNull( pStm) || - ! pStm->AdjustTopology() || - ! pStm->CreateByExtrusion( PL, vtExtr)) + if ( IsNull( pStm) || ! pStm->AdjustTopology() || ! pStm->CreateByExtrusion( PL, vtExtr)) return nullptr ; // aggiungo i triangoli ricavati alla zuppa if ( ! IsNull( pStm) && pStm->IsValid()) { @@ -2288,12 +2292,11 @@ PocketingNT::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, doubl //---------------------------------------------------------------------------- ISurfFlatRegion* -PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, - const Vector3d& vtTool) +PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool, + const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil) { // controllo dei parametri - if ( pStmRaw == nullptr || ! pStmRaw->IsValid() || - pSfr == nullptr || ! pSfr->IsValid()) + if ( pStmRaw == nullptr || ! pStmRaw->IsValid() || pSfr == nullptr || ! pSfr->IsValid()) return nullptr ; // recupero il piano di taglio dalla regione piana @@ -2302,10 +2305,48 @@ PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRe if ( ! plProj.Set( ptCen, vtTool)) return nullptr ; - // recupero la Silhouette al piano trovato + #if DEBUG_SILHOUETTE + int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; + m_pGeomDB->SetName( nGrp, "Silhouette") ; + m_pGeomDB->SetStatus( nGrp, GDB_ST_OFF) ; + int nLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + int nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pStmRaw->Clone()) ; + m_pGeomDB->SetMaterial( nSfr, Color( 0., 0., 0., .5)) ; + PtrOwner frPock( CreateGeoFrame3d()) ; frPock->Set( frAtTop) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, Release( frPock)) ; + PtrOwner ptDepth( CreateGeoPoint3d()) ; + double dLevel = abs( ( frAtTop.Orig() - plProj.GetPoint()) * vtTool) ; + ptDepth->Set( frAtTop.Orig() - frAtTop.VersZ() * dLevel) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, Release( ptDepth)) ; + #endif + + // verifico con quale metodo calcolare la Silhouette in base al numero di triangoli + const double TRIA_NUM = 500 ; + int nTriaCnt = pStmRaw->GetTriangleCount() ; + bool bSimpleSil = ( nTriaCnt <= TRIA_NUM) ; POLYLINEVECTOR vPL ; - if ( ! pStmRaw->GetSilhouette( plProj, EPS_SMALL, vPL)) - return nullptr ; + if ( bSimpleSil) { + // calcolo la Silhouette base mediante proiezione dei triangoli + bSimpleSil = ( pStmRaw->GetSilhouette( plProj, EPS_SMALL, vPL)) ; + } + if ( ! bSimpleSil) { + // calcolo la Silhouette mediante CAv + vPL.clear() ; // per sicurezza + // --- se non ho già istanziato un classe di Cav, la inizializzo, altrimenti utilizzo quella presente + if ( *ppCavParSil == nullptr) { + *ppCavParSil = CreateCAvParSilhouettesSurfTm() ; + if ( *ppCavParSil == nullptr) + return nullptr ; + } + if ( ! frAtTop.IsValid()) + return nullptr ; + double dLevel = abs( ( frAtTop.Orig() - plProj.GetPoint()) * vtTool) ; + const double SIL_TOL = 1.0 ; + if ( ! ( *ppCavParSil)->SetData( CISURFTMPVECTOR{ pStmRaw}, frAtTop, SIL_TOL) || + ! ( *ppCavParSil)->GetSilhouette( - dLevel - 10. * EPS_SMALL, vPL)) // evito di essere a filo del grezzo + return nullptr ; + } + // se non trovo nessun contorno sono fuori dal grezzo, la superficie è vuota if ( vPL.empty()) return ( CreateSurfFlatRegion()) ; @@ -2316,6 +2357,10 @@ PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRe PtrOwner pCrvLoop( CreateCurveComposite()) ; if ( IsNull( pCrvLoop) || ! pCrvLoop->FromPolyLine( PL)) return nullptr ; + #if DEBUG_SILHOUETTE + int nCvrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pCrvLoop->Clone()) ; + m_pGeomDB->SetMaterial( nCvrId, RED) ; + #endif SfrByC.AddCurve( Release( pCrvLoop)) ; } PtrOwner pSfrRaw( SfrByC.GetSurf()) ; @@ -2326,6 +2371,46 @@ PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRe return Release( pSfrRaw) ; } +//---------------------------------------------------------------------------- +Point3d +PocketingNT::GetStartPointByUser( const ISurfFlatRegion* pSfr) const +{ + // se dalle note utente non ho un punto scelto, non faccio nulla + Point3d ptStartRef = P_INVALID ; + if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_START_PNT, ptStartRef) || ! ptStartRef.IsValid()) + return P_INVALID ; + + // se il tipo di svuotatura è di categoria ZigZag/OneWay, non considero tale parametro + if ( m_Params.m_nSubType == POCKET_SUB_ZIGZAG || m_Params.m_nSubType == POCKET_SUB_ONEWAY || + m_Params.m_nSubType == POCKET_SUB_CONFORMAL_ZIGZAG || m_Params.m_nSubType == POCKET_SUB_CONFORMAL_ONEWAY) + return P_INVALID ; + + // se lavorazione in SpiralIn il punto serve per determinare su quale aperto entrare, quindi restituisco automaticamente il punto + // (il calcolo dei percorsi di svuotatura cerca automaticamente l'aperto migliore in base al punto su sui effettuare l'entrata) + if ( m_Params.m_nSubType == POCKET_SUB_SPIRALIN) + return ptStartRef ; + + // se la lavorazione e in SpiralOut, allora il punto serve per effettuare l'entrata e poi per collegarsi al punto iniziale della + // svuotatura + if ( m_Params.m_nSubType == POCKET_SUB_SPIRALOUT) { + if ( pSfr != nullptr && pSfr->IsValid()) { + // recupero il piano della regione + Point3d ptCentroid ; pSfr->GetCentroid( ptCentroid) ; + Plane3d plSfr ; + if ( ! plSfr.Set( ptCentroid, pSfr->GetNormVersor())) + return P_INVALID ; + // proietto il punto trovato su tale piano + Point3d ptProj = ProjectPointOnPlane( ptStartRef, plSfr) ; + // verifico che sia al suo interno + bool bIsInside = false ; + if ( IsPointInsideSurfFr( ptProj, pSfr, m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL, bIsInside) && bIsInside) + return ptProj ; + } + } + + return P_INVALID ; +} + //---------------------------------------------------------------------------- Point3d PocketingNT::GetStartPointsByHead( const STEPINFOPOVECTOR& vStepInfo) const @@ -2504,7 +2589,7 @@ PocketingNT::GetStartPointsByHead( const STEPINFOPOVECTOR& vStepInfo) const //---------------------------------------------------------------------------- Point3d -PocketingNT::GetStartPointsFromSteps( const STEPINFOPOVECTOR& vStepInfo, int nCrvType) const +PocketingNT::GetStartPointsBySteps( const STEPINFOPOVECTOR& vStepInfo, int nCrvType) const { // se non ho step, allora non ho un punto di riferimento if ( vStepInfo.empty()) @@ -2871,24 +2956,25 @@ PocketingNT::ExtendOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm) bool PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion) { - // controllo parametri : - if ( pSfr == nullptr || ! pSfr->IsValid() || - pStmExtrusion == nullptr) + 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 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 ; + const double DIST_TOL = 250. * EPS_SMALL ; // scorro tutti i loop for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { @@ -2898,7 +2984,7 @@ PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* p return false ; // scorro ogni sua sottocurva for ( int nU = 0 ; nU < pCrvCompoLoop->GetCurveCount() ; ++ nU) { - // la sottocurva viene messa chiusa ( condizione base) + // la sottocurva viene messa aperta ( condizione base) pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_OPEN_EDGE, 0) ; // recupero la sottocurva const ICurve* pCrv = pCrvCompoLoop->GetCurve( nU) ; @@ -2915,7 +3001,7 @@ PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* p DistPointSurfTm distCalculator( ptPar, *pStmExtrusion) ; double dDist = 0. ; distCalculator.GetDist( dDist) ; - bIsOnStm = ( dDist < 25 * EPS_SMALL) ; + bIsOnStm = ( dDist < DIST_TOL) ; } if ( bIsOnStm) pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_CLOSE_EDGE, 0) ; @@ -2924,7 +3010,6 @@ PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* p } return true ; - } //---------------------------------------------------------------------------- @@ -3520,13 +3605,19 @@ PocketingNT::CalcGeoExtSurfFr( const ISurfFlatRegion* pSfrPock, const Vector3d& if ( vGeoSel.empty()) return true ; - // porto la regione di svuotatura nel più basso + // porto la regione di svuotatura nel punto più basso PtrOwner pSfr( CloneSurfFlatRegion( pSfrPock)) ; if ( IsNull( pSfr) || ! pSfr->IsValid()) return false ; pSfr->Translate( - vtTool * dDepth) ; // sempre in questo piano calcolo la silhouette del Grezzo - PtrOwner pSfrRaw( GetSfrRawProjection( pStmRaw, pSfr, vtTool)) ; + PtrOwner pCavParSil( nullptr) ; + ICAvParSilhouettesSurfTm* ppCavParSil = Get( pCavParSil) ; + Point3d ptAtTop ; pSfr->GetCentroid( ptAtTop) ; + Frame3d frAtTop ; + if ( ! frAtTop.Set( ptAtTop, pSfr->GetNormVersor())) + return false ; + PtrOwner pSfrRaw( GetSfrRawProjection( pStmRaw, pSfr, vtTool, frAtTop, &ppCavParSil)) ; // verifico se l'entità selezionata è una superficie TriMesh ( quindi un SoloId) for ( const SelData& Id : vGeoSel) { @@ -3828,6 +3919,13 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) } #endif + // definisco la classe di calcolo della Silhoette del grezzo nel caso mi servisse + PtrOwner pCavParSil( nullptr) ; + Point3d ptAtTop ; pSfr->GetCentroid( ptAtTop) ; + Frame3d frAtTop ; + if ( ! frAtTop.Set( ptAtTop, pSfr->GetNormVersor())) + return false ; + // se necessario modifico la geometria in caso di selezione originaria di TriMesh // ( Gestione dei lati chiusi di una TriMesh tagliati su più facce del grezzo) ISURFFRPOVECTOR vSurfFrGeoExt ; @@ -4016,7 +4114,9 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) return false ; // adatto la regione piana alla geometria del grezzo - PtrOwner pSfrTrim( GetSfrRawProjection( ( pStmTrim == nullptr ? pStmRaw : pStmTrim), pSfrPock, vtTool)) ; + ICAvParSilhouettesSurfTm* pCavParSilTmp = Get( pCavParSil) ; + PtrOwner pSfrTrim( GetSfrRawProjection( ( pStmTrim == nullptr ? pStmRaw : pStmTrim), pSfrPock, vtTool, frAtTop, + &pCavParSilTmp)) ; if ( IsNull( pSfrTrim)) { m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Slicing Raw failed") ; return false ; @@ -4607,15 +4707,33 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) if ( vStepInfo.empty()) return true ; - // punto finale di riferimento per il percorso attuale ( serve per trovare il punto iniziale - // del percorso successivo). Parto analizzando la testa ( da sopra/da sotto) - Point3d ptStartRef = GetStartPointsByHead( vStepInfo) ; - // --- se punto invalido e raggio utensile grande - if ( ! ptStartRef.IsValid() && m_TParams.m_dDiam / 2. > TOOL_RAD_PTSTART - EPS_ZERO) { - // cerco l'ingresso in base alla geometria iniziale della tasca - ptStartRef = GetStartPointsFromSteps( vStepInfo, TEMP_PROP_OPEN_EDGE) ; - if ( ! ptStartRef.IsValid()) - ptStartRef = GetStartPointsFromSteps( vStepInfo, TEMP_PROP_CLOSE_EDGE) ; + // definisco il tipo di punto iniziale + enum START_PT { DEFAULT = 0, BY_USER = 1, BY_HEAD = 2, BY_OPEN_GEO = 3, BY_CLOSE_GEO = 4} ; + int nStartPtType = START_PT::DEFAULT ; + Point3d ptLinkStart = P_INVALID ; + // recupero eventuale punto iniziale per la svuotatura definito dall'utente + Point3d ptStartRef = GetStartPointByUser( vStepInfo.front().pSfrPock) ; + if ( ! ptStartRef.IsValid()) { + // se l'utente non ha definito un punto iniziale, allora eseguo analisi della testa (da sopra/da sotto) + ptStartRef = GetStartPointsByHead( vStepInfo) ; + if ( ! ptStartRef.IsValid() && m_TParams.m_dDiam / 2. > TOOL_RAD_PTSTART - EPS_ZERO) { + // se punto non valido ed utensile grane, cerco l'ingresso in base alla geometria dei lati aperti della tasca + ptStartRef = GetStartPointsBySteps( vStepInfo, TEMP_PROP_OPEN_EDGE) ; + if ( ! ptStartRef.IsValid()) { + // se punto non valido, cerco l'ingresso in base alla geometria dei lati chiusi della tasca + ptStartRef = GetStartPointsBySteps( vStepInfo, TEMP_PROP_CLOSE_EDGE) ; + if ( ptStartRef.IsValid()) + nStartPtType = START_PT::BY_CLOSE_GEO ; + } + else + nStartPtType = START_PT::BY_OPEN_GEO ; + } + else + nStartPtType = START_PT::BY_HEAD ; + } + else { + nStartPtType = START_PT::BY_USER ; + ptLinkStart = ptStartRef ; } // recupero flag per casi ottimizzati @@ -4665,6 +4783,10 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) bool bConventionalMilling = ( m_Params.m_nSubType == POCKET_SPIRALIN || m_Params.m_nSubType == POCKET_SPIRALOUT || m_Params.m_nSubType == POCKET_ONEWAY || m_Params.m_nSubType == POCKET_CONFORMAL_ONEWAY) ; + + // flag per svuotatura in SpiralOut con punto iniziale + bool bPtStartLink = ( nStartPtType == START_PT::BY_USER && m_Params.m_nSubType == POCKET_SUB_SPIRALOUT) ; + // scorro gli indici delle superfici for ( int i = 0 ; i < ssize( vStepInfo) ; ++ i) { // calcolo i percorsi di Pocketing ( o di lucidatura se richiesto) @@ -4735,27 +4857,43 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) if ( ! vStepInfo[i].vPaths[j].pCrvPath.Set( vCrvPaths[j])) return false ; } - // definisco il nuovo punto di riferimento per il percorso successivo - // --------------------- Se caso ottimizzato a spirale --------------------- - if ( ssize( vStepInfo[i].vPaths) == 1 && vStepInfo[i].vPaths[0].bOptCirle) { - // Se entrata da fuori, ricomincio dall'esterno - if ( vStepInfo[i].vPaths[0].bOutStart) - vStepInfo[i].vPaths[0].pCrvPath->GetStartPoint( ptStartRef) ; - // altrimenti - else { - if ( m_Params.m_nSubType == POCKET_SPIRALOUT) - vStepInfo[i].vPaths[0].pCrvPath->GetEndPoint( ptStartRef) ; // è invertito - else - vStepInfo[i].vPaths[0].pCrvPath->GetStartPoint( ptStartRef) ; + + // se lavorazione in SpiralOut e punto d'inizio definito dall'utente, aggiungo un tratto di collegamento + if ( bPtStartLink) { + Point3d ptStartPath ; vStepInfo[i].vPaths.front().pCrvPath->GetStartPoint( ptStartPath) ; + PtrOwner pCompoLink( CreateCurveComposite()) ; + if ( IsNull( pCompoLink)) + return false ; + if ( CalcLinkByStartUserPoint( vStepInfo[i].pSfrPock, vStepInfo[i].pSfrLimit, ptLinkStart, ptStartPath, pCompoLink)) { + if ( ! vStepInfo[i].vPaths.front().pCrvPath->AddCurve( Release( pCompoLink), false, 10. * EPS_SMALL)) { + m_pMchMgr->SetLastError( 2455, "Error in PocketingNT : Error in Connecting Start Point") ; + return false ; + } } } - // altrimenti rimane fisso al punto iniziale del percorso precedente else { - // se percorso di correzione, e caso precedente a spirale, non aggiorno il percorso - if ( bToolComp && ssize( vStepInfo[i].vPaths) == 2 && vStepInfo[i].vPaths[0].bOptCirle) - ; // lascio invariato - else - vStepInfo[i].vPaths.front().pCrvPath->GetStartPoint( ptStartRef) ; + // definisco il nuovo punto di riferimento per il percorso successivo + // --------------------- Se caso ottimizzato a spirale --------------------- + if ( ! ( bPtStartLink && i == 0) && ssize( vStepInfo[i].vPaths) == 1 && vStepInfo[i].vPaths[0].bOptCirle) { + // Se entrata da fuori, ricomincio dall'esterno + if ( vStepInfo[i].vPaths[0].bOutStart) + vStepInfo[i].vPaths[0].pCrvPath->GetStartPoint( ptStartRef) ; + // altrimenti + else { + if ( m_Params.m_nSubType == POCKET_SPIRALOUT) + vStepInfo[i].vPaths[0].pCrvPath->GetEndPoint( ptStartRef) ; // è invertito + else + vStepInfo[i].vPaths[0].pCrvPath->GetStartPoint( ptStartRef) ; + } + } + // altrimenti rimane fisso al punto iniziale del percorso precedente + else { + // se percorso di correzione, e caso precedente a spirale, non aggiorno il percorso + if ( bToolComp && ssize( vStepInfo[i].vPaths) == 2 && vStepInfo[i].vPaths[0].bOptCirle) + ; // lascio invariato + else + vStepInfo[i].vPaths.front().pCrvPath->GetStartPoint( ptStartRef) ; + } } // aggiorno la progressBar ExeProcessEvents( 50 + i * 50 / ssize( vStepInfo), 0) ; @@ -4810,7 +4948,7 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) if ( ! bToolComp || ( bToolComp && bHolePocketing && j == 1)) { if ( IsNull( pCrvGlideIn) || ! CalcRetCurve( vStepInfo[i].vPaths[j], vStepInfo[i], vStepInfo[i].vPaths[j].pCrvPath, - vStepInfo[i].pSfrPock->GetNormVersor(), bHolePocketing, ptHoleDest, bToolComp, true, pCrvGlideIn)) { + vStepInfo[i].pSfrPock->GetNormVersor(), ( ! bPtStartLink && bHolePocketing), ptHoleDest, bToolComp, true, pCrvGlideIn)) { m_pMchMgr->SetLastError( 2415, "Error in PocketingNT : LeadIn not computable") ; return false ; } @@ -4825,7 +4963,7 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) PtrOwner pCrvGlideOut( CreateCurveComposite()) ; if ( IsNull( pCrvGlideOut) || ! CalcRetCurve( vStepInfo[i].vPaths[j], vStepInfo[i], vStepInfo[i].vPaths[j].pCrvPath, - vStepInfo[i].pSfrPock->GetNormVersor(), ( ! bToolComp && bHolePocketing), P_INVALID, bToolComp, false, pCrvGlideOut)) { + vStepInfo[i].pSfrPock->GetNormVersor(), ( ! bToolComp && ! bPtStartLink && bHolePocketing), P_INVALID, bToolComp, false, pCrvGlideOut)) { m_pMchMgr->SetLastError( 2416, "Error in PocketingNT : LeadOut not computable") ; return false ; } @@ -5251,7 +5389,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou 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)) ; + double dCoeffFeed = min( 1., ( dTempParam > EPS_SMALL ? dTempParam /= FEED_MAX_COEFF : 1)) ; // se prima entità if ( k == 0) { @@ -7035,6 +7173,156 @@ PocketingNT::AssignPropsToCamDataForToolCompensation( int nId, bool bLineIn, boo return true ; } +//---------------------------------------------------------------------------- +bool +PocketingNT::CalcLinkByStartUserPoint( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrLimit, const Point3d& ptStart, + const Point3d& ptEnd, ICurveComposite* pCompoLink) const +{ + // se la regione di svuotarua non è valida, errore + if ( pSfrPock == nullptr || ! pSfrPock->IsValid()) + return false ; + + // calcolo un collegamento lineare tra inizio e fine + if ( pCompoLink == nullptr) + return false ; + pCompoLink->Clear() ; + Point3d ptC ; pSfrPock->GetCentroid( ptC) ; + Plane3d plProj ; + if ( ! plProj.Set( ptC, pSfrPock->GetNormVersor())) + return false ; + Point3d ptStartProj = ProjectPointOnPlane( ptStart, plProj) ; + Point3d ptEndProj = ProjectPointOnPlane( ptEnd, plProj) ; + if ( ! pCompoLink->AddPoint( ptStartProj) || ! pCompoLink->AddLine( ptEndProj)) + return false ; + + #if DEBUG_USER_PTSTART + int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, Frame3d()) ; + int nLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, Frame3d()) ; + m_pGeomDB->SetName( nGrp, "User_Pt_Start") ; + m_pGeomDB->SetName( nLay, "user_Pt_Start_Glob") ; + int nCrv = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pCompoLink->Clone()) ; + m_pGeomDB->SetMaterial( nCrv, BLUE) ; + #endif + + // se non ho una regione limite, allora il collegamento l'ho già calcolato + if ( pSfrLimit == nullptr || ! pSfrLimit->IsValid()) { + for ( int nCrv = 0 ; nCrv < pCompoLink->GetCurveCount() ; ++ nCrv) + pCompoLink->SetTempParam( FEED_MAX_COEFF) ; + return true ; + } + else { + + #if DEBUG_USER_PTSTART + int nSfrLimit = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pSfrLimit->Clone()) ; + m_pGeomDB->SetMaterial( nSfrLimit, Color( .0, .0, .0, .9)) ; + #endif + + // effettuo un Offset della regione del raggio utensile a cui sommo eventuale sovramateriale + double dOffs = m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL ; + PtrOwner pSfrSafe( pSfrPock->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrSafe) || ! pSfrSafe->IsValid()) + return false ; + // verifico se il collegamento lineare passa nella regione limite + CRVCVECTOR ccClass ; + if ( ! pSfrSafe->GetCurveClassification( *pCompoLink, EPS_SMALL, ccClass)) + return false ; + if ( ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_OUT) { + for ( int nCrv = 0 ; nCrv < pCompoLink->GetCurveCount() ; ++ nCrv) + pCompoLink->SetCurveTempParam( nCrv, FEED_MAX_COEFF) ; + return true ; + } + // eseguo un percorso di raccordo mediante smussamento sulla regione + else { + // porto tutto in un piano locale XY + Point3d ptC ; pSfrPock->GetCentroid( ptC) ; + Frame3d frXY ; + if ( ! frXY.Set( ptC, pSfrPock->GetNormVersor())) + return false ; + pCompoLink->ToLoc( frXY) ; + pCompoLink->SetExtrusion( Z_AX) ; + pSfrSafe->ToLoc( frXY) ; + + // recupero il vettore delle curve della regione + ICURVEPOVECTOR vSfrOffsLoops ; + for ( int nC = 0 ; nC < pSfrSafe->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrSafe->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCrvLoop( pSfrSafe->GetLoop( nC, nL)) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid() || + ! vSfrOffsLoops.emplace_back( Release( pCrvLoop)) || ! vSfrOffsLoops.back()->IsValid()) + return false ; + } + } + if ( vSfrOffsLoops.empty()) + return false ; + + #if DEBUG_USER_PTSTART + int nLay1 = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, Frame3d()) ; + int nCrv = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, pCompoLink->Clone()) ; + m_pGeomDB->SetMaterial( nCrv, BLUE) ; + int nSfrLimit = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, pSfrSafe->Clone()) ; + m_pGeomDB->SetMaterial( nSfrLimit, Color( .0, .0, .0, .9)) ; + for ( int i = 0 ; i < ssize( vSfrOffsLoops) ; ++ i) { + int nLoopId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, vSfrOffsLoops[i]->Clone()) ; + m_pGeomDB->SetMaterial( nLoopId, RED) ; + } + #endif + + // definisco le curve di calcolo e di verifica + PtrOwner pCompo( pCompoLink->Clone()) ; + PtrOwner pCompoHelp( pCompoLink->Clone()) ; + if ( IsNull( pCompo) || ! pCompo->IsValid() || IsNull( pCompoHelp) || ! pCompoHelp->IsValid()) + return false ; + + // scorro il vettore delle curve di bordo + for ( int i = 0 ; i < ssize( vSfrOffsLoops) ; ++ i) { + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCompo, *vSfrOffsLoops[i]) ; + intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; + if ( ! pCompoHelp->Clear()) + return false ; + // per ogni intersezione con l'offset dell'isola, recupero le parti esterne e raccordo esternamente le parti interne + for ( int j = 0 ; j < ssize( ccClass) ; ++ j) { + // se ho intersezione spezzo il segmento + if ( ccClass[j].nClass == CRVC_OUT) { + Point3d ptS ; pCompo->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; + double dOffS ; vSfrOffsLoops[i]->GetParamAtPoint( ptS, dOffS) ; + Point3d ptE ; pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; + double dOffE ; vSfrOffsLoops[i]->GetParamAtPoint( ptE, dOffE) ; + // recupero i due possibili percorsi e uso il più corto + PtrOwner pCrvA( vSfrOffsLoops[i]->CopyParamRange( dOffS, dOffE)) ; + PtrOwner pCrvB( vSfrOffsLoops[i]->CopyParamRange( dOffE, dOffS)) ; + if ( IsNull( pCrvA) || IsNull( pCrvB)) + return false ; + double dLenA ; pCrvA->GetLength( dLenA) ; + double dLenB ; pCrvB->GetLength( dLenB) ; + if ( dLenA < dLenB) + pCompoHelp->AddCurve( Release( pCrvA)) ; + else { + pCrvB->Invert() ; + pCompoHelp->AddCurve( Release( pCrvB)) ; + } + } + // se non interseco + else + pCompoHelp->AddCurve( pCompo->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + } + pCompo->Clear() ; + pCompo->AddCurve( pCompoHelp->Clone()) ; + } + if ( pCompo->IsValid()) { + pCompoLink->Clear() ; + pCompoLink->AddCurve( Release( pCompo)) ; + for ( int nCrv = 0 ; nCrv < pCompoLink->GetCurveCount() ; ++ nCrv) + pCompoLink->SetCurveTempParam( nCrv, FEED_MAX_COEFF) ; + pCompoLink->ToGlob( frXY) ; + return true ; + } + } + } + + return false ; +} + // debug functions //---------------------------------------------------------------------------- void diff --git a/PocketingNT.h b/PocketingNT.h index f846f65..78b19cb 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -21,6 +21,7 @@ #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkIntersPlaneSurfTm.h" +#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h" // struttura informazioni sui singoli percorsi struct PathInfoPO { @@ -109,15 +110,17 @@ class PocketingNT : public Machining bool GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const ISurfTriMesh* pStmTrim, ICURVEPLIST& lstPC) ; bool SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, bool* pbSomeOpen = nullptr) ; bool SetSfrLoopsAllTempProp( int nSfrId, ISurfFlatRegion* pSfr) ; - bool ResetCurveAllTempProp( ICurve* pCurve) ; + bool ResetCurveAllTempProp( ICurve* pCurve, bool bClose = true) ; bool Chain( int nGrpDestId) ; ISurfTriMesh* GetRaw( void) ; ISurfTriMesh* GetStmTrim( void) ; ISurfTriMesh* GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExtr) ; ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) ; - ISurfFlatRegion* GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool) ; + ISurfFlatRegion* GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool, + const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil = nullptr) ; + Point3d GetStartPointByUser( const ISurfFlatRegion* pSfr) const ; Point3d GetStartPointsByHead( const STEPINFOPOVECTOR& vStepInfo) const ; - Point3d GetStartPointsFromSteps( const STEPINFOPOVECTOR& vStepInfo, int nCrvType) const ; + Point3d GetStartPointsBySteps( const STEPINFOPOVECTOR& vStepInfo, int nCrvType) const ; bool ChooseRawPart( const ISurfFlatRegion* pSfrChunk, ISurfTriMesh* pStm) const ; bool ManageOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmPart) ; bool GetHomogeneousParts( const ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCrvs) const ; @@ -186,6 +189,9 @@ class PocketingNT : public Machining bool AddTangentLinesForToolCompensation( ICurveComposite* pCompoPath, const Vector3d& vtTool, const ISurfFlatRegion* pSfrLimit, bool bWithEndGuide) const ; bool AssignPropsToCamDataForToolCompensation( int nId, bool bLineIn, bool bLineOut, bool bToolAtLeft) ; + bool CalcLinkByStartUserPoint( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrLimit, const Point3d& ptStart, + const Point3d& ptEnd, ICurveComposite* pCompoLink) const ; + // debug void DebugDrawSfr( const ISurfFlatRegion* pSfr, bool bUniform, int nlayer = GDB_ID_ROOT) ; void DebugDrawLoop( const ICurveComposite* pCrvCompo, int nLayer, bool bUniform) ;