From 06180175ebe2f375005a0a816d87b7fdec2b89ec Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 7 Jul 2026 11:37:29 +0200 Subject: [PATCH] EgtMachKernel : - in SawFinishing aggiunto sottotipo "Section" - in SawFinishing correzioni varie. --- OperUserNotesConst.h | 2 + SawFinishing.cpp | 556 +++++++++++++++++++++++++++++++++++++++++-- SawFinishing.h | 11 +- 3 files changed, 548 insertions(+), 21 deletions(-) diff --git a/OperUserNotesConst.h b/OperUserNotesConst.h index 74cc255..1369a31 100644 --- a/OperUserNotesConst.h +++ b/OperUserNotesConst.h @@ -65,6 +65,8 @@ static const std::string UN_EWE = "EWE" ; // Solo per SawFinishing e SawRoughing static const std::string UN_EXTEND = "Extend" ; +static const std::string UN_RB_DIST = "RawBottomDist" ; // per SawFinishing Section +static const std::string UN_LIMIT_ANG = "LimitAngle" ; // per SawFinishing Section // Solo per SurfFinishing static const std::string UN_SKIPMAXDOWN = "SkipMaxDown" ; diff --git a/SawFinishing.cpp b/SawFinishing.cpp index b98eb61..c62b64b 100644 --- a/SawFinishing.cpp +++ b/SawFinishing.cpp @@ -58,10 +58,12 @@ using namespace std ; // 2714 = "Error in SawFinishing : link outstroke xx" // 2715 = "Error in SawFinishing : post apply not calculable" // 2716 = "Error in SawFinishing : special apply not calculable" +// 2717 = "Error in SawFinishing : CalculateSectionToolPath failed" // 2751 = "Warning in SawFinishing : Skipped entity (xx)" // 2752 = "Warning in SawFinishing : No machinable path" // 2753 = "Warning in SawFinishing : Tool name changed (xx)" // 2754 = "Warning in SawFinishing : Tool data changed (xx)" +// 2755 = "Warning in SawFinishing : Link not compatible with extension" //---------------------------------------------------------------------------- const string MCH_SECTION = "Sect" ; @@ -588,6 +590,12 @@ SawFinishing::Apply( bool bRecalc, bool bPostApply) } } } + else if ( m_Params.m_nSubType == SAWFIN_SUB_SECTION) { + if ( ! CalculateStraightSectionToolPath( nAuxId, nClId)) { + m_pMchMgr->SetLastError( 2717, "Error in SawFinishing : CalculateSectionToolPath failed") ; + return false ; + } + } // assegno ingombri dei vari percorsi di lavorazione e della lavorazione nel suo complesso CalcAndSetBBox( nClId) ; @@ -1082,6 +1090,11 @@ SawFinishing::CalculateStraightAlongToolPath( int nAuxId, int nClId) bool bExtend ; if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_EXTEND, bExtend)) bExtend = true ; + // se estensione non presente e Link di tipo Extended, lo forzo come Center + if ( ! bExtend && m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { + m_pMchMgr->SetWarning( 2655, "Warning in SawRoughing : Link not compatible with extension") ; + m_Params.m_nLeadLinkType = SAWFIN_LL_CENT ; + } // Recupero ed elaboro la linea guida Point3d ptGdStart, ptGdEnd ; @@ -1272,6 +1285,11 @@ SawFinishing::CalculateStraightAcrossToolPath( int nAuxId, int nClId) bool bExtend ; if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_EXTEND, bExtend)) bExtend = true ; + // se estensione non presente e Link di tipo Extended, lo forzo come Center + if ( ! bExtend && m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { + m_pMchMgr->SetWarning( 2655, "Warning in SawRoughing : Link not compatible with extension") ; + m_Params.m_nLeadLinkType = SAWFIN_LL_CENT ; + } // Recupero ed elaboro la linea guida Point3d ptGdStart, ptGdEnd ; @@ -1763,7 +1781,507 @@ SawFinishing::CalculateCurvedAcrossToolPath( int nAuxId, int nClId) //---------------------------------------------------------------------------- bool -SawFinishing::CalculateSection( int nSectGrpId, ICurve*& pSect) +SawFinishing::CalculateStraightSectionToolPath( int nAuxId, int nClId) +{ + // recupero il riferimento globale delle sezioni + int nSectGrpId = m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_SECTION) ; + Frame3d frSect ; m_pGeomDB->GetGroupGlobFrame( nSectGrpId, frSect) ; + // recupero il box globale delle sezioni + BBox3d b3Sect ; m_pGeomDB->GetGlobalBBox( nSectGrpId, b3Sect) ; + + // Recupero ed elaboro le sezioni per portarle ad essere la curva del centro in basso della lama + ICurve* pSect ; + if ( ! CalculateOffsetSection( nSectGrpId, frSect, pSect)) + return false ; + PtrOwner pCrv( pSect) ; + if ( IsNull( pCrv) || ! pCrv->IsValid()) + return false ; + + // Recupero da UserNotes il flag di estensione al bordo del grezzo + bool bExtend ; + if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_EXTEND, bExtend)) + bExtend = true ; + // se estensione non presente e Link di tipo Extended, lo forzo come Center + if ( ! bExtend && m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { + m_pMchMgr->SetWarning( 2655, "Warning in SawRoughing : Link not compatible with extension") ; + m_Params.m_nLeadLinkType = SAWFIN_LL_CENT ; + } + + // Recupero ed elaboro la linea guida + Point3d ptGdStart, ptGdEnd ; + Vector3d vtGdDir ; + int nGuideId = m_pGeomDB->GetFirstInGroup( m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_GUIDE)) ; + if ( ! CalculateGuideLine( nGuideId, pSect, ptGdStart, ptGdEnd, vtGdDir, nSectGrpId, bExtend)) + return false ; + if ( m_Params.m_bInvert) { + swap( ptGdStart, ptGdEnd) ; + vtGdDir.Invert() ; + } + + // recupero il box globale della linea guida + BBox3d b3Guide ; m_pGeomDB->GetGlobalBBox( nGuideId, b3Guide) ; + + // recupero il box del grezzo in globale + BBox3d b3Test ; + b3Test.Add( b3Sect) ; + b3Test.Add( b3Guide) ; + BBox3d b3Raw ; + if ( ! GetRawGlobBox( m_nPhase, b3Test, 10. * EPS_SMALL, b3Raw) || b3Raw.IsEmpty()) { + m_pMchMgr->SetLastError( 2703, "Error in SawFinishing : Empty RawBox") ; + return false ; + } + + // valuto l'espressione dell'affondamento + ExeLuaSetGlobNumVar( "TH", 0.) ; + ExeLuaSetGlobNumVar( "RB", b3Raw.GetMax().z - b3Raw.GetMin().z) ; + double dDepth ; + if ( ! ExeLuaEvalNumExpr( m_Params.m_sDepth, &dDepth)) { + m_pMchMgr->SetLastError( 2704, "Error in SawFinishing : Depth not computable") ; + return false ; + } + + // creo gruppo per geometria di lavorazione + int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ; + if ( nPxId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nPxId, MCH_PATH + "1_1") ; + m_pGeomDB->SetMaterial( nPxId, GREEN) ; + + // Determino versori fresa e correzione + Point3d ptSecStart ; pSect->GetStartPoint( ptSecStart) ; + Point3d ptSecEnd ; pSect->GetEndPoint( ptSecEnd) ; + Vector3d vtTool, vtCorr ; + if ( ! CalculateToolAndCorrVersors( GetToGlob( ptSecEnd - ptSecStart, frSect), m_Params.m_nHeadSide, vtTool, vtCorr)) { + m_pMchMgr->SetLastError( 2705, "Error in SawFinishing : CalculateToolAndCorrVersors") ; + return false ; + } + + // Approssimo la curva di sezione ad una spezzata + PolyLine PL ; + if ( ! pCrv->ApproxWithLines( LIN_TOL_MID, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL)) { + m_pMchMgr->SetLastError( 2706, "Error in SawFinishing : ApproxWithLines") ; + return false ; + } + // Se link standard, allungo inizio e fine della sezione dello spessore lama + if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { + // inizio + PL.Invert() ; + double dU ; + Point3d ptP ; + PL.GetLastUPoint( &dU, &ptP) ; + PL.AddUPoint( dU, ptP + Vector3d( m_TParams.m_dThick, 0., 0.)) ; + PL.Invert() ; + // fine + PL.GetLastUPoint( &dU, &ptP) ; + PL.AddUPoint( dU, ptP - Vector3d( m_TParams.m_dThick, 0., 0.)) ; + } + // La porto in globale + PL.ToGlob( frSect) ; + // traslo la sezione lungo la direzione della guida per farla coicidere con il suo punto iniziale + PL.Translate( ( ( ptGdStart - GetToGlob( ptSecStart, frSect)) * vtGdDir) * vtGdDir) ; + + // Imposto dati comuni + SetPathId( nPxId) ; + SetToolDir( vtTool) ; + SetCorrAuxDir( vtCorr) ; + + // assegno il vettore estrazione al gruppo del percorso + m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ; + + // recupero la TriMesh del grezzo in globale + PtrOwner pStmRaw( CreateSurfTriMesh()) ; + if ( IsNull( pStmRaw)) + return false ; + pStmRaw->AdjustTopology() ; + 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) { + // 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) ; + } + + // Inizializzo contatore tagli + m_nCuts = 0 ; + + // Calcolo le passate + double dStep = max( m_Params.m_dSideStep, 10. * EPS_SMALL) ; + double dL = Dist( ptGdStart, ptGdEnd) ; + int nStep = static_cast( ceil( dL/dStep)) ; + dStep = dL / nStep ; + Point3d ptP ; + for ( int i = 0 ; i <= nStep ; ++ i) { + // vettore di spostamento + Vector3d vtMove = vtGdDir * ( i * dStep) ; + // se link Extended, allora estendo il percorso fino alla dimensione del grezzo + if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { + PL.Translate( vtMove) ; + if ( ! ExtendPathToRaw( PL, pStmRaw, m_TParams.m_dThick)) + return false ; + PL.Translate( - vtMove) ; + } + // lavoro la sezione + if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) { + if ( ! CalcAcrossOneWayCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth)) + return false ; + } + else { + bool bFirst = ( i == 0) ; + if ( ! CalcAcrossZigZagCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth, bFirst)) + return false ; + } + } + // se ZigZag aggiungo risalita + if ( m_Params.m_nStepType == SAWFIN_ST_ZIGZAG) { + // recupero distanza di sicurezza + double dSafeZ = GetSafeZ() ; + // lunghezza di approccio/retrazione + double dAppr = m_Params.m_dStartPos ; + // aggiungo retrazione + Point3d ptEnd ; + if ( ! GetCurrPos( ptEnd)) + return false ; + double dElev = b3Raw.GetMax().z - ptEnd.z ; + if ( ! AddRetract( ptEnd, vtCorr, dSafeZ, dElev, dAppr)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SawFinishing::ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double dExtraOut) const +{ + // se grezzo non valido, non estendo nulla + if ( pStmRaw == nullptr || ! pStmRaw->IsValid() || pStmRaw->GetTriangleCount() == 0) + return true ; + + // recupero gli estremi della PolyLine e il versore di estensione + Point3d ptS ; PL.GetFirstPoint( ptS) ; + Point3d ptE ; PL.GetLastPoint( ptE) ; + Vector3d vtExt = ( ptE - ptS) ; + vtExt.z = 0. ; + if ( ! vtExt.Normalize()) + return false ; + + const double LINE_LEN = 1e5 ; + const double COS_SMALL = sin( EPS_ANG_SMALL * DEGTORAD) ; + + // verifico se posso estendere l'inizio + ILSIVECTOR vInfo ; + if ( ! IntersLineSurfTm( ptS, - vtExt, LINE_LEN, *pStmRaw, vInfo)) + return false ; + if ( ! vInfo.empty()) { + for ( int i = 0 ; i < ssize( vInfo) ; ++ i) { + // se c'è intersezione ed esco dalla superficie + if ( vInfo[i].nILTT != ILTT_NO && vInfo[i].dCosDN > COS_SMALL) { + // aggiungo il punto di intersezione con il grezzo + PL.AddUPoint( 0., vInfo[i].ptI, false) ; + // aggiungo un punto per estensione aggiuntiva + if ( dExtraOut > EPS_SMALL) + PL.AddUPoint( 0., vInfo[i].ptI - vtExt * dExtraOut, false) ; + break ; + } + } + } + + // allo stesso modo, verifico se posso estendere la fine + vInfo.clear() ; + if ( ! IntersLineSurfTm( ptE, vtExt, LINE_LEN, *pStmRaw, vInfo)) + return false ; + if ( ! vInfo.empty()) { + for ( int i = 0 ; i < ssize( vInfo) ; ++ i) { + // se c'è intersezione ed esco dalla superficie + if ( vInfo[i].nILTT != ILTT_NO && vInfo[i].dCosDN > COS_SMALL) { + // aggiungo il punto di intersezione con il grezzo + PL.AddUPoint( 0., vInfo[i].ptI, true) ; + // aggiungo un punto per estensione aggiuntiva + if ( dExtraOut > EPS_SMALL) + PL.AddUPoint( 0., vInfo[i].ptI + vtExt * dExtraOut, true) ; + break ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SawFinishing::TrimVerticalSectionBounds( ICurveComposite* pSect, double dAngDeg) const +{ + // verifico che la curva sia valida + if ( pSect == nullptr || ! pSect->IsValid()) + return false ; + + // -->! NB. La sezione è già orientata per X decrescente e nel piano XY + // splitto gli archi con angolo maggiore della tolleranza + VerifyArcs( pSect, dAngDeg) ; + + // elimino tutti i tratti all'inizio della sezione + const double COS_ANG_TOL = cos( ( dAngDeg) * DEGTORAD) ; + for ( int i = 0 ; i < pSect->GetCurveCount() ; ++ i) { + const ICurve* pCrv = pSect->GetCurve( i) ; + if ( pCrv != nullptr && pCrv->IsValid()) { + // se Linea + if ( pCrv->GetType() == CRV_LINE) { + Vector3d vtDir ; pCrv->GetStartDir( vtDir) ; + Vector3d vtPerp = vtDir ; vtPerp.Rotate( Z_AX, - ANG_RIGHT) ; + if ( abs( vtPerp * Y_AX) > COS_ANG_TOL) { + // se prima linea in tolleranza, elimino tutte le curve precedenti + if ( i > 0) + pSect->TrimStartAtParam( 1. * i) ; + break ; + } + } + // se Arco + else if ( pCrv->GetType() == CRV_ARC) { + const ICurveArc* pArc = GetCurveArc( pCrv) ; + if ( pArc == nullptr) + return false ; + Point3d ptCenter = pArc->GetCenter() ; + Point3d ptStart ; pArc->GetStartPoint( ptStart) ; + Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; + Vector3d vtDirS = ( ptStart - ptCenter) ; vtDirS.Normalize() ; + Vector3d vtDirE = ( ptEnd - ptCenter) ; vtDirE.Normalize() ; + bool bOkStart = ( abs( vtDirS * Y_AX) > COS_ANG_TOL) ; + bool bOkEnd = ( abs( vtDirE * Y_AX) > COS_ANG_TOL) ; + // se inizio valido, allora non ho bisogno di modificare l'arco corrente (elimino eventuali curve precedenti) + if ( bOkStart) { + if ( i > 0) + pSect->TrimStartAtParam( 1. * i) ; + break ; + } + // se nè inizio nè fine validi, passo il controllo alla curva successiva + if ( ! bOkEnd) + continue ; + // se inizio non valido, ma fine in tolleranza, determino il nuovo punto iniziale della curva e trimmo tutto in precedenza + else { + // Trim iniziale + Point3d ptNewStart = ptCenter + pArc->GetRadius() * Y_AX ; + ptNewStart.Rotate( ptCenter, Z_AX, - dAngDeg) ; + double dUTrim = 0. ; + pSect->GetParamAtPoint( ptNewStart, dUTrim, 10. * EPS_SMALL) ; + pSect->TrimStartAtParam( dUTrim) ; + break ; + } + } + } + } + + // ripeto lo stesso ragionemento per il tratto finale + if ( ! pSect->IsValid()) + return false ; + for ( int i = pSect->GetCurveCount() - 1 ; i >= 0 ; -- i) { + const ICurve* pCrv = pSect->GetCurve( i) ; + if ( pCrv != nullptr && pCrv->IsValid()) { + // se Linea + if ( pCrv->GetType() == CRV_LINE) { + Vector3d vtDir ; pCrv->GetStartDir( vtDir) ; + Vector3d vtPerp = vtDir ; vtPerp.Rotate( Z_AX, - ANG_RIGHT) ; + if ( abs( vtPerp * Y_AX) > COS_ANG_TOL) { + // se linea in tolleranza, elimino tutte le successive + if ( i < pSect->GetCurveCount() - 1) + pSect->TrimEndAtParam( 1. * ( i + 1)) ; + break ; + } + } + // se Arco + else if ( pCrv->GetType() == CRV_ARC) { + const ICurveArc* pArc = GetCurveArc( pCrv) ; + if ( pArc == nullptr) + return false ; + Point3d ptCenter = pArc->GetCenter() ; + Point3d ptStart ; pArc->GetStartPoint( ptStart) ; + Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; + Vector3d vtDirS = ( ptStart - ptCenter) ; vtDirS.Normalize() ; + Vector3d vtDirE = ( ptEnd - ptCenter) ; vtDirE.Normalize() ; + bool bOkStart = ( abs( vtDirS * Y_AX) > COS_ANG_TOL) ; + bool bOkEnd = ( abs( vtDirE * Y_AX) > COS_ANG_TOL) ; + // se fine valido, non ho bisogno di modificare l'arco corrente (elimino eventuali curve precedenti) + if ( bOkEnd) { + if ( i < pSect->GetCurveCount() - 1) + pSect->TrimEndAtParam( 1. * ( i + 1)) ; + break ; + } + // se nè inizio nè fine validi, passo il controllo alla curva successiva + if ( ! bOkStart) + continue ; + // se inizio no valido, ma fine in tolleranza, determino il nuovo punto finale della curva e trimmo tutto in successione + else { + // Trim Finale + Point3d ptNewEnd = ptCenter + pArc->GetRadius() * Y_AX ; + ptNewEnd.Rotate( ptCenter, Z_AX, dAngDeg) ; + double dUTrim = pSect->GetCurveCount() - 1 ; + pSect->GetParamAtPoint( ptNewEnd, dUTrim, 10. * EPS_SMALL) ; + pSect->TrimEndAtParam( dUTrim) ; + break ; + } + } + } + } + if ( pSect->IsValid()) { + pSect->MergeCurves( LIN_TOL_MID, ANG_TOL_STD_DEG) ; + return true ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +bool +SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect) const +{ + // recupero le sezioni + ICURVEPVECTOR vpSects ; + int nSectId = m_pGeomDB->GetFirstInGroup( nSectGrpId) ; + while ( nSectId != GDB_ID_NULL) { + // recupero il puntatore alla curva + vpSects.emplace_back( ::GetCurve( m_pGeomDB->GetGeoObj( nSectId))) ; + if ( vpSects.back() == nullptr) + return false ; + // passo alla successiva + nSectId = m_pGeomDB->GetNext( nSectId) ; + } + + // elimino eventuali sottosquadra + ICURVEPOVECTOR vpNucCrvs ; + vpNucCrvs.reserve( vpSects.size()) ; + for ( const auto& pSect : vpSects) { + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo) || + ! pCrvCompo->AddCurve( *pSect) || + ! pCrvCompo->RemoveUndercutOnY( LIN_TOL_STD, ANG_TOL_STD_DEG)) + return false ; + + vpNucCrvs.emplace_back( Release( pCrvCompo)) ; + } + + // calcolo ordinamento delle curve secondo la X decrescente + typedef pair INDASC ; // coppia indice, ascissa + typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa + INDASCVECTOR vIAsc ; + vIAsc.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + Point3d ptStart ; + if ( ! vpNucCrvs[i]->GetStartPoint( ptStart)) + return false ; + vIAsc.emplace_back( i, ptStart.x) ; + } + sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; + + // definisco la regione non oltrepassabile dal fondo della lama + BBox3d b3Raw ; + if ( ! GetCurrRawsGlobBox( b3Raw) || b3Raw.IsEmpty()) { + m_pMchMgr->SetLastError( 2703, "Error in SawFinishing : Empty RawBox") ; + return false ; + } + b3Raw.ToLoc( frSec) ; + Point3d ptMin = b3Raw.GetMin(), + ptMax = b3Raw.GetMax() ; + double dMinY = 5. ; + double dTabDist = 0. ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_RB_DIST, dTabDist) && dTabDist > dMinY) + dMinY = dTabDist ; + const double LINE_EXT = 1e5 ; + Point3d ptLineMinYStart = Point3d( ptMin.x - LINE_EXT, ptMin.y + dMinY, 0.) ; + Point3d ptLineMinYEnd = Point3d( ptMax.x + LINE_EXT, ptMin.y + dMinY, 0.) ; + PtrOwner pCompoRegLimit( CreateCurveComposite()) ; + if ( IsNull( pCompoRegLimit)) + return false ; + pCompoRegLimit->AddPoint( ptLineMinYStart) ; + pCompoRegLimit->AddLine( ptLineMinYStart - Y_AX * LINE_EXT) ; + pCompoRegLimit->AddLine( ptLineMinYEnd - Y_AX * LINE_EXT) ; + pCompoRegLimit->AddLine( ptLineMinYEnd) ; + pCompoRegLimit->Close() ; + PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->AddExtLoop( ::Release( pCompoRegLimit))) + return false ; + + // unisco le diverse curve (ora aperte) in un unico profilo + PtrOwner pCurve( CreateCurveComposite()) ; + if ( IsNull( pCurve)) + return false ; + bool bFirst = true ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + if ( ! bFirst) { + Point3d ptStart ; + if ( ! vpNucCrvs[vIAsc[i].first]->GetStartPoint( ptStart) || + ! pCurve->AddLine( ptStart)) + return false ; + } + if ( ! pCurve->AddCurve( Release( vpNucCrvs[vIAsc[i].first]))) + return false ; + bFirst = false ; + } + + // elimino tutti i tratti all'inizio e alla fine della sezione con tangenza sotto i 60deg + double dAngDegSplit = 60. ; + double dAngUN = 0. ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_LIMIT_ANG, dAngUN)) + dAngDegSplit = max( 15. - EPS_ANG_SMALL, dAngUN) ; + if ( ! TrimVerticalSectionBounds( pCurve, dAngDegSplit)) + return false ; + + // offset radiale delle sezioni per il sovramateriale e il raggio utensile + OffsetCurve OffsCrv ; + pCurve->Translate( - Y_AX * m_TParams.m_dDiam / 2.) ; + OffsCrv.Make( pCurve, m_TParams.m_dDiam / 2. + GetOffsR(), ICurve::OFF_FILLET) ; + PtrOwner pOvrCrv( OffsCrv.GetLongerCurve()) ; + + // la curva ricavata deve essere sufficientemente distante dal fondo del grezzo + CRVCVECTOR ccClass ; + if ( ! pSfrLimit->GetCurveClassification( *pOvrCrv, EPS_SMALL, ccClass)) + return false ; + ICURVEPOVECTOR vpCrvOut ; vpCrvOut.reserve( ccClass.size()) ; + for ( int i = 0 ; i < ssize( ccClass) ; ++ i) { + if ( ccClass[i].nClass != CRVC_IN) + vpCrvOut.emplace_back( pOvrCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ; + } + erase_if( vpCrvOut, []( const ICurve* pCrv) { return ( pCrv == nullptr || ! pCrv->IsValid()) ; }) ; + if ( vpCrvOut.empty()) + return false ; + pCurve->Clear() ; + bFirst = true ; + for ( int i = 0 ; i < ssize( vpCrvOut) ; ++ i) { + if ( ! bFirst) { + Point3d ptStart ; + if ( ! vpCrvOut[i]->GetStartPoint( ptStart) || ! pCurve->AddLine( ptStart)) + return false ; + } + if ( ! pCurve->AddCurve( Release( vpCrvOut[i]))) + return false ; + bFirst = false ; + } + + // eseguo trim (se richiesto) + if ( IsNull( pCurve) || ! TrimSection( pCurve)) + return false ; + + pSect = Release( pCurve) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SawFinishing::CalculateSection( int nSectGrpId, ICurve*& pSect) const { // recupero le sezioni ICURVEPVECTOR vpSects ; @@ -1845,7 +2363,7 @@ SawFinishing::CalculateSection( int nSectGrpId, ICurve*& pSect) //---------------------------------------------------------------------------- bool -SawFinishing::TrimSection( ICurve* pCrv) +SawFinishing::TrimSection( ICurve* pCrv) const { // se parametri di accorciamento iniziale e finale sono nulli, non faccio alcunché if ( m_Params.m_dStartAddLen > - EPS_SMALL && m_Params.m_dEndAddLen > -EPS_SMALL) @@ -2004,9 +2522,9 @@ SawFinishing::CalculateSectElevation( const Polygon3d& pgFacet, double& dElev) c // calcolo l'elevazione iniziale double dCurrElev = 0. ; if ( ! PolygonElevationInClosedSurfTm( pgFacetL, *pStm, true, dCurrElev)) - return false ; + return false ; if ( dCurrElev > EPS_SMALL) - vRawElev.emplace_back( nStmId, dCurrElev) ; + vRawElev.emplace_back( nStmId, dCurrElev) ; } } // passo al grezzo successivo @@ -2038,9 +2556,9 @@ SawFinishing::CalculateSectElevation( const Polygon3d& pgFacet, double& dElev) c } b3Tool.Expand( MAX_DIST_RAW) ; // verifico la reale interferenza dell'utensile con i diversi grezzi - for ( int i = 0 ; i < int( vRawElev.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vRawElev) ; ++ i) { // box del grezzo - BBox3d b3Raw ; + BBox3d b3Raw ; m_pGeomDB->GetGlobalBBox( vRawElev[i].first, b3Raw) ; // confronto con il box dell'utensile nella posizione precedente BBox3d b3CurrTool = b3Tool ; @@ -2085,6 +2603,7 @@ SawFinishing::CalculateGuideLine( int nGuideId, const ICurve* pSect, Point3d& pt nSectId = m_pGeomDB->GetNext( nSectId) ; } // per ogni sezione calcolo eventuale elevazione + double dMaxStartElev = 0., dMaxEndElev = 0. ; for ( const ICurve* pCrvSect : vpSects) { // applico offset radiale OffsetCurve OffsCrv ; @@ -2103,22 +2622,26 @@ SawFinishing::CalculateGuideLine( int nGuideId, const ICurve* pSect, Point3d& pt if ( ! pgFacet.FromPolyLine( PL)) return false ; // calcolo l'estensione della guida fino alla proiezione in eccesso del grezzo - double dSectStartElev = 0. ; - if ( ! CalculateSectElevation( pgFacet, dSectStartElev)) + double dCurrStartElev = 0. ; + if ( ! CalculateSectElevation( pgFacet, dCurrStartElev)) return false ; + if ( dCurrStartElev > dMaxStartElev) + dMaxStartElev = dCurrStartElev ; // calcolo l'estensione della guida fino alla proiezione in eccesso del grezzo pgFacet.Translate( ptGdEnd - ptGdStart) ; pgFacet.Invert() ; - double dSectEndElev = 0. ; - if ( ! CalculateSectElevation( pgFacet, dSectEndElev)) + double dCurrEndElev = 0. ; + if ( ! CalculateSectElevation( pgFacet, dCurrEndElev)) return false ; - // estendo la guida delle quantità calcolate - if ( dSectStartElev > EPS_SMALL) - ptGdStart -= ( vtGdDir * dSectStartElev) ; - if ( dSectEndElev > EPS_SMALL) - ptGdEnd += ( vtGdDir * dSectEndElev) ; + if ( dCurrEndElev > dMaxEndElev) + dMaxEndElev = dCurrEndElev ; } } + // estendo la guida nel punto trovato + if ( dMaxEndElev > EPS_SMALL) + ptGdEnd += ( vtGdDir * dMaxEndElev) ; + if ( dMaxStartElev > EPS_SMALL) + ptGdStart -= ( vtGdDir * dMaxStartElev) ; } return true ; @@ -3147,8 +3670,7 @@ SawFinishing::AddRetract( const Point3d& ptP, const Vector3d& vtCorr, //---------------------------------------------------------------------------- bool -SawFinishing::CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide, - Vector3d& vtTool, Vector3d& vtCorr) +SawFinishing::CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide, Vector3d& vtTool, Vector3d& vtCorr) const { // Versore fresa : annullo la componente in Z e normalizzo vtTool = vtTang ; diff --git a/SawFinishing.h b/SawFinishing.h index bef5a46..931a9ea 100644 --- a/SawFinishing.h +++ b/SawFinishing.h @@ -85,9 +85,13 @@ class SawFinishing : public Machining bool CalculateStraightAcrossToolPath( int nAuxId, int nClId) ; bool CalculateCurvedAlongToolPath( int nAuxId, int nClId) ; bool CalculateCurvedAcrossToolPath( int nAuxId, int nClId) ; - bool CalculateSection( int nSectGrpId, ICurve*& pSect) ; - bool TrimSection( ICurve* pCrv) ; + bool CalculateStraightSectionToolPath( int nAuxId, int nClId) ; + bool TrimVerticalSectionBounds( ICurveComposite* pSect, double dAngDeg) const ; + bool CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect) const ; + bool CalculateSection( int nSectGrpId, ICurve*& pSect) const ; + bool TrimSection( ICurve* pCrv) const ; bool AdaptGuideLineToRaw( Point3d& ptGdStart, Point3d& ptGdEnd, const Vector3d& vtGdDir, bool bExtend, const ISurfTriMesh* pStmRaw) const ; + bool ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double dExtraOut) const ; bool CalculateSectElevation( const Polygon3d& pgFacet, double& dElev) const ; bool CalculateGuideLine( int nGuideId, const ICurve* pSect, Point3d& ptGdStart, Point3d& ptGdEnd, Vector3d& vtGdDir, int nSectGrpId, bool bExtendToRawBox) const ; @@ -120,8 +124,7 @@ class SawFinishing : public Machining bool AddCornerApproach( const Point3d& ptP, const Vector3d& vtCorr, const Vector3d& vtPrev, double dSafeZ, double dElev, double dAppr) ; bool AddRetract( const Point3d& ptP, const Vector3d& vtCorr, double dSafeZ, double dElev, double dAppr) ; - bool CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide, - Vector3d& vtTool, Vector3d& vtCorr) ; + bool CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide, Vector3d& vtTool, Vector3d& vtCorr) const ; bool GetHeightOnSection( const ICurve* pSect, double dX, double dYmin, double dYmax, double& dY) ; private :