From 3270b573a898834182433e5e9160b1497cbb61ba Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Wed, 3 Jul 2024 13:23:52 +0200 Subject: [PATCH 1/7] EgtGeomKernel : - in CalcPocketing aggiunte funzioni di Feed e migliorati i controlli sui lati aperti. --- CalcPocketing.cpp | 829 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 726 insertions(+), 103 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 3800841..5883f73 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -60,12 +60,15 @@ struct PocketParams { Point3d ptStart = P_INVALID ; // punto d'inizio Point3d ptEnd = P_INVALID ; // punto di fine SurfFlatRegion SfrLimit ; // superficie limite per estensione lati aperti - bool bCalcFeed = false ; // flag per calcolo della Feed + bool bCalcFeed = true ; // flag per calcolo della Feed double dFeed = 1000 ; // feed di riferimento per frazione double dToolFeed = 1000 ; // feed del tool } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket +static int TMP_PROP_SINGLE_CURVE = 3 ; // percorso singola curva aperta ( seguendo i chiusi) +static int TMP_PROP_CRV_OPEN_SIDE = 2 ; // segmento per entrata da fuori +static int TMP_PROP_OPT_TRAPEZOID = 4 ; // caso ottimizzato Trapezio //--------------------------------------------------------------------------- @@ -93,15 +96,47 @@ GetFeed( const PocketParams& PockParams) //---------------------------------------------------------------------------- static bool -AssignDefaultFeed( ICurveComposite* pCrv, const PocketParams& PockParams) +AssignMaxFeed( ICurveComposite* pCrv, const PocketParams& PockParams) { // controllo dei parametri - if ( pCrv == nullptr || !pCrv->IsValid() || pCrv->GetCurveCount() == 0) + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) return false ; // assegno la Feed massima ad ogni sottocurva di pCrv for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempProp( u, int( GetMaxFeed( PockParams)), 0) ; + pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; + + return true ; +} + +//--------------------------------------------------------------------------- +static bool +AssignMinFeed( ICurveComposite* pCrv, const PocketParams& PockParams) +{ + // controllo dei parametri + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) + return false ; + + // assegno la Feed minima ad ogni sottocurva di pCrv + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + + return true ; +} + +//--------------------------------------------------------------------------- +static bool +AssignCustomFeed( ICurveComposite* pCrv, const PocketParams& PockParams, double dFeed) +{ + // controllo dei parametri + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) + return false ; + // La Feed deve essere compresa tra la minima e la massima + dFeed = Clamp( dFeed, GetMinFeed( PockParams), GetMaxFeed( PockParams)) ; + + // assegno la Feed ad ogni sottocurva di pCrv + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempParam( u, dFeed, 0) ; return true ; } @@ -111,7 +146,7 @@ static bool GetFeedForParam( double& dPar, const PocketParams& PockParams, double& dFeed) { /* - feed + Feed ^ | GetFeed() + --------------\ @@ -122,7 +157,7 @@ GetFeedForParam( double& dPar, const PocketParams& PockParams, double& dFeed) | * \ GetFeed() * GetSideStep() / Diam + * * | * * - 0--------------+------+---------------> Tool Working Arc + 0--------------+------+---------------> Length of working angle GetSideStep() Diam */ @@ -145,6 +180,7 @@ GetFeedForParam( double& dPar, const PocketParams& PockParams, double& dFeed) return true ; } + //---------------------------------------------------------------------------- static bool AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURVEPOVECTOR& vLAbove, @@ -157,11 +193,11 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV // controllo se il Flag per assegnare la Feed è attivo if ( ! PockParams.bCalcFeed) - return AssignDefaultFeed( pCompo, PockParams) ; + return AssignMaxFeed( pCompo, PockParams) ; // inzialmente setto la feed Minima alla curva - for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) - pCompo->SetCurveTempProp( u, int( GetMinFeed( PockParams)), 0) ; + for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) + pCompo->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; // se è un link tra livelli diversi, allora esco ( con Feed Minima ) if ( bIsLink) { @@ -222,8 +258,11 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV pSfrRectUp->GetCurveClassification( *vAddedLinks[l], EPS_SMALL, ccClass) ; for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { if (( ccClass[i].nClass == CRVC_IN && bIsDown) || - ( ccClass[i].nClass == CRVC_OUT && ! bIsDown)) - vAllInt.emplace_back( GetCurveComposite( vAddedLinks[l]->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; + ( ccClass[i].nClass == CRVC_OUT && ! bIsDown)) { + PtrOwner pCrvInt( ConvertCurveToComposite( vAddedLinks[l]->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; + if ( ! IsNull( pCrvInt) || pCrvInt->IsValid()) + vAllInt.emplace_back( Release( pCrvInt)) ; + } } } } @@ -299,14 +338,293 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV if ( ! bIsLink) { for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) { if ( IsEven( u) == bFMax) - pCompo->SetCurveTempProp( u, int( GetMaxFeed( PockParams)) , 0) ; + pCompo->SetCurveTempParam( u, GetMaxFeed( PockParams) , 0) ; else - pCompo->SetCurveTempProp( u, int( GetMinFeed( PockParams)), 0) ; + pCompo->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; } } return true ; } +//---------------------------------------------------------------------------- +static bool +CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll) +{ + // controllo dei parametri + if (( pCrv == nullptr || pCrvOri == nullptr || dToll < EPS_SMALL)) + return false ; + nStat = 1 ; // 0 -> no overlap | 1 -> overlap + + // controllo se una sottocurva della composita è abbastanza vicina a tutti i punti trovati + const double nMAX = 10.0 ; + for ( int i = 0 ; i <= nMAX ; ++i) { + double dPar = i / nMAX ; + Point3d ptC ; pCrv->GetPointD1D2( dPar, ICurve::FROM_PLUS, ptC) ; + if ( ! pCrvOri->IsPointOn( ptC, dToll)) { + nStat = 0 ; + return true ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AssignFeedForOpenEdge( ICurveComposite* pCrv, const ICurveComposite* pCrvOF_orig, + const PocketParams& PockParams) +{ + // se non rischiesto il calcolo della Feed, lascio quella standard + if ( ! PockParams.bCalcFeed) + return AssignMaxFeed( pCrv, PockParams) ; + + // controllo se qualche curva passa sopra ad un lato aperto... + if ( pCrvOF_orig != nullptr ) { + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + const ICurve* pCrv_u = pCrv->GetCurve( u) ; + if ( pCrv_u == nullptr) + return false ; + int nStat = -1 ; + if ( CheckSimpleOverlap( pCrv_u, pCrvOF_orig, nStat, 1500 * EPS_SMALL) && nStat == 1) { + double dFeed = GetMinFeed( PockParams) ; + double dPar = PockParams.dRad ; + if ( ! GetFeedForParam( dPar, PockParams, dFeed)) + return false ; + pCrv->SetCurveTempParam( u, dFeed, 0) ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs, bool bIsLink, + const ICRVCOMPOPOVECTOR& vLinks_done, const ICurveComposite* pCrv_orig, + const PocketParams& PockParams, double dToll) +{ + // controllo la validità della curva + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) + return false ; + + // controllo se il Flag per assegnare la Feed è attivo + if ( ! PockParams.bCalcFeed) + return AssignMaxFeed( pCrv, PockParams) ; + + // imposto di Default la Feed minima per ogni sottocurva + for ( int u = 0 ; u < int( pCrv->GetCurveCount()) ; ++ u) + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + + // se non ho una superificie svuotata, allora esco ( con Feed Minima) + if ( pSrfRemoved_offs == nullptr || ! pSrfRemoved_offs->IsValid() || pSrfRemoved_offs->GetChunkCount() == 0) { + // controllo eventuali sovrapposizioni con lati aperti + AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; + return true ; + } + + // clono la superificie ( valida) + PtrOwner pSrf_Removed_offs_clone( CloneSurfFlatRegion( pSrfRemoved_offs)) ; + if ( IsNull( pSrf_Removed_offs_clone) || ! pSrf_Removed_offs_clone->IsValid() || + pSrf_Removed_offs_clone->GetChunkCount() == 0) + return true ; // esco ( sempre con Feed Minima) + + // restringo la superificie in maniera appropriata + if ( bIsLink) { // se curva di Link + if ( ! pSrf_Removed_offs_clone->Offset( - PockParams.dRad + 1500 * EPS_SMALL, ICurve::OFF_CHAMFER) || + ! pSrf_Removed_offs_clone->IsValid() || pSrf_Removed_offs_clone->GetChunkCount() == 0) + return true ; // esco ( sempre con Feed Minima) + } + else if ( PockParams.dRad < PockParams.dSideStep) { // se curva di Offset e raggio utensile < Side step + if ( ! pSrf_Removed_offs_clone->Offset( PockParams.dSideStep - PockParams.dRad, ICurve::OFF_CHAMFER) || + ! pSrf_Removed_offs_clone->IsValid() || pSrf_Removed_offs_clone->GetChunkCount() == 0) + return true ; // esco ( sempre con Feed Minima) + } + + // classifico le parti interne alla superificie creata solo dagli Offset + CRVCVECTOR ccClass ; + if ( ! pSrf_Removed_offs_clone->GetCurveClassification( *pCrv, EPS_SMALL, ccClass)) + return true ; // esco ( sempre con Feed Minima) + + // creo la nuova curva con le Feed regolate + PtrOwner pCrv_new( CreateCurveComposite()) ; + if ( IsNull( pCrv_new)) + return false ; + + for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { + // recupero il tratto di curva ricavato dalla classificazione + double dCurrFeed = GetMinFeed( PockParams) ; + PtrOwner PCrv_sez( ConvertCurveToComposite( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; + if ( IsNull( PCrv_sez)) + continue ; // curva troppo piccola, passo alla successiva + // controllo se interno o fuori alla regione ( regolando quindi la Feed) + if ( ccClass[i].nClass == CRVC_IN) // se interna alla regione rimossa... + dCurrFeed = GetMaxFeed( PockParams) ; + // assegno tale Feed ad ogni sottocurva ricavata dal tratto di classificazione + for ( int u = 0 ; u < PCrv_sez->GetCurveCount() ; ++ u) + PCrv_sez->SetCurveTempParam( u, dCurrFeed, 0) ; + // aggiungo la nuova curva con la Feed regolata a quella finale + pCrv_new->AddCurve( Release( PCrv_sez)) ; + } + + // sotituisco con quanto calcolato + pCrv->Clear() ; + pCrv->AddCurve( Release( pCrv_new)) ; + + // controllo eventuali sovrapposizioni tra la curva attuale e i Link in precedenza percorsi + for ( int l = 0 ; l < int( vLinks_done.size()) ; ++ l) { + // classificazione + IntersCurveCurve intCC( *pCrv, *vLinks_done[l]) ; + for ( int i = 0 ; i < intCC.GetIntersCount() ; ++ i) { // per ogni tratto ricavato + IntCrvCrvInfo aInfo ; + if ( ! intCC.GetIntCrvCrvInfo( i, aInfo) || ! aInfo.bOverlap || + AreSamePointApprox( aInfo.IciA[0].ptI, aInfo.IciA[1].ptI)) + continue ; // passo al successivo se non c'è overlap o se i punti coicidono + // tratto precedente + PtrOwner pCrv_before( CloneCurveComposite( pCrv)) ; + if ( ! pCrv_before->TrimEndAtParam( aInfo.IciA[0].dU)) + pCrv_before->Clear() ; // se troppo piccolo, elimino + // tratto successivo + PtrOwner pCrv_after( CloneCurveComposite( pCrv)) ; + if ( ! pCrv_after->TrimStartAtParam( aInfo.IciA[1].dU)) + pCrv_after->Clear() ; // se troppo piccolo, elimino + // tratto di overlap + PtrOwner pCrv_overlap( ConvertCurveToComposite( pCrv->CopyParamRange( aInfo.IciA[0].dU, aInfo.IciA[1].dU))) ; + if ( ! IsNull( pCrv_overlap) && pCrv_overlap->IsValid()) { + for ( int u = 0 ; u < pCrv_overlap->GetCurveCount() ; ++ u) + pCrv_overlap->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; + // sostituisco unendo i 3 tratti + pCrv->Clear() ; + pCrv->AddCurve( Release( pCrv_before)) ; + pCrv->AddCurve( Release( pCrv_overlap)) ; + pCrv->AddCurve( Release( pCrv_after)) ; + } + } + } + + if ( ! bIsLink) { // ---------------- NEL CASO DI OFFSET ---------------- + // creo un intervallo con tutte le Feed Minime + Intervals IntMinFeed ; + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + double dParam ; pCrv->GetCurveTempParam( u, dParam, 0) ; + if ( abs( dParam - GetMinFeed( PockParams)) < 5 * EPS_SMALL) + IntMinFeed.Add( u, u + 1) ; + } + double dParS = EPS_SMALL ; double dParE = EPS_SMALL ; + + // a questo intervallo tolgo tutti i sottotratti di lunghezza inferiore alla tolleranza richiesta + Intervals IntMinFeed_noSmall ; + bool bFound = IntMinFeed.GetFirst( dParS, dParE) ; + while ( bFound) { + PtrOwner pCrv_Crv( pCrv->CopyParamRange( dParS, dParE)) ; + double dLen = EPS_SMALL ; pCrv_Crv->GetLength( dLen) ; + if ( dLen > dToll + 5 * EPS_SMALL) + IntMinFeed_noSmall.Add( dParS, dParE) ; + bFound = IntMinFeed.GetNext( dParS, dParE) ; + } + + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + if ( IntMinFeed_noSmall.IsInside( u + 0.5)) + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + else + pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; + } + } + else { // ---------------- NEL CASO DI LINK ---------------- + // le curve con lunghezza < dToll vanno modificate + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + double dLen = EPS_SMALL ; + pCrv->GetCurve( u)->GetLength( dLen) ; + if ( dLen < dToll + 5 * EPS_SMALL) { + PtrOwner pCrvCompo( CloneCurveComposite( pCrv)) ; + if ( ! pCrvCompo->TrimStartAtParam( u)) + pCrvCompo->Clear() ; + if ( ! pCrvCompo->TrimEndAtLen( dLen + PockParams.dRad * 2)) + pCrvCompo->Clear() ; + if ( pCrvCompo->IsValid()) { + bool bFound = false ; + for ( int uu = 1 ; uu < pCrvCompo->GetCurveCount() ; ++ uu) { + double dLenH = EPS_SMALL ; pCrvCompo->GetCurve( uu)->GetLength( dLenH) ; + if ( dLenH < dToll + 5 * EPS_SMALL) + continue ; + // cerco tra le curve successive vicine se ne trovo una con Feed Minima + double dParam ; pCrvCompo->GetCurveTempParam( uu, dParam, 0) ; + if ( abs( dParam - GetMinFeed( PockParams)) < 5 * EPS_SMALL) { + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + bFound = true ; + break ; + } + } + if ( ! bFound && u != 0) { + // arrivato qui, so che successivamente non ho curve con Feed Minima vicine + double dParam ; pCrv->GetCurveTempParam( u - 1, dParam, 0) ; + if ( abs( dParam - GetMaxFeed( PockParams)) < 5 * EPS_SMALL) + // se anche la precedente ha Feed Massima -> la curva u-esima è piccola ed Isolata + pCrv->SetCurveTempParam( u, dParam, 0) ; + } + } + else + pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + } + } + } + + // controllo eventuali sovrapposizioni con lati aperti + AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv ) +{ + // controllo della curva corrente + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) + return false ; + + // controllo se il Flag per assegnare la Feed è attivo + if ( ! PockParams.bCalcFeed) + return AssignMaxFeed( pCrv, PockParams) ; + + switch ( PockParams.nType) { + case POCKET_SPIRALIN : + if ( nOptType == 0) { // Spirale dall'Esterno + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + if ( u == 0) // prima circonferenza + pCrv->SetCurveTempProp( 0, GetMinFeed( PockParams), 0) ; + else // semi cerchi in tangenza + pCrv->SetCurveTempProp( u, GetMaxFeed( PockParams), 0) ; + } + } + else if ( nOptType == 1) { // Trapezoidi + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + } + break ; + /* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre + orientate nello stesso modo, solamente alla fine viene invertita la curva finale per la svuotatura... */ + case POCKET_SPIRALOUT : + if ( nOptType == 0) { // Spiral verso l'esterno + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze + pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + else + pCrv->SetCurveTempProp( u, GetMaxFeed( PockParams), 0) ; + } + } + else if ( nOptType == 1) { // Trapezoidi + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + } + break ; + default : + break ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool IsPointInsideSfr( const ISurfFlatRegion* pSfr, const Point3d& pt, bool& bIsInside) @@ -343,7 +661,6 @@ IsPointInsideSfr( const ISurfFlatRegion* pSfr, const Point3d& pt, bool& bIsInsid return true ; } - //---------------------------------------------------------------------------- static bool GetCurvesForOptimizedPocketing( const ISurfFlatRegion* pSfr, ICRVCOMPOPOVECTOR& vCrvExtOrig) @@ -686,8 +1003,8 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, // recupero il punto iniziale della curva Point3d ptMidOpen ; if ( bEndOrStart) { - if ( ! pCrvPath->GetEndPoint( ptMidOpen)) - return false ; + if ( ! pCrvPath->GetEndPoint( ptMidOpen)) + return false ; } else { if ( ! pCrvPath->GetStartPoint( ptMidOpen)) @@ -697,7 +1014,8 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, Point3d ptOut = ptMidOpen + vtMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; // aggiungo al ritorno l'uscita pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), 2, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima return true ; } @@ -905,18 +1223,67 @@ CreateSurfFrIncidence( const ICurveComposite* pCrv, const Vector3d& vtTanS_, con return false ; pSfrInc->Clear() ; - // creo la Fat Curve dalla curva *pCrv - PtrOwner pSfrInc_tmp( GetSurfFlatRegionFromFatCurve( pCrv->Clone(), dRad + EPS_SMALL, false, false)) ; - if ( IsNull( pSfrInc_tmp) || ! pSfrInc_tmp->IsValid()) - return false ; - pSfrInc->CopyFrom( pSfrInc_tmp) ; // pSfrInc ha sempre normale Z_AX ! - - // se la curva è chiusa, allora tutto il bordo è aperto - if ( pCrv->IsClosed()) { + // se la curva è chiusa, allora la regione di incidenza è già definita + if ( pCrv->IsClosed()) { + PtrOwner pSfrInc_tmp( GetSurfFlatRegionFromFatCurve( pCrv->Clone(), dRad + EPS_SMALL, false, false)) ; + if ( IsNull( pSfrInc_tmp) || ! pSfrInc_tmp->IsValid()) + return false ; pSfrInc->CopyFrom( pSfrInc_tmp) ; - return pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0 ; + return ( pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0) ; } + // creo la curva di Offset esterna ( deve esistere ed essere valida) + OffsetCurve OffsCrv ; + PtrOwner pOffsExt( CreateCurveComposite()) ; + if ( IsNull( pOffsExt) || + ! OffsCrv.Make( pCrv, dRad, 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( pCrv, - dRad, ICurve::OFF_FILLET)) { + PtrOwner pMyCrv( OffsCrv.GetLongerCurve()) ; + if ( ! IsNull( pMyCrv) && pMyCrv->IsValid()) + pOffsInt.Set( Release( pMyCrv)) ; + } + + // recupero gli estremi della curva aperta corrente + Point3d pt1 ; pCrv->GetEndPoint( pt1) ; + Point3d pt4 ; pCrv->GetStartPoint( pt4) ; + + // creo la regione dalle curve + PtrOwner pCrvExtLoopSurfInc( CreateCurveComposite()) ; + if ( IsNull( pCrvExtLoopSurfInc) || + ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsExt)) || + ! pCrvExtLoopSurfInc->AddLine( pt1)) + return false ; + Point3d pt5 ; pCrvExtLoopSurfInc->GetStartPoint( pt5) ; + if ( ! IsNull( pOffsInt) && pOffsInt->IsValid()) { + Point3d pt2 ; pOffsInt->GetEndPoint( pt2) ; + Point3d pt3 ; pOffsInt->GetStartPoint( pt3) ; + if ( ! pCrvExtLoopSurfInc->AddLine( pt2) || + ! pOffsInt->Invert() || + ! pCrvExtLoopSurfInc->AddCurve( Release( pOffsInt)) || + ! pCrvExtLoopSurfInc->AddLine( pt4) || + ! pCrvExtLoopSurfInc->AddLine( pt5)) + return false ; + } + else { + if ( ! pCrvExtLoopSurfInc->AddLine( pt4) || + ! pCrvExtLoopSurfInc->AddLine( pt5)) + return false ; + } + // per sicurezza... + pCrvExtLoopSurfInc->Close() ; + + // creo la regione + if ( ! pSfrInc->AddExtLoop( Release( pCrvExtLoopSurfInc))) + return false ; + return ( pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0) ; } @@ -1036,28 +1403,6 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI } pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; // passo al tratto offsettato successivo } - // 9) creo la regione squadrata da rimuovere alla regione di incidenza - OffsetCurve OffsCrvRect ; - if ( ! OffsCrvRect.Make( vpCrvs[cl], dDiamJ * 0.5, ICurve::OFF_FILLET)) - return false ; - // 10) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti - PtrOwner pOffLongestCrvRect( OffsCrvRect.GetLongerCurve()) ; - while ( ! IsNull( pOffLongestCrvRect)) { - - // 11) creo la regione di incidenza di tale curva ( "Curva a rettangolo") - PtrOwner pSfrRect( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrvRect), dDiamJ * 0.5, true, false)) ; - if ( IsNull( pSfrRect) || ! pSfrRect->IsValid()) - return false ; - // inverto se necessario - if ( AreOppositeVectorApprox( pSfrRect->GetNormVersor(), pSfrInc->GetNormVersor())) - pSfrRect->Invert() ; - - // 12) aggiorno la regione di incidenza - if ( ! pSfrInc->Subtract( *pSfrRect)) - return false ; - - pOffLongestCrvRect.Set( OffsCrvRect.GetLongerCurve()) ; // passo al tratto offsettato successivo - } } } @@ -1142,10 +1487,9 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI break ; } } - } // se bordo esterno inserisco il bordo esterno - return pCrvBorder->AddCurve( Release( pCrvNewBorder)) ; + return ( pCrvBorder->AddCurve( Release( pCrvNewBorder))) ; } // altrimenti la spezzo il loop della regione di incidenza nei punti iniziali e finali della curva aperta originale @@ -1317,27 +1661,281 @@ CheckForRemovingIsland( const ICurveComposite* pCrvIslandBorder, double dOffs, b //---------------------------------------------------------------------------- static bool -ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams) +GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes, bool& bAllRemoved) +{ + // controllo parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + bAllRemoved = false ; + + // controllo se la superficie si annulla con un controOffset del raggio utensile + PtrOwner pSfrCheck( CloneSurfFlatRegion( pSfrChunk)) ; + if ( IsNull( pSfrCheck) || ! pSfrCheck->IsValid()) + return false ; + pSfrCheck->Offset( - PockParams.dRad + 200 * EPS_SMALL, ICurve::OFF_FILLET) ; + if ( pSfrCheck->IsValid() && pSfrCheck->GetChunkCount() > 0) + return true ; // se la superficie non si annulla, allora non ricavo nessuna curva + /* + NB. Si poteva calcolare la Fat curve del raggio utensile dell'Offset di tutti i chiusi e vedere + se l'unione di queste regioni copriva interamente il Chunk attuale... così facendo rischio di + trascurare delle parti che spariscono facendo il primo Offset dei chiusi; il controllo va fatto + quindi con un contro-offset della regione complessiva + */ + + // controllo se il Chunk ha delle isole + bool bHasIslands = ( pSfrChunk->GetLoopCount( 0) > 1) ; + + // recupero il Loop esterno + PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) + return false ; + // recupero i tratti con proprietà uniformi + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvExtLoop, PockParams, vpCrvs) ; + if ( vpCrvs.size() > 1) { // unisco il primo e l'ultimo se estremi compatibili + // NB. GetHomogeneousParts() cambia il punto di inizio nel lato chiuso più lungo ( se presente) + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE)) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + // controllo se il loop Esterno è uniforme ( quindi tutto chiuso o tutto aperto) + bool bExtAllClose = false ; + bool bExtAllOpen = false ; + if ( int( vpCrvs.size()) == 1) { + if ( vpCrvs[0]->GetTempProp( 0) == 0) + bExtAllClose = true ; + else + bExtAllOpen = true ; + } + // NB. Se regione estena tutta chiusa o aperta e senza isole... allora non faccio nulla ( es caso trapezi) + // Se tutta chiusa -> Chunk non svuotabile, il contro-offset del raggio utensile annulla la regione + // Se tutta aperta -> La regione è definita mediante Offset esterno del contorno aperto + if ( ( bExtAllClose || bExtAllOpen) && ! bHasIslands) + return true ; + + // scorro i chiusi e sottraggo la regione da loro creata mediante l'utensile + ICRVCOMPOPOVECTOR vCrvOffs ; // salvo il vettore di curve offsettate del raggio utensile + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == 0) { // se tratto chiuso... + OffsetCurve OffsCrv ; // con offset verso l'interno + if ( OffsCrv.Make( vpCrvs[i], - PockParams.dRad, ICurve::OFF_FILLET)) { + PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; + while ( ! IsNull( pOffLongestCrv)) { + // salvo la curva corrente + vCrvOffs.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; + // passo alla successiva + pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; + } + } + } + } + + /* + Casi gestiti : + 1) La curva esterna è tutta chiusa o tutta aperta e al suo interno ci sono delle isole uniformi + ( quindi ogni isola può essere solo aperta o chiusa) : + - se la curva esterna è tutta aperta, allora la regione da creare è formata da tutte le isole chiuse + e il percorso da seguire sarà un offset verso l'esterno di questa regione + - se la curva esterna è tutta chiusa, allora la regione è definita da questa loop esterno e + come loop interni vengono inserite tutte le isole chiuse; le curva da seguire sono ricavate + da un'offset verso l'interno della regione + 2) La curva esterna non è uniforme, quindi presenta sia tratti chiusi che tratti aperti : + - se non ci sono isole, allora ho già ricavato le curve + - se ci sono isole non faccio nulla ( meglio estendere i lati aperti del loop esterno e + delle isole mediante la funzione AdjustContourWithOpenEdges() + */ + + // creo la regione finale il cui Offset mi genera le curve di pocketing da seguire ( Offset positivo o negativo) + // NB. Le isole potrebbero unirsi tra di loro mediante gli Offset + PtrOwner pSfrToOffset( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrToOffset)) + return false ; + if ( bExtAllClose) // se il loop esterno è chiuso, lo aggiungo + pSfrToOffset->AddExtLoop( pCrvExtLoop->Clone()) ; //AAAAAAAAAAAAAAA + + // se ho delle isole e il loop esterno è uniforme ( tutto aperto o chiuso) + if ( bHasIslands && ( bExtAllClose || bExtAllOpen)) { + for ( int i = 1 ; i < pSfrChunk->GetLoopCount( 0) ; ++ i) { + // controllo uniformità dell'isola + int nCurrTmpProp = -1 ; + int nPrecTmpProp = -1 ; + bool bIsMixed = false ; + PtrOwner pCrvIsl( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, i))) ; + if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid()) + return false ; + for ( int u = 0 ; u < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ u) { + pCrvIsl->GetCurveTempProp( u, nCurrTmpProp, 0) ; + bIsMixed = ( u != 0 && nCurrTmpProp != nPrecTmpProp) ; + nPrecTmpProp = nCurrTmpProp ; + } + // se proprità non uniformi -> tutta chiusa ( isole non uniformi non sono definite) + if ( bIsMixed) { + for ( int u = 0 ; u < pCrvIsl->GetCurveCount() ; ++ u) + pCrvIsl->SetTempProp( u, 0) ; + nCurrTmpProp = 0 ; // aggiorno il Flag + } + // se isola chiusa + if ( nCurrTmpProp == 0) { + OffsetCurve OffsCrv ; // con Offset interno ( senso orario) + if ( OffsCrv.Make( pCrvIsl, - PockParams.dRad, ICurve::OFF_FILLET)) { + PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; + while ( ! IsNull( pOffLongestCrv)) { + // salvo la curva corrente + vCrvOffs.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; + // passo alla successiva + pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; + } + } + if ( bExtAllClose) { // se ho inserito il loop esterno + // inserisco la curva come isola + if ( ! pSfrToOffset->AddIntLoop( Release( pCrvIsl))) + return false ; + } + else { + // le isole saranno da loop esterni + pCrvIsl->Invert() ; // seguo il percorso di lavoro + if ( ! pSfrToOffset->AddExtLoop( Release( pCrvIsl))) + return false ; + } + } + } + } + + // vettore di curve temporanee ( da confrontare con la regione limite) + ICRVCOMPOPOVECTOR vCrvCompoRes_tmp ; + + if ( ! bHasIslands) { // se non avevo isole... + // restituisco le curve di svuotatura calcolate dai chiusi del loop esterno + for ( int i = 0 ; i < int( vCrvOffs.size()) ; ++ i) + vCrvCompoRes_tmp.emplace_back( Release( vCrvOffs[i])) ; + bAllRemoved = true ; // aggiornamento Flag + } + else { // se avevo isole + // i percorsi sono definiti dall'Offset della regione rimossa + // NB. Se ho inserito solo isole, allora l'Offset va verso l'esterno + // Se ho inserito sia il loop esterno che le isole, allora l'Offset è interno + double dOffs = PockParams.dRad ; + if ( bExtAllClose) + dOffs *= -1 ; + pSfrToOffset->Offset( dOffs, ICurve::OFF_FILLET) ; + if ( pSfrToOffset->IsValid() && pSfrToOffset->GetChunkCount() > 0) { + for ( int c = 0 ; c < pSfrToOffset->GetChunkCount() ; ++ c) + for ( int l = 0 ; l < pSfrToOffset->GetLoopCount( c) ; ++ l) + vCrvCompoRes_tmp.emplace_back( ConvertCurveToComposite( pSfrToOffset->GetLoop( c, l))) ; + bAllRemoved = true ; + } + } + // se non ho ottenuto curve, allora ho finito + if ( vCrvCompoRes_tmp.empty()) + return true ; + + // per tutte le curve inserite, devo tenere solamente quelle esterne alla superficie limite + if ( PockParams.SfrLimit.IsValid()) { // se esiste, allora classifico + ICRVCOMPOPOVECTOR vCrvCompoRes_tmp_Splitted ; + for ( int i = 0 ; i < int( vCrvCompoRes_tmp.size()) ; ++ i) { + CRVCVECTOR ccClass ; + if ( PockParams.SfrLimit.GetCurveClassification( *vCrvCompoRes_tmp[i], EPS_SMALL, ccClass)) { + for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + if ( ccClass[j].nClass == CRVC_OUT) { + PtrOwner pCrvRes( ConvertCurveToComposite( vCrvCompoRes_tmp[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; + if ( ! IsNull( pCrvRes) && pCrvRes->IsValid()) + vCrvCompoRes_tmp_Splitted.emplace_back( Release( pCrvRes)) ; + } + } + } + } + // se non ho curve, allora esco + if ( vCrvCompoRes_tmp_Splitted.empty()) + return true ; + // altrimenti aggiorno il vettore di curve con quelle solo esterne alla regione limite + swap( vCrvCompoRes_tmp, vCrvCompoRes_tmp_Splitted) ; + } + + // imposto le Feed per tali curve e aggiungo eventuale entrata da fuori + for ( int i = 0 ; i < int( vCrvCompoRes_tmp.size()) ; ++ i) { + // per ora è default ( sono passate singole)... + /* + Idea : Feed proporzionale al minimo Offset per annullare la regione ? + -> Massimo parametro sui bisettori di VORONOI (?) + */ + AssignMinFeed( vCrvCompoRes_tmp[i], PockParams) ; + // ricavo punto di inizio e vettore tangente + Point3d ptStart ; vCrvCompoRes_tmp[i]->GetStartPoint( ptStart) ; + Vector3d vtStart ; vCrvCompoRes_tmp[i]->GetStartDir( vtStart) ; + // recupero il punto di caduta dell'utensile + Point3d ptFall = ptStart - vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + // controllo che il tool non sia interno alla regione limite + PtrOwner pCrvToolShape( CreateCurveArc()) ; + if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) + return false ; + CRVCVECTOR ccClass ; + if ( PockParams.SfrLimit.GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + vCrvCompoRes_tmp[i]->AddLine( ptFall, false) ; + vCrvCompoRes_tmp[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed minima + } + else { // se trovo intersezione, provo a ruotare di 90° + vtStart.Rotate( Z_AX, ANG_RIGHT) ; // verso sinistra + ptFall = ptStart + vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + if ( ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) + return false ; + ccClass.clear() ; + if ( PockParams.SfrLimit.GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + vCrvCompoRes_tmp[i]->AddLine( ptFall, false) ; + vCrvCompoRes_tmp[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed massima + } + } + // imposto il flag di curva singola + vCrvCompoRes_tmp[i]->SetTempProp( TMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola + // inserisco la curva nel vettore finale + vCrvCompoRes.emplace_back( Release( vCrvCompoRes_tmp[i])) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes, + bool& bSkipPocket) { // controllo parametri : if ( pSfr == nullptr || ! pSfr->IsValid()) return true ; // <- se superficie non valida, allora non ho niente da impostare sui suoi lati + bSkipPocket = false ; // NB. Tutti i Loop che presentano dei lati aperti possono essere estesi ; sia per loop esterni che per isole... // I lati aperti vanno estesi seguendo lo geometria dei lati chiusi adiacenti e tenendo conto delle isole chiuse // vicine ad essi - // NB. Se ho una lavorazione precedente, allora estendo i lati aperti delle quantità relative alla lavorazione - // precedente ( l'attuale infatti svuoterà quello che rimane da svuotare proprio da questa lavorazione) - // Vedi GetNewSfrByAnotherPocketing() - // creo la superficie da restituire... ( questa superficie sarà estesa presso i lati aperti) PtrOwner pSrfFinal( CreateSurfFlatRegion()) ; if ( IsNull( pSrfFinal)) return false ; + int nChunkOneCurve = 0 ; // numero di chunk rimovibili mediante una sola curva di Offset + int nChunk = pSfr->GetChunkCount() ; // numero complessivo di Chunk da svuotare + // per ogni Chunck della superificie ottenuta... - for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++ c) { + for ( int c = 0 ; c < nChunk ; ++ c) { + + // 0) controllo se seguendo i chiusi posso svuotare l'interno chunk + PtrOwner pSfrChunk( pSfr->CloneChunk( c)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + bool bIsAllRemoved = false ; + GetPocketCurvesByCloseEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; + if ( bIsAllRemoved) { // se ho rimosso tutto, allora passo la chunk successivo + ++ nChunkOneCurve ; // aumento il contatore + continue ; + } // vettore delle isole che userò ( le isole aperte piccole sono trascurate) ICRVCOMPOPOVECTOR vCrvToTIsland ; @@ -1446,6 +2044,11 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams) } } + // se ho rimosso tutti i Chunk con una singola curva... + bSkipPocket = ( nChunk == nChunkOneCurve) ; + if ( bSkipPocket) + return true ; + // restituisco la superficie aggiornata ricavata if ( ! pSrfFinal->IsValid()) return false ; @@ -1666,7 +2269,7 @@ SetSpecialPtStartForOpenEdges( const ICurveComposite* pCrvOrig, const Frame3d& f //---------------------------------------------------------------------------- static bool -AssignOpenCloseTmpPropToFirstOffsCurve( ICurveComposite* pCrv, const PocketParams& PockParams, +AssignOpenCloseTmpPropToFirstOffsCurve( ICurveComposite* pCrv, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvLoops, INTVECTOR& vIndex, bool& bSomeOpen) { // controllo dei parametri @@ -1907,7 +2510,7 @@ SetAdvancedPtStartForPath( ICRVCOMPOPOVECTOR& vCrvOffsAct, const PocketParams& P // cambio il suo punto d'inizio dell'Offset attuale if ( SetPtStartForPath( vCrvOffsAct[i], PockParams, pSrfToWork, ptEndPrec, frPocket, ptStart, vtMidOut, bMidOut, nOffs, - ( int( vCrvOrigChunkLoops.size()) < i ? Get( vCrvOrigChunkLoops[i]) : nullptr))) + ( int( vCrvOrigChunkLoops.size()) < i) ? Get( vCrvOrigChunkLoops[i]) : nullptr)) vCrvOffsAct[i]->GetStartPoint( ptStart) ; else return false ; @@ -2177,6 +2780,9 @@ CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, dou if ( pMCrv->GetCurveCount() == 0) return false ; + // assegno la Feed + AssignFeedSpiralOpt( 0, PockParams, pMCrv) ; + // calcolo l'eventuale percorso di ritorno Point3d ptStart ; pMCrv->GetStartPoint( ptStart) ; Point3d ptEnd ; pMCrv->GetEndPoint( ptEnd) ; @@ -3999,7 +4605,7 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU { // controllo dei parametri - if ( vFirstOffs.size() == 0 || ( int)vCrvs.size() < ( int)vFirstOffs.size()) + if ( vFirstOffs.empty() || int( vCrvs.size()) < int( vFirstOffs.size())) return false ; pSrfToCut->Clear() ; @@ -4007,13 +4613,14 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU PtrOwner pSrfExtern( CreateSurfFlatRegion()) ; if ( IsNull( pSrfExtern)) return false ; - for ( int i = 0 ; i < int( vFirstOffs.size()) ; ++ i) { if ( i == 0) pSrfExtern->AddExtLoop( vFirstOffs[i]->Clone()) ; else { PtrOwner pCrvIntLoop( vFirstOffs[i]->Clone()) ; - if( IsNull( pCrvIntLoop) || ! pCrvIntLoop->Invert() || ! pSrfExtern->AddIntLoop( pCrvIntLoop->Clone())) + if ( IsNull( pCrvIntLoop) || + ! pCrvIntLoop->Invert() || + ! pSrfExtern->AddIntLoop( Release( pCrvIntLoop))) return false ; } } @@ -4029,18 +4636,20 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU // creo un vettore che conterrà solamente i Link percorsi fino ad Ora ICRVCOMPOPOVECTOR vLinks_done ; - for ( int i = PockParams.nType == POCKET_SPIRALIN ? 0 : ( int)vCrvs.size() - 1 ; - PockParams.nType == POCKET_SPIRALIN ? i < int( vCrvs.size()) : i >= 0 ; - PockParams.nType == POCKET_SPIRALIN ? ++ i : -- i) { + for ( int i = ( PockParams.nType == POCKET_SPIRALIN ? 0 : int( vCrvs.size()) - 1) ; + ( PockParams.nType == POCKET_SPIRALIN ? i < int( vCrvs.size()) : i >= 0 ) ; + ( PockParams.nType == POCKET_SPIRALIN ? ++ i : -- i)) { // ================= LINK ================================ - if ( i <= ( int)vLinks.size() && ! IsNull( vLinks[i]) && vLinks[i]->IsValid()) { - + // ( Il primo link è nullo, inatti non vi è nessun raccordo per raggiungere il primo Offset) + if ( i <= int( vLinks.size()) && ! IsNull( vLinks[i]) && vLinks[i]->IsValid()) { // Feed PtrOwner pCompoLink_i( CreateCurveComposite()) ; if ( IsNull( pCompoLink_i)) return false ; pCompoLink_i->AddCurve( vLinks[i]->Clone()) ; + if ( ! AssignFeedSpiral( pCompoLink_i, pSrfTool_Offs, true, vLinks_done, pCrv_orig, PockParams, 2 * PockParams.dRad / 3)) + return false ; // per Link ... PtrOwner pCrvLink_i( vLinks[i]->Clone()) ; @@ -4062,6 +4671,9 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU } // ================== OFFSET ============================= + // Feed + if ( ! AssignFeedSpiral( vCrvs[i], pSrfTool_Offs, false, vLinks_done, pCrv_orig, PockParams, 2 * PockParams.dRad / 3)) + return false ; // aggiorno la superificie svuotata PtrOwner pCrvOffs_i( CloneCurveComposite( vCrvs[i])) ; @@ -4069,10 +4681,10 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU return false ; PtrOwner pSrfToolRegOffi( GetSurfFlatRegionFromFatCurve( Release( pCrvOffs_i) , PockParams.dRad + 5 * EPS_SMALL, false, false)) ; if ( ! IsNull( pSrfToolRegOffi)) { - if ( ! pSrfTool_Offs->IsValid() || pSrfTool_Offs->GetChunkCount() == 0) - pSrfTool_Offs.Set( Release( pSrfToolRegOffi)) ; - else - pSrfTool_Offs->Add( *pSrfToolRegOffi) ; + if ( ! pSrfTool_Offs->IsValid() || pSrfTool_Offs->GetChunkCount() == 0) + pSrfTool_Offs.Set( Release( pSrfToolRegOffi)) ; + else + pSrfTool_Offs->Add( *pSrfToolRegOffi) ; } } @@ -5283,7 +5895,9 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con // aggiorno il collegamento vLinks[i+1].Set( Release( pCrvLink)) ; + } + } return true ; @@ -5455,6 +6069,7 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int else return true ; } + } // porto la superficie nel frame corrente @@ -5640,29 +6255,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int return true ; } -//---------------------------------------------------------------------------- -static bool -CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll) -{ - // controllo dei parametri - if (( pCrv == nullptr || pCrvOri == nullptr || dToll < EPS_SMALL)) - return false ; - nStat = 1 ; // 0 -> no overlap | 1 -> overlap - - // controllo se una sottocurva della composita è abbastanza vicina a tutti i punti trovati - const double nMAX = 10.0 ; - for ( int i = 0 ; i <= nMAX ; ++i) { - double dPar = i / nMAX ; - Point3d ptC ; pCrv->GetPointD1D2( dPar, ICurve::FROM_PLUS, ptC) ; - if ( ! pCrvOri->IsPointOn( ptC, dToll)) { - nStat = 0 ; - return true ; - } - } - - return true ; -} - //---------------------------------------------------------- static bool CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, const PocketParams& PockParams, @@ -5897,8 +6489,8 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I pSrfZigZag->GetCurveClassification( *pLine, EPS_SMALL, ccClass) ; for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { if ( ccClass[j].nClass == CRVC_IN) { // memorizzo il segmento - Section currSec; - currSec.bActive = true; + Section currSec ; + currSec.bActive = true ; PtrOwner pSeg( GetCurveLine( pLine->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; if ( IsNull( pSeg)) continue ; @@ -6186,9 +6778,11 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo - // se il chunk presenta dei lati aperti, estendo la curva che ho trovato per un LeadIn - if ( bOptimizedTrap) // se caso a trapezio + if ( bOptimizedTrap) { // se caso a trapezio AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; + AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; + pMCrv->SetTempProp( TMP_PROP_OPT_TRAPEZOID, 0) ; + } else if ( bSomeOpen) { // se presenza di lati aperti if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false)) return false ; @@ -6197,7 +6791,9 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, // inserisco le curve nel vettore vCrvCompoRes.emplace_back( Release( pMCrv)) ; ++ nReg ; // incremento il numero di regione progressiva + } + } return true ; @@ -6248,6 +6844,12 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo + if ( bOptimizedTrap) { // se caso a trapezio + AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; + AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; + pMCrv->SetTempProp( TMP_PROP_OPT_TRAPEZOID, 0) ; + } + // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) pMCrv->Invert() ; pRCrv->Invert() ; @@ -6435,7 +7037,7 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con return false ; // riporto le superfici ideali nel sistema di riferimento globale ( Ogni chunk verrà poi messo nel suo frame) - for ( int i = 0 ; i < ( int)vSrfFlat.size() ; ++ i) + for ( int i = 0 ; i < int( vSrfFlat.size()) ; ++ i) vSrfFlat[i]->ToGlob( frLoc) ; // ------------------------------------------------------------------ @@ -6464,12 +7066,12 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con // passi in Y int nYStep = static_cast( ceil(( dDimY + 2 * dExtra) / PockParams.dSideStep)) ; double dYStep = ( nYStep > 0 ? ( dDimY + 2 * dExtra) / nYStep : 0) ; - --nYStep ; + -- nYStep ; // vettore dei segmenti al di sotto della linea corrente ICURVEPOVECTOR vLineUnder ; - ICURVEPOVECTOR vLineAbove ; - ICRVCOMPOPOVECTOR vCrvLink ; + ICURVEPOVECTOR vCrvNull ; + ICRVCOMPOPOVECTOR vCrvCompoNull ; // calcolo le linee di svuotatura const double EXP_LEN = 1.0 ; @@ -6481,13 +7083,18 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) return false ; + // linea come composita per Feed ( la dovrò spezzare) + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + // vettore di tutti i segmenti lineari che si formano nello step nYStep ICURVEPOVECTOR vAddedLines ; // riempio il vettore di segmenti CRVCVECTOR ccClassSeg ; pSrfIdeal->GetCurveClassification( *pLine, EPS_SMALL, ccClassSeg) ; - for ( int w = 0 ; w < int( ccClassSeg.size()) ; ++w) { + for ( int w = 0 ; w < int( ccClassSeg.size()) ; ++ w) { if ( ccClassSeg[w].nClass == CRVC_IN) { PtrOwner pCrvSeg( GetCurveLine( pLine->CopyParamRange( ccClassSeg[w].dParS, ccClassSeg[w].dParE))) ; @@ -6500,14 +7107,24 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con ! pCrvSeg->TrimEndAtParam( duF)) pCrvSeg.Set( GetCurveLine( pLine->CopyParamRange( ccClassSeg[w].dParS, ccClassSeg[w].dParE))) ; + // aggiungo il segmento al vettore dei tratti correnti + vAddedLines.emplace_back( pCrvSeg->Clone()) ; + + // trasformo il tratto lineare in curve composita per il calcolo della Feed PtrOwner pCrvSegCompo( CreateCurveComposite()) ; if ( IsNull( pCrvSegCompo)) return false ; pCrvSegCompo->AddCurve( Release( pCrvSeg)) ; + // calcolo la Feed + AssignFeedZigZagOneWay( pCrvSegCompo, false, vCrvNull, vLineUnder, vCrvCompoNull, PockParams) ; pCrvSegCompo->ToGlob( frPocket) ; vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ; } } + // i tratti lineari correnti diventano i precedenti + vLineUnder.clear() ; + for ( int u = 0 ; u < int( vAddedLines.size()) ; ++ u) + vLineUnder.emplace_back( Release( vAddedLines[u])) ; } } @@ -6554,8 +7171,14 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double if ( myParams.SfrLimit.IsValid()) myParams.SfrLimit.ToLoc( frLoc) ; // modifico la superficie da svuotare estendendo i lati aperti - if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams)) + bool bSkipPocket = false ; // se la superficie si svuota mediante curve singole di primo Offset dei chiusi + if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams, vCrvCompoRes, bSkipPocket)) return false ; + // se ottengo delle curve si svuotatura di primo Offset, le riporto in globale + for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) + vCrvCompoRes[i]->ToGlob( frLoc) ; + if ( bSkipPocket) // se tali curva rimuovono tutta la regione, allora non faccio nulla + return true ; // riporto tutto nel frame originale pSfrAdj->ToGlob( frLoc) ; if ( myParams.SfrLimit.IsValid()) From 8981057d29682c1803f028c498d158f792688f63 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 3 Jul 2024 17:07:35 +0200 Subject: [PATCH 2/7] EgtGeomKernel : - in calcolo pocketing piccole sistemazioni a salvataggio coefficiente feed (sempre in CurveTempParam). --- CalcPocketing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 5883f73..848be9f 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -564,7 +564,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs } } else - pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; } } } @@ -592,14 +592,14 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC if ( nOptType == 0) { // Spirale dall'Esterno for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { if ( u == 0) // prima circonferenza - pCrv->SetCurveTempProp( 0, GetMinFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ; else // semi cerchi in tangenza - pCrv->SetCurveTempProp( u, GetMaxFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; } } else if ( nOptType == 1) { // Trapezoidi for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; } break ; /* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre @@ -608,14 +608,14 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC if ( nOptType == 0) { // Spiral verso l'esterno for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze - pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; else - pCrv->SetCurveTempProp( u, GetMaxFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; } } else if ( nOptType == 1) { // Trapezoidi for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempProp( u, GetMinFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; } break ; default : From 447ebe11e58a3835a1df9710797998cab29cb161 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 4 Jul 2024 16:43:44 +0200 Subject: [PATCH 3/7] EgtGeomKernel : - in calcolo pocketing, semplificate le curve di Feed e migliorata la gestione della superficie limite. --- CalcPocketing.cpp | 181 +++++++++++++++++++++++++++++++++++++++------- VolZmapVolume.cpp | 2 +- 2 files changed, 155 insertions(+), 28 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 848be9f..7a2338a 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -398,6 +398,102 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ICurveComposite* pCrvOF_orig return true ; } +//---------------------------------------------------------------------------- +static bool +SimplifyCurveByFeeds( ICurveComposite* pCrvCompo, const PocketParams& PockParam, double dToler) +{ + // controllo la validità della curva + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() || pCrvCompo->GetCurveCount() == 0) + return false ; + + // NB. Effettuo il Merge dei tratti di curva che presentano la stessa Feed ( mediante la tolleranza) + + // curva semplificata + PtrOwner pCrvSimple( CreateCurveComposite()) ; + if ( IsNull( pCrvSimple)) + return false ; + + /* + - effettuo il Merge dei tratti di curva che presentano la stessa Feed + - imposto la Feed dei tratti piccoli come quella dei tratti precedenti ( per evitare singolarità) + - effettuo un nuovo Merge per uniformare ulteriormente i nuovi tratti ottenuti + */ + double dCurrTempParam ; + int nParStart = 0 ; + double dTempParam ; + double dLen ; + for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { + pCrvCompo->GetCurveTempParam( i, dTempParam) ; + if ( i == 0) { + dCurrTempParam = dTempParam ; + nParStart = i ; + } + else if ( abs( dCurrTempParam - dTempParam) > dToler) { // se parametri diversi + // recupero il tratto di curva uniforme + PtrOwner pCrv( ConvertCurveToComposite( pCrvCompo->CopyParamRange( nParStart, i))) ; + if ( IsNull( pCrv)) + return false ; + // lo semplifico + // recupero la lunghezza del tratto e imposto associo la Feed corrente + // se curva corta -> il parametro di Feed è definito da quello precedente + pCrv->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; + pCrv->GetLength( dLen) ; + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempParam( u, ( 0.1 * PockParam.dRad < dLen ? dCurrTempParam : dTempParam), 0) ; + pCrvSimple->AddCurve( Release( pCrv)) ; + dCurrTempParam = dTempParam ; + nParStart = i ; + } + } + // ultima parte di curva uniforme ... + PtrOwner pCrvLast( ConvertCurveToComposite( pCrvCompo->CopyParamRange( nParStart, pCrvCompo->GetCurveCount()))) ; + if ( ! IsNull( pCrvLast)) { + pCrvLast->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; + double dLen ; pCrvLast->GetLength( dLen) ; + for ( int u = 0 ; u < pCrvLast->GetCurveCount() ; ++ u) + pCrvLast->SetCurveTempParam( u, ( 0.1 * PockParam.dRad < dLen ? dCurrTempParam : dTempParam), 0) ; + pCrvSimple->AddCurve( Release( pCrvLast)) ; + } + + // pulisco la curva originale + pCrvCompo->Clear() ; + + // scorro i nuovi tratti ottenuti e ripeto il ragionamento + for ( int i = 0 ; i < pCrvSimple->GetCurveCount() ; ++ i) { + pCrvSimple->GetCurveTempParam( i, dTempParam) ; + if ( i == 0) { + dCurrTempParam = dTempParam ; + nParStart = i ; + } + else if ( abs( dCurrTempParam - dTempParam) > dToler) { + PtrOwner pCrv( ConvertCurveToComposite( pCrvSimple->CopyParamRange( nParStart, i))) ; + if ( IsNull( pCrv)) + return false ; + pCrv->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; + // recupero la lunghezza di tale curve + double dLen ; pCrv->GetLength( dLen) ; + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempParam( u, ( 0.1 * PockParam.dRad < dLen ? dCurrTempParam : dTempParam), 0) ; + pCrvCompo->AddCurve( Release( pCrv)) ; // aggiungo alla curva finale + dCurrTempParam = dTempParam ; + nParStart = i ; + } + } + // ultima parte di curva uniforme ... + pCrvLast.Set( ConvertCurveToComposite( pCrvSimple->CopyParamRange( nParStart, pCrvSimple->GetCurveCount()))) ; + if ( ! IsNull( pCrvLast)) { + // semplifico + pCrvLast->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; + // recupero la lunghezza di tale curva e imposto la Feed + pCrvLast->GetLength( dLen) ; + for ( int u = 0 ; u < pCrvLast->GetCurveCount() ; ++ u) + pCrvLast->SetCurveTempParam( u, ( 0.1 * PockParam.dRad < dLen ? dCurrTempParam : dTempParam), 0) ; + pCrvCompo->AddCurve( Release( pCrvLast)) ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs, bool bIsLink, @@ -431,7 +527,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs // restringo la superificie in maniera appropriata if ( bIsLink) { // se curva di Link - if ( ! pSrf_Removed_offs_clone->Offset( - PockParams.dRad + 1500 * EPS_SMALL, ICurve::OFF_CHAMFER) || + if ( ! pSrf_Removed_offs_clone->Offset( - PockParams.dRad, ICurve::OFF_CHAMFER) || ! pSrf_Removed_offs_clone->IsValid() || pSrf_Removed_offs_clone->GetChunkCount() == 0) return true ; // esco ( sempre con Feed Minima) } @@ -454,17 +550,17 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { // recupero il tratto di curva ricavato dalla classificazione double dCurrFeed = GetMinFeed( PockParams) ; - PtrOwner PCrv_sez( ConvertCurveToComposite( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; - if ( IsNull( PCrv_sez)) + PtrOwner pCrv_sez( ConvertCurveToComposite( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; + if ( IsNull( pCrv_sez)) continue ; // curva troppo piccola, passo alla successiva // controllo se interno o fuori alla regione ( regolando quindi la Feed) if ( ccClass[i].nClass == CRVC_IN) // se interna alla regione rimossa... dCurrFeed = GetMaxFeed( PockParams) ; // assegno tale Feed ad ogni sottocurva ricavata dal tratto di classificazione - for ( int u = 0 ; u < PCrv_sez->GetCurveCount() ; ++ u) - PCrv_sez->SetCurveTempParam( u, dCurrFeed, 0) ; + for ( int u = 0 ; u < pCrv_sez->GetCurveCount() ; ++ u) + pCrv_sez->SetCurveTempParam( u, dCurrFeed, 0) ; // aggiungo la nuova curva con la Feed regolata a quella finale - pCrv_new->AddCurve( Release( PCrv_sez)) ; + pCrv_new->AddCurve( Release( pCrv_sez)) ; } // sotituisco con quanto calcolato @@ -1755,7 +1851,7 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam if ( IsNull( pSfrToOffset)) return false ; if ( bExtAllClose) // se il loop esterno è chiuso, lo aggiungo - pSfrToOffset->AddExtLoop( pCrvExtLoop->Clone()) ; //AAAAAAAAAAAAAAA + pSfrToOffset->AddExtLoop( Release( pCrvExtLoop)) ; // se ho delle isole e il loop esterno è uniforme ( tutto aperto o chiuso) if ( bHasIslands && ( bExtAllClose || bExtAllOpen)) { @@ -1833,12 +1929,23 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam if ( vCrvCompoRes_tmp.empty()) return true ; + // recupero la superficie limite ( se esiste ed è valida) + PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrLimit)) + return false ; + // per tutte le curve inserite, devo tenere solamente quelle esterne alla superficie limite if ( PockParams.SfrLimit.IsValid()) { // se esiste, allora classifico + // recupero la superficie limite + pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) + return false ; + // effettuo un Offset della regione, tutto ciò che dista più del raggio utensile non la rovina + pSfrLimit->Offset( PockParams.dRad - 250 * EPS_SMALL, ICurve::OFF_FILLET) ; // c'è un offset radiale, quindi tengo tolleranza alta ICRVCOMPOPOVECTOR vCrvCompoRes_tmp_Splitted ; for ( int i = 0 ; i < int( vCrvCompoRes_tmp.size()) ; ++ i) { CRVCVECTOR ccClass ; - if ( PockParams.SfrLimit.GetCurveClassification( *vCrvCompoRes_tmp[i], EPS_SMALL, ccClass)) { + if ( pSfrLimit->GetCurveClassification( *vCrvCompoRes_tmp[i], EPS_SMALL, ccClass)) { for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { if ( ccClass[j].nClass == CRVC_OUT) { PtrOwner pCrvRes( ConvertCurveToComposite( vCrvCompoRes_tmp[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; @@ -1869,27 +1976,29 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam // recupero il punto di caduta dell'utensile Point3d ptFall = ptStart - vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; // controllo che il tool non sia interno alla regione limite - PtrOwner pCrvToolShape( CreateCurveArc()) ; - if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) - return false ; - CRVCVECTOR ccClass ; - if ( PockParams.SfrLimit.GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && - int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { - vCrvCompoRes_tmp[i]->AddLine( ptFall, false) ; - vCrvCompoRes_tmp[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out - vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed minima - } - else { // se trovo intersezione, provo a ruotare di 90° - vtStart.Rotate( Z_AX, ANG_RIGHT) ; // verso sinistra - ptFall = ptStart + vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - if ( ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) + if ( pSfrLimit->IsValid()) { + PtrOwner pCrvToolShape( CreateCurveArc()) ; + if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) return false ; - ccClass.clear() ; - if ( PockParams.SfrLimit.GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && + CRVCVECTOR ccClass ; + if ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { vCrvCompoRes_tmp[i]->AddLine( ptFall, false) ; vCrvCompoRes_tmp[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out - vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed massima + vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed minima + } + else { // se trovo intersezione, provo a ruotare di 90° + vtStart.Rotate( Z_AX, ANG_RIGHT) ; // verso sinistra + ptFall = ptStart + vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + if ( ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) + return false ; + ccClass.clear() ; + if ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + vCrvCompoRes_tmp[i]->AddLine( ptFall, false) ; + vCrvCompoRes_tmp[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + vCrvCompoRes_tmp[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed massima + } } } // imposto il flag di curva singola @@ -5236,6 +5345,9 @@ GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurveComposite* if ( ! AreSameVectorApprox( vtS_cir, vtS_CrvH1)) pPath1->Invert() ; + // assegno la Feed + AssignMinFeed( pPath1, PockParams) ; + // controllo che la circonferenza sia ammissibile ( solo che non esca dalle prime curve di Offset) Point3d ptCrvS ; pPath1->GetStartPoint( ptCrvS) ; if ( ! CutCurveByOffsets( pPath1, VFirstOff)) // taglio la curva sugli Offsets @@ -5278,6 +5390,10 @@ GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurveComposite* ! CalcBoundedSmoothedLink( ptE, vtTanS, ptS, vtTanS, 0.5, VFirstOff, PockParams, pPath2)) return false ; + // assegno la Feed a queste due nuove curve + AssignMinFeed( pPath1, PockParams) ; + AssignMinFeed( pPath2, PockParams) ; + // creo la nuova curva con il doppio Biarco if ( pCrvH1 != nullptr && pCrvH1->GetFirstCurve() != nullptr) if ( ! pCrvNewCurve->AddCurve( pCrvH1->Clone())) // aggiungo inizio @@ -5320,7 +5436,7 @@ ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pCrvPath, ICu CRVCVECTOR ccClass ; IntersCurveCurve intCC( *pLine, *pCrv) ; intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; - if (( int)ccClass.size() > 1) // se intersezione con parte precedente inverto la direzione + if ( int( ccClass.size()) > 1) // se intersezione con parte precedente inverto la direzione pLine->SetPVL( ptHS, - vTanE, ( 2 * PockParams.dRad) / 3 - 5 * EPS_SMALL) ; if ( IsNull( pLine) || ! pLine->IsValid()) @@ -5446,6 +5562,9 @@ GetNewCurvetWithPath( const ICurveComposite* pCrvH1, const ICurveComposite* pCrv if ( ! ManageSmoothAndAutoInters( pCrvToAdd, pCrvPath, pPath1, PockParams, pPath2, VoffsCl)) return false ; + // imposto la Feed + AssignMinFeed( pCrvToAdd, PockParams) ; + // curva finale if ( pCrvH1 != nullptr && pCrvH1->GetFirstCurve() != nullptr) if ( ! pCrvNewCurve->AddCurve( pCrvH1->Clone())) // aggiungo inizio @@ -5464,6 +5583,9 @@ GetNewCurvetWithPath( const ICurveComposite* pCrvH1, const ICurveComposite* pCrv if ( ! CalcBoundedLink( ptHS, ptHE, VFirstOff, pCrvBiArcHelper)) return false ; + // assegno la Feed + AssignMinFeed( pCrvBiArcHelper, PockParams) ; + if ( ! pCrvNewCurve->AddCurve( Release( pCrvBiArcHelper)) || ! pCrvNewCurve->AddCurve( pCrvToAdd->Clone())) return false ; @@ -5484,6 +5606,9 @@ GetNewCurvetWithPath( const ICurveComposite* pCrvH1, const ICurveComposite* pCrv if ( ! CalcBoundedLink( ptHS, ptHE, VFirstOff, pCrvBiArcHelper) ) return false ; + // assegno la Feed + AssignMinFeed( pCrvBiArcHelper, PockParams) ; + if ( ! pCrvNewCurve->AddCurve( pCrvBiArcHelper->Clone()) || ! pCrvNewCurve->AddCurve( pCrvH2->Clone())) { ++nTry ; @@ -6163,7 +6288,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int if ( vOffs.empty()) return true ; - // cambio il punto iniziale della prima Curva di Offset Point3d ptRef = PockParams.ptEnd ; ptRef.ToLoc( frPocket) ; Point3d ptNewStart ; @@ -6238,6 +6362,9 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int pMCrv->AddCurve( vOffs[i]->Clone()) ; } + // semplifico la curva ottenuta + SimplifyCurveByFeeds( pMCrv, PockParams, 10 * EPS_SMALL) ; + // verifico il percorso di lavoro if ( pMCrv->GetCurveCount() == 0) return false ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index ee6245e..20e3680 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -5090,7 +5090,7 @@ VolZmap::CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ, // ---------- SFERA ---------------------------------------------------------- -//---------------------------------------------------------------------------- pizza +//---------------------------------------------------------------------------- bool VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe, double dRad, int nToolNum) { From b6a7ce4eefb3a60853b38c89ca862943bbb9c91b Mon Sep 17 00:00:00 2001 From: SaraP Date: Tue, 9 Jul 2024 10:25:24 +0200 Subject: [PATCH 4/7] EgtGeomKernel : - aggiunte funzioni che restituiscono il valore di offset che fa sparire una curva chiusa, una flat region o un suo chunk. --- CurveAux.cpp | 23 ++++++++++ OffsetAux.cpp | 14 +++--- OffsetAux.h | 4 +- SurfFlatRegion.cpp | 37 +++++++++++++++ SurfFlatRegion.h | 2 + Voronoi.cpp | 110 +++++++++++++++++++++++++++++++++------------ Voronoi.h | 2 + 7 files changed, 153 insertions(+), 39 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index b2edb45..2036ac9 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -1472,6 +1472,29 @@ CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bo return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ; } +//---------------------------------------------------------------------------- +bool +CalcCurveLimitOffset( const ICurve& crvC, double& dOffs) +{ + // se curva aperta errore + if ( ! crvC.IsClosed()) + return false ; + + Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ; + if ( pVoronoiObj == nullptr) + return false ; + + // verifico l'orientamento della curva rispetto al piano di vroni per capire se l'offset critico è quello a destra ( offset > 0) + // oppure quello a sinistra ( offset < 0) + Plane3d plPlane, plPlaneVroni ; + double dArea ; + if ( ! CurveGetArea( crvC, plPlane, dArea) || ! pVoronoiObj->GetVroniPlane( plPlaneVroni)) + return false ; + bool bLeft = AreSameVectorApprox( plPlane.GetVersN(), plPlaneVroni.GetVersN()) ; + + return pVoronoiObj->CalcLimitOffset( 0, bLeft, dOffs) ; +} + //---------------------------------------------------------------------------- void ResetCurveVoronoi( const ICurve& crvC) diff --git a/OffsetAux.cpp b/OffsetAux.cpp index ad683bb..9b5c30e 100644 --- a/OffsetAux.cpp +++ b/OffsetAux.cpp @@ -2,7 +2,7 @@ // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5 -// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve. +// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve. // // // @@ -25,11 +25,7 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist) { // identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) { - // recupero la curva - PtrOwner pCrv( pCrvCo->GetCurve(i)->Clone()) ; - if ( IsNull( pCrv)) - return false ; - if ( IsFillet( pCrv, dDist)) + if ( IsFillet( pCrvCo->GetCurve( i), dDist)) pCrvCo->SetCurveTempParam( i, 1.0) ; else pCrvCo->SetCurveTempParam( i, 0.0) ; @@ -39,12 +35,14 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist) //---------------------------------------------------------------------------- bool -IsFillet( ICurve* pCrv, double dDist) +IsFillet( const ICurve* pCrv, double dDist) { + if ( pCrv == nullptr) + return false ; // deve essere un arco if ( pCrv->GetType() != CRV_ARC) return false ; - CurveArc* pArc = GetBasicCurveArc( pCrv) ; + const CurveArc* pArc = GetBasicCurveArc( pCrv) ; // deve avere raggio uguale alla distanza di offset if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL) return false ; diff --git a/OffsetAux.h b/OffsetAux.h index 6564059..488af20 100644 --- a/OffsetAux.h +++ b/OffsetAux.h @@ -2,7 +2,7 @@ // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : OffsetAux.h Data : 23.11.23 Versione : 2.5k5 -// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve. +// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve. // // // @@ -16,6 +16,6 @@ //---------------------------------------------------------------------------- bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ; -bool IsFillet( ICurve* pCrv, double dDist) ; +bool IsFillet( const ICurve* pCrv, double dDist) ; bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ; bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ; diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 0391dc8..0027f7c 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -1481,6 +1481,43 @@ SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ; } +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::GetChunkMaxOffset( int nChunk, double& dOffs) const +{ + // verifico se è stato calcolato Voronoi + if ( m_pVoronoiObj == nullptr) + if ( ! CalcVoronoiObject()) + return false ; + + // il massimo offset per il chunk è il massimo offset del suo loop esterno + // ( il diagramma di Voronoi tiene già conto della limitazione con i loop interni) + int nInd = GetIndFromChunkLoop( nChunk, 0) ; + return m_pVoronoiObj->CalcLimitOffset( nInd, true, dOffs) ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::GetMaxOffset( double& dOffs) const +{ + int nChunks = GetChunkCount() ; + if ( nChunks == 0) + return false ; + + // calcolo il massimo fra gli offset limite di tutti i suoi chunks + if ( ! GetChunkMaxOffset( 0, dOffs)) + return false ; + for ( int i = 1 ; i < nChunks ; i++) { + double dCurrOffs ; + if ( ! GetChunkMaxOffset( i, dCurrOffs)) + return false ; + if ( dCurrOffs > dOffs) + dOffs = dCurrOffs ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd) diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 9173c1c..c1198e8 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -105,6 +105,8 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ; bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ; + bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ; + bool GetMaxOffset( double& dOffs) const override ; void ResetVoronoiObject( void) const override ; bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ; bool GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd = 0) const override ; diff --git a/Voronoi.cpp b/Voronoi.cpp index 2c894bd..7d05caa 100644 --- a/Voronoi.cpp +++ b/Voronoi.cpp @@ -371,6 +371,16 @@ Voronoi::GetCurve( int nId) const return pCrv ; } +//---------------------------------------------------------------------------- +bool +Voronoi::GetVroniPlane( Plane3d& plPlane) const +{ + if ( ! IsValid()) + return false ; + plPlane.Set( m_Frame.Orig(), m_Frame.VersZ()) ; + return plPlane.IsValid() ; +} + //---------------------------------------------------------------------------- bool Voronoi::CalcVoronoi( int nBound) @@ -512,12 +522,12 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) // verifico se necessario calcolo Voronoi if ( ! m_bVDComputed || nBound != m_nBound) CalcVoronoi( nBound) ; - + for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { // recupero la curva del bisettore PtrOwner pCrv( GetBisectorCurve( i)) ; if ( ! IsNull( pCrv) && pCrv->IsValid()) - vCrvs.emplace_back( Release( pCrv)) ; + vCrvs.emplace_back( Release( pCrv)) ; } // libero la memoria di vroni utilizzata per calcolare bisettore @@ -609,31 +619,31 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) AdjustClosedOffsetCurve( *pCrv, dOffs) ; else AdjustOpenOffsetCurve( *pCrv, dOffs) ; - - if ( pCrv->IsValid()) { - // eventuale inversione - if ( dOffs > EPS_SMALL) - pCrv->Invert() ; + + if ( pCrv->IsValid()) { + // eventuale inversione + if ( dOffs > EPS_SMALL) + pCrv->Invert() ; - // sistemo i raccordi - if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { - IdentifyFillets( pCrv, dOffs) ; - AdjustCurveFillets( pCrv, dOffs, nType) ; - } + // sistemo i raccordi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + IdentifyFillets( pCrv, dOffs) ; + AdjustCurveFillets( pCrv, dOffs, nType) ; + } - if ( bClosed) { - // forzo chiusura della curva per evitare piccole imprecisioni - pCrv->Close() ; - // sistemo il punto di inizio - AdjustOffsetStart( *pCrv) ; - } + if ( bClosed) { + // forzo chiusura della curva per evitare piccole imprecisioni + pCrv->Close() ; + // sistemo il punto di inizio + AdjustOffsetStart( *pCrv) ; + } - // porto nel frame globale - pCrv->ToGlob( m_Frame) ; - // unisco le parti allineate - pCrv->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; - // aggiungo al vettore finale - vOffs.emplace_back( pCrv) ; + // porto nel frame globale + pCrv->ToGlob( m_Frame) ; + // unisco le parti allineate + pCrv->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; + // aggiungo al vettore finale + vOffs.emplace_back( pCrv) ; } else delete pCrv ; @@ -1011,7 +1021,8 @@ Voronoi::Translate( const Vector3d & vtMove) } //--------------------------------------------------------------------------- -bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) +bool +Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) { if ( ! IsValid()) return false ; @@ -1019,7 +1030,8 @@ bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) } //--------------------------------------------------------------------------- -bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) +bool +Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { if ( ! IsValid()) return false ; @@ -1027,7 +1039,8 @@ bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, } //--------------------------------------------------------------------------- -bool Voronoi::ToGlob( const Frame3d& frRef) +bool +Voronoi::ToGlob( const Frame3d& frRef) { if ( ! IsValid()) return false ; @@ -1035,7 +1048,8 @@ bool Voronoi::ToGlob( const Frame3d& frRef) } //--------------------------------------------------------------------------- -bool Voronoi::ToLoc( const Frame3d& frRef) +bool +Voronoi::ToLoc( const Frame3d& frRef) { if ( ! IsValid()) return false ; @@ -1043,9 +1057,47 @@ bool Voronoi::ToLoc( const Frame3d& frRef) } //--------------------------------------------------------------------------- -bool Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) +bool +Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { if ( ! IsValid()) return false ; return m_Frame.LocToLoc( frOri, frDest) ; } + +//--------------------------------------------------------------------------- +bool +Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) +{ + if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1) + return false ; + // se curva aperta errore + if ( ! m_vpCrvs[nCrv]->IsClosed()) + return false ; + + dOffs = - INFINITO ; + try { + // verifico se necessario calcolo Voronoi + if ( ! m_bVDComputed) + CalcVoronoi() ; + + for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { + // verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno + if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) { + // calcolo i parametri del bisettore + double dParS, dParE ; + m_vroni->GetBisectorParams( i, dParS, dParE) ; + dOffs = max( { dParS, dParE, dOffs}) ; + } + } + + // libero la memoria di vroni dedicata agli offset + m_vroni->apiFreeOffsetData() ; + } + catch (...) { + LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ; + return false ; + } + + return true ; +} diff --git a/Voronoi.h b/Voronoi.h index 5ffc9d6..502cf91 100644 --- a/Voronoi.h +++ b/Voronoi.h @@ -50,10 +50,12 @@ class Voronoi ICurve* GetCurve( int nId) const ; int GetCurveCount( void) const { return m_vpCrvs.size() ; } ; + bool GetVroniPlane( Plane3d& plPlane) const ; bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) ; bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ; bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ; bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ; + bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ; bool Translate( const Vector3d& vtMove) ; bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ; From 052cc9e8414a05cea4d3a3962efc88bb2c942d56 Mon Sep 17 00:00:00 2001 From: SaraP Date: Tue, 9 Jul 2024 10:30:51 +0200 Subject: [PATCH 5/7] EgtGeomKernel 2.6g2 : - aggiornamento versione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 9968570b22baeb789e01518d9d84677be132c8c8..06e49bd091f36b02e7319716684d7caf66bc1c88 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SD2&FAG5nSs Date: Tue, 9 Jul 2024 11:10:49 +0200 Subject: [PATCH 6/7] EgtGeomKernel : - in CalcPocketing pulizia del codice e migliorie varie. --- CalcPocketing.cpp | 232 ++++++++++------------------------------------ 1 file changed, 49 insertions(+), 183 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 7a2338a..fa68929 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -72,7 +72,6 @@ static int TMP_PROP_OPT_TRAPEZOID = 4 ; // caso ottimizzato Trapezio //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- static double GetMaxFeed( const PocketParams& PockParams) @@ -124,23 +123,6 @@ AssignMinFeed( ICurveComposite* pCrv, const PocketParams& PockParams) return true ; } -//--------------------------------------------------------------------------- -static bool -AssignCustomFeed( ICurveComposite* pCrv, const PocketParams& PockParams, double dFeed) -{ - // controllo dei parametri - if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) - return false ; - // La Feed deve essere compresa tra la minima e la massima - dFeed = Clamp( dFeed, GetMinFeed( PockParams), GetMaxFeed( PockParams)) ; - - // assegno la Feed ad ogni sottocurva di pCrv - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempParam( u, dFeed, 0) ; - - return true ; -} - //--------------------------------------------------------------------------- static bool GetFeedForParam( double& dPar, const PocketParams& PockParams, double& dFeed) @@ -196,8 +178,7 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV return AssignMaxFeed( pCompo, PockParams) ; // inzialmente setto la feed Minima alla curva - for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) - pCompo->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + AssignMinFeed( pCompo, PockParams) ; // se è un link tra livelli diversi, allora esco ( con Feed Minima ) if ( bIsLink) { @@ -239,13 +220,13 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV // determino la direzione del Link Vector3d vtLinkDir( - 25, 0, 0) ; - Point3d ptS_l ; - vAddedLinks[l]->GetStartPoint( ptS_l) ; - Point3d ptE_l ; - vAddedLinks[l]->GetEndPoint( ptE_l) ; + // recupero gli estremi + Point3d ptS_l ; vAddedLinks[l]->GetStartPoint( ptS_l) ; + Point3d ptE_l ; vAddedLinks[l]->GetEndPoint( ptE_l) ; if ( ptE_l.x - ptS_l.x < EPS_SMALL) vtLinkDir.x -= ptS_l.x - ptE_l.x ; + // superficie a rettangolo definita dal Box PtrOwner pSfrRectUp( GetSurfFlatRegionRectangle( bBoxLink.GetDimX() + 50, PockParams.dSideStep)) ; pSfrRectUp->Translate(( ptS_l - ORIG) + vtLinkDir) ; @@ -254,6 +235,7 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV if ( dCurrY - ptS_l.y < EPS_SMALL) bIsDown = false ; + // classificazione con la superficie a rettangolo CRVCVECTOR ccClass ; pSfrRectUp->GetCurveClassification( *vAddedLinks[l], EPS_SMALL, ccClass) ; for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { @@ -275,6 +257,7 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV if ( ! vAllInt[i]->GetLength( dLen_iU) || ( dLen_iU < 1.1 * ( 2 * PockParams.dRad) && i < nDim)) continue ; + // estremi dell'intervallo Point3d ptS_iU, ptE_iU ; vAllInt[i]->GetStartPoint( ptS_iU) ; vAllInt[i]->GetEndPoint( ptE_iU) ; @@ -286,7 +269,6 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV // l'intervallo orginale ora conterrà i sottointervalli con feed Minima, tolgo quelli troppo piccoli Intervals IntMinFeed_noSmall ; - double dParS = EPS_SMALL ; double dParE = EPS_SMALL ; bool bFound = IntMinFeed.GetFirst( dParS, dParE) ; while ( bFound) { @@ -302,7 +284,6 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV // tolgo le parti piccole Intervals IntMaxFeed_noSmall ; - bFound = IntMaxFeed.GetFirst( dParS, dParE) ; while ( bFound) { if ( dParE - dParS > PockParams.dRad - 5 * EPS_SMALL) @@ -418,6 +399,7 @@ SimplifyCurveByFeeds( ICurveComposite* pCrvCompo, const PocketParams& PockParam, - imposto la Feed dei tratti piccoli come quella dei tratti precedenti ( per evitare singolarità) - effettuo un nuovo Merge per uniformare ulteriormente i nuovi tratti ottenuti */ + double dCurrTempParam ; int nParStart = 0 ; double dTempParam ; @@ -509,8 +491,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs return AssignMaxFeed( pCrv, PockParams) ; // imposto di Default la Feed minima per ogni sottocurva - for ( int u = 0 ; u < int( pCrv->GetCurveCount()) ; ++ u) - pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + AssignMinFeed( pCrv, PockParams) ; // se non ho una superificie svuotata, allora esco ( con Feed Minima) if ( pSrfRemoved_offs == nullptr || ! pSrfRemoved_offs->IsValid() || pSrfRemoved_offs->GetChunkCount() == 0) { @@ -757,36 +738,6 @@ IsPointInsideSfr( const ISurfFlatRegion* pSfr, const Point3d& pt, bool& bIsInsid return true ; } -//---------------------------------------------------------------------------- -static bool -GetCurvesForOptimizedPocketing( const ISurfFlatRegion* pSfr, ICRVCOMPOPOVECTOR& vCrvExtOrig) -{ - - // controllo parametri - if ( pSfr == nullptr || ! pSfr->IsValid()) { - vCrvExtOrig.emplace_back( CreateCurveComposite()) ; - return true ; // <- se superficie non valida, allora non ho curve da salvare - } - vCrvExtOrig.clear() ; - - // NB. I Loop esterni sono salvati con TmpProp0 = 0 ; a seguire ognuno di essi ci sono tutte le isole - // di tale Loop con TmpProp0 = 1 - - // ricavo tutti i Loop esterni e interni della superficie con i lati Aperti/Chiusi - for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++ c) { - for ( int l = 0 ; l < pSfr->GetLoopCount( c) ; ++ l) { - PtrOwner pCrvCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ; - if ( IsNull( pCrvCompoLoop) || ! pCrvCompoLoop->IsValid()) - return false ; - pCrvCompoLoop->SetTempProp( ( l == 0 ? 0 : 1), 0) ; // 0 -> loop esterno | 1 -> isola - vCrvExtOrig.emplace_back( Release( pCrvCompoLoop)) ; - } - } - - return true ; - -} - //---------------------------------------------------------------------------- static bool GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) @@ -796,6 +747,7 @@ GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) if ( pArc == nullptr || ! pArc->IsValid()) return false ; + // recupero il punto medio Point3d ptMid ; if ( ! pArc->GetMidPoint( ptMid)) return false ; @@ -809,17 +761,20 @@ GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) // effettuo la classificazione IntersCurveCurve intCC( *pArc, *pCrvTool) ; CRVCVECTOR ccClass ; - if ( intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) && - int( ccClass.size()) == 3 && - ccClass[1].nClass == CRVC_IN) { + if ( intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) && int( ccClass.size()) == 3 && + ccClass[1].nClass == CRVC_IN) { + // recupero i due punti di intersezione Point3d ptS, ptE ; pCrvTool->GetPointD1D2( ccClass[1].dParS, ICurve::FROM_MINUS, ptS) ; pCrvTool->GetPointD1D2( ccClass[1].dParE, ICurve::FROM_PLUS, ptE) ; + // vettori uscenti dal centro dell'arco e diretti verso i punti di intersezione Vector3d vtS = ptS - pArc->GetCenter() ; Vector3d vtE = ptE - pArc->GetCenter() ; + // angolo tra i due vettori double dTheta ; vtS.GetAngle( vtE, dTheta) ; dTheta = abs( dTheta) ; + // lunghezza del tratto di arco compreso dSubArc = pArc->GetRadius() * DEGTORAD * dTheta ; } else @@ -844,7 +799,7 @@ GetParamForPtStartOnEdge( const ICurve* pCrvCheck, const ICurveComposite* pCrvCo // controllo dei parametri if ( pCrvCheck == nullptr || ! pCrvCheck->IsValid() || - pCrvCompo == nullptr || ! pCrvCompo->IsValid() || pCrvCompo->GetCurveCount() == 0) + pCrvCompo == nullptr || ! pCrvCompo->IsValid() || pCrvCompo->GetCurveCount() == 0) return false ; // clono le curve @@ -853,7 +808,7 @@ GetParamForPtStartOnEdge( const ICurve* pCrvCheck, const ICurveComposite* pCrvCo if ( IsNull( pCrv) || IsNull( pCompo)) return false ; ICRVCOMPOPOVECTOR vCrvNoInters ; - for ( int i = 0 ; i < ( int)vOtherCrv.size() ; ++ i) + for ( int i = 0 ; i < int( vOtherCrv.size()) ; ++ i) vCrvNoInters.emplace_back( ConvertCurveToComposite( vOtherCrv[i]->Clone())) ; // ricavo l'estrusione della curva composita @@ -973,35 +928,6 @@ GetParamForPtStartOnEdge( const ICurve* pCrvCheck, const ICurveComposite* pCrvCo return false ; } -//---------------------------------------------------------------------------- -static bool -ExistOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParam, bool& bExist) -{ - // controllo dei parametri - if ( pSfr == nullptr || ! pSfr->IsValid()) - return false ; - // controllo la presenza di lati aperti - PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfr->GetLoop( 0, 0))) ; - if ( IsNull( pCrvExtLoop)) - return false ; - for ( int u = 0 ; u < pCrvExtLoop->GetCurveCount() ; ++ u) { - const ICurve* pCrv_u = pCrvExtLoop->GetCurve( u) ; - if ( pCrv_u == nullptr) - return false ; - bool bIsOpen = ( pCrv_u->GetTempProp( 0) == 1) ; - if ( bIsOpen) { - double dLen = EPS_SMALL ; - if ( pCrv_u->GetLength( dLen) && dLen > 2 * PockParam.dRad + 500 * EPS_SMALL) { - bExist = true ; - return true ; - } - } - } - - bExist = false ; - return true ; -} - //---------------------------------------------------- static bool ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const Vector3d& vtMainDir, bool bLeadIn, @@ -1814,6 +1740,7 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam return true ; // scorro i chiusi e sottraggo la regione da loro creata mediante l'utensile + // NB. Queste curve sono orientate in maniera corretta ICRVCOMPOPOVECTOR vCrvOffs ; // salvo il vettore di curve offsettate del raggio utensile for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { if ( vpCrvs[i]->GetTempProp( 0) == 0) { // se tratto chiuso... @@ -1880,6 +1807,8 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam if ( OffsCrv.Make( pCrvIsl, - PockParams.dRad, ICurve::OFF_FILLET)) { PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; while ( ! IsNull( pOffLongestCrv)) { + // inverto la curva dato che è il contorno di un'isola + pOffLongestCrv->Invert() ; // salvo la curva corrente vCrvOffs.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; // passo alla successiva @@ -1914,14 +1843,24 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam // i percorsi sono definiti dall'Offset della regione rimossa // NB. Se ho inserito solo isole, allora l'Offset va verso l'esterno // Se ho inserito sia il loop esterno che le isole, allora l'Offset è interno + // La superficie la Oriento sempre con normale Z_AX + if ( AreOppositeVectorApprox( pSfrToOffset->GetNormVersor(), Z_AX)) + pSfrToOffset->Invert() ; double dOffs = PockParams.dRad ; if ( bExtAllClose) dOffs *= -1 ; pSfrToOffset->Offset( dOffs, ICurve::OFF_FILLET) ; if ( pSfrToOffset->IsValid() && pSfrToOffset->GetChunkCount() > 0) { for ( int c = 0 ; c < pSfrToOffset->GetChunkCount() ; ++ c) - for ( int l = 0 ; l < pSfrToOffset->GetLoopCount( c) ; ++ l) - vCrvCompoRes_tmp.emplace_back( ConvertCurveToComposite( pSfrToOffset->GetLoop( c, l))) ; + for ( int l = 0 ; l < pSfrToOffset->GetLoopCount( c) ; ++ l) { + // recupero il loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrToOffset->GetLoop( c, l))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + if ( l > 0) // se isola, inverto il senso di percorrenza + pCrvLoop->Invert() ; + vCrvCompoRes_tmp.emplace_back( Release( pCrvLoop)) ; + } bAllRemoved = true ; } } @@ -1929,6 +1868,12 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam if ( vCrvCompoRes_tmp.empty()) return true ; + // se richiesta inversione, cambio l'orientamento delle curve ottenute + if ( PockParams.bInvert) { + for ( int i = 0 ; i < int( vCrvCompoRes_tmp.size()) ; ++ i) + vCrvCompoRes_tmp[i]->Invert() ; + } + // recupero la superficie limite ( se esiste ed è valida) PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; if ( IsNull( pSfrLimit)) @@ -2209,7 +2154,6 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == 1) pPrevCrv->GetLength( dLenPrev) ; const ICurve* pCrv = pCompo->GetFirstCurve() ; - int nPriorityOpenEdge = -1 ; while ( pCrv != nullptr) { // analizzo la curva successiva const ICurve* pNextCrv = pCompo->GetNextCurve() ; @@ -2219,7 +2163,6 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth double dLenNext = 0 ; if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == 1) pNextCrv->GetLength( dLenNext) ; - ++ nPriorityOpenEdge ; // verifico la curva corrente if ( pCrv->GetTempProp() == 1) { // contributo dalle entità adiacenti (se non tutte aperte) @@ -2283,9 +2226,6 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth // vettore d'uscita nel sistema di riferimento globale Vector3d vtMidOut = vtMidOrt ; vtMidOut.ToGlob( frPocket) ; - // ricavo il punto fuori - Point3d ptOut = ptStart + vtMidOut * ( PockParams.dRad + PockParams.dRadialOffset + - ( PockParams.dRad + PockParams.dOpenMinSafe)) ; } } dLenPrev = dLen ; @@ -3678,83 +3618,6 @@ CalcTrapezoidSpiralXCoord( const ICurveComposite* pCrvPocket, int nBase, int nSe return true ; } -//---------------------------------------------------- -static bool -SpecialAdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const bool bEvenClosed, - const PocketParams& PockParams, const ICurveComposite* pCrvPocket) -{ - // parametri - double dDiam = PockParams.dRad_prec > 0 ? 2 * PockParams.dRad_prec : 2 * PockParams.dRad ; - double dOffsR = PockParams.dRad_prec > 0 ? PockParams.dRadialOffset_prec : PockParams.dRadialOffset ; - double dRad = 0.5 * dDiam + dOffsR ; - - // calcolo gli offset dei lati obliqui - PtrOwner pLineS( GetCurveLine( pCrvPocket->GetCurve( bEvenClosed ? 0 : 3)->Clone())) ; - pLineS->SimpleOffset( - dRad) ; - pLineS->Invert() ; - PtrOwner pLineE( GetCurveLine( pCrvPocket->GetCurve( bEvenClosed ? 2 : 1)->Clone())) ; - pLineE->SimpleOffset( - dRad) ; - 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->GetCurve( bEvenClosed ? 1 : 0)->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, bEvenClosed ? 90 : 0, 0.5)) ; - - // secondo raccordo - vtE.Invert() ; - vtE.GetAngleXY( X_AX, dAng) ; - PtrOwner pBiArc2( GetBiArc( ptE, - dAng, ptCrv2, bEvenClosed ? - 90 : 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 ; -} - //---------------------------------------------------- static bool AdjustTrapezoidSpiralForAngles( ICurveComposite* pMCrv, const ICurveComposite* pCrvPocket, @@ -4532,6 +4395,7 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; if ( ! pCompoHelp->Clear()) return false ; + // per ogni intersezione j con l'offset dell'isola i for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { // se ho intersezione spezzo il segmento @@ -4595,8 +4459,10 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const } } - // smusso e restituisco - ModifyCurveToSmoothed( pCompo, PockParams, 0.05, 0.05, true) ; + PtrOwner pCrvCompo_noSmooth( CloneCurveComposite( pCompo)) ; + if ( ! ModifyCurveToSmoothed( pCompo, PockParams, 0.05, 0.05, true) || + ! pCompo->IsValid()) + pCompo.Set( Release( pCrvCompo_noSmooth)) ; pCrvLink->AddCurve( Release( pCompo)) ; return true ; @@ -4702,7 +4568,7 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM ++ nIter ; } - pCrvLink->AddCurve( ptCrvFinal->Clone()) ; // ultimo arco valido trovato + pCrvLink->AddCurve( Release( ptCrvFinal)) ; // ultimo arco valido trovato return true ; } @@ -5982,7 +5848,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con return false ; // NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, PockParams, pCrvLink, - i == 0 ? 0 : 0.01, 0.01, 2)) { + i == 0 ? 0 : 0.01, 0.01, 2) || ! pCrvLink->IsValid()) { // se non sono riuscito, cerco una strada più semplice // ripristino le curve pCrvLink->Clear() ; @@ -6354,12 +6220,12 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int 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 - if ( ! pMCrv->AddCurve( vLinks[i]->Clone())) + if ( ! pMCrv->AddCurve( Release( vLinks[i]))) { return false ; + } } - pMCrv->AddCurve( vOffs[i]->Clone()) ; + pMCrv->AddCurve( Release( vOffs[i])) ; } // semplifico la curva ottenuta From ff9ea34ae1f477e613c5e19a07106367fd31849b Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Tue, 9 Jul 2024 16:48:54 +0200 Subject: [PATCH 7/7] =?UTF-8?q?EgtGeomKernel=20:=20-=20in=20TestPosition?= =?UTF-8?q?=20di=20CollisionAvoid=20possibilit=C3=A0=20di=20restituire=20n?= =?UTF-8?q?ormale=20alla=20superficie=20nell'ultimo=20punto=20di=20contatt?= =?UTF-8?q?o.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CAvToolSurfTm.cpp | 30 ++++++++++++++++++++++-------- CAvToolSurfTm.h | 7 ++++--- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp index 0fcd4c2..acb6f3d 100644 --- a/CAvToolSurfTm.cpp +++ b/CAvToolSurfTm.cpp @@ -121,7 +121,8 @@ CAvToolSurfTm::SetGenTool( const ICurveComposite* pToolOutline) //---------------------------------------------------------------------------- bool -CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist) const +CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, + double& dTotDist, Vector3d* pvtTriaN) const { // Se utensile non definito, errore if ( m_Tool.GetType() == Tool::UNDEF) @@ -141,13 +142,19 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve if ( AreSameFrame( frMove, m_frMove)) { // Eseguo controllo Point3d ptCurr = ptT ; - dTotDist = MyTestPositionHG( ptCurr, vtDir) ; + Vector3d vtTriaN ; + dTotDist = MyTestPositionHG( ptCurr, vtDir, vtTriaN) ; + if ( pvtTriaN != nullptr) + *pvtTriaN = vtTriaN ; return ( dTotDist > - EPS_SMALL) ; } } // Altrimenti eseguo controllo diretto Point3d ptCurr = ptT ; - dTotDist = MyTestPosition( ptCurr, vtDir, vtMove) ; + Vector3d vtTriaN ; + dTotDist = MyTestPosition( ptCurr, vtDir, vtMove, vtTriaN) ; + if ( pvtTriaN != nullptr) + *pvtTriaN = vtTriaN ; return ( dTotDist > - EPS_SMALL) ; } @@ -232,7 +239,8 @@ CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, // Ciclo sui punti da verificare for ( int i = nFirst ; i <= nLast ; ++ i) { // verifico il punto - double dMove = MyTestPositionHG( vPntM[i].first, vtDir) ; + Vector3d vtTriaN ; + double dMove = MyTestPositionHG( vPntM[i].first, vtDir, vtTriaN) ; vPntM[i].second = dMove ; if ( dMove < - EPS_SMALL) return false ; @@ -353,7 +361,8 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou while ( itPntMCurr != lPntM.end()) { // verifico il punto ptCurr = itPntMCurr->first ; - double dMove = MyTestPositionHG( itPntMCurr->first, vtDir) ; + Vector3d vtTriaN ; + double dMove = MyTestPositionHG( itPntMCurr->first, vtDir, vtTriaN) ; itPntMCurr->second = dMove ; if ( dMove < - EPS_SMALL) return false ; @@ -397,7 +406,8 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn Point3d ptMid = Media( ptPrev, ptCurr, 0.5) ; // ne effettuo la correzione per evitare la collisione Point3d ptNewMid = ptMid ; - double dMidMove = MyTestPositionHG( ptNewMid, vtDir) ; + Vector3d vtTriaN ; + double dMidMove = MyTestPositionHG( ptNewMid, vtDir, vtTriaN) ; if ( dMidMove < - EPS_SMALL) return false ; // massima distanza ammissibile @@ -419,9 +429,10 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn //---------------------------------------------------------------------------- double -CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove) const +CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const { double dTotDist = 0 ; + vtTriaN = V_NULL ; for ( auto pStm : m_vSTM) { Triangle3d Tria ; for ( int nTria = pStm->GetFirstTriangle( Tria) ; @@ -433,6 +444,7 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector if ( dDist > EPS_SMALL) { dTotDist += dDist ; ptT += dDist * vtMove ; + vtTriaN = Tria.GetN() ; } } } @@ -441,7 +453,7 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector //---------------------------------------------------------------------------- double -CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) const +CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const { // calcolo box utensile nel riferimento di movimento BBox3d b3Tool ; @@ -463,6 +475,7 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) const } // ciclo sui triangoli che intersecano box in 2d double dTotDist = 0 ; + vtTriaN = V_NULL ; INTVECTOR vnIds ; if ( m_HGrids.Find( b3Tool, vnIds)) { for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) { @@ -478,6 +491,7 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) const if ( dDist > EPS_SMALL) { dTotDist += dDist ; ptT += dDist * m_frMove.VersZ() ; + vtTriaN = Tria.GetN() ; } else if ( dDist < -EPS_SMALL) return -1 ; diff --git a/CAvToolSurfTm.h b/CAvToolSurfTm.h index 37201e9..7aaea3d 100644 --- a/CAvToolSurfTm.h +++ b/CAvToolSurfTm.h @@ -36,7 +36,8 @@ class CAvToolSurfTm : public ICAvToolSurfTm { return m_Tool.GetHeigth() ; } const ICurveComposite& GetToolOutline( bool bApprox = false) const override { return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;} - bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist) const override ; + bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, + double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ; bool TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ; bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ; @@ -47,8 +48,8 @@ class CAvToolSurfTm : public ICAvToolSurfTm private : bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ; bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff) ; - double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove) const ; - double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) const ; + double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const ; + double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const ; bool MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr, const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ; bool PrepareHashGrid( void) ;