diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index e9ae10c..160c946 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- // EgalTech 2023-2023 //---------------------------------------------------------------------------- -// File : EGkCalcPocketing.h Data : 16.11.23 Versione : 2.5j1 +// File : EGkCalcPocketing.cpp Data : 16.11.23 Versione : 2.5j1 // Contenuto : Dichiarazione della funzione per calcolare le curve base di Pocketing // // @@ -66,6 +66,7 @@ struct PocketParams { bool bSmooth = false ; // curve smussate bool bInvert = false ; // inversione dei percorsi bool bAvoidOpt = false ; // flag per evitare casi ottimizzati + bool bConventionalMilling = true ; // flag per Conventional Milling Vs Climb Milling per svuotature a curva singola bool bAllowZigZagOneWayBorders = false ; // flag per abilitare le curve di bordo per ZigZag/OneWay Point3d ptStart = P_INVALID ; // punto d'inizio Point3d ptEnd = P_INVALID ; // punto di fine @@ -84,9 +85,12 @@ struct PocketParams { bool bPolishing = false ; // flag per lucidatura double dEpicyclesRad = 0. ; // raggio degli epicicli double dEpicyclesDist = 0. ; // distanza degli epicicli + // -------------------------------------------------------- + bool bToolCompensation = false ; // flag aggiungere un percorso di contornatura } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket static double TOL_REMOVE_OFFSET = 2. ; // tolleranza per controllo materiale lasciato da un Offset +static double TOL_COMPENSATION_MIN_RAD = 100. * EPS_SMALL ; // tolleranza per creazione archi per angoli interni se richiesto il contorno typedef vector VICRVCOMPOPOVECTOR ; //--------------------------------------------------------------------------- @@ -1020,7 +1024,9 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite* static double GetExtendPathLen( const PocketParams& PockParam) { - return ( Clamp( 2. * PockParam.dRad - PockParam.dOpenEdgeRad, 0., PockParam.dRad) + PockParam.dOpenMinSafe) ; + double dDistToolCenterWithMaterial = PockParam.dOpenEdgeRad - PockParam.dRad - PockParam.dRadialOffset ; + double dOutDist = Clamp( PockParam.dRad - dDistToolCenterWithMaterial, 0., PockParam.dRad) ; + return dOutDist + PockParam.dOpenMinSafe ; } //---------------------------------------------------------------------------- @@ -1061,7 +1067,7 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa const array vAngles{ 0., ANG_RIGHT, 3 * ANG_RIGHT, ANG_45, 3 * ANG_45, 5 * ANG_45, 7 * ANG_45} ; // ruoto il versore di uscita cercando un'entrata valida - double dMinDist = PockParams.dRad + PockParams.dRadialOffset ; + double dMinDist = 0. ; for ( int i = 0 ; i < ssize( vAngles) ; ++ i) { // ruoto il versore d'uscita Vector3d vtRotOut = GetRotate( vtFirstOut, Z_AX, - vAngles[i]) ; @@ -2114,7 +2120,7 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, PocketParams& PockParams, return false ; // imposto le Feed e inverto i percorsi per tali curve se richiesto - bool bAllowInvert = ( PockParams.nType == POCKET_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ZIGZAG) ; + bool bAllowInvert = ( ! PockParams.bConventionalMilling) ; for ( int i = 0 ; i < ssize( vCrvSingleCurves) ; ++ i) { /* Idea : Feed proporzionale al minimo Offset per annullare la regione @@ -2719,7 +2725,7 @@ IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& Pock break ; } } - bForced = ( dLenOpen < dDiam + TOL_TRAPEZOID) ; + bForced = ( dLenOpen < dDiam + 2. * PockParam.dRadialOffset + TOL_TRAPEZOID) ; } // se alternate, non forzo else @@ -2752,7 +2758,7 @@ IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& Pock break ; } } - bForced = ( dLenOpen < dDiam + TOL_TRAPEZOID) ; + bForced = ( dLenOpen < dDiam + 2. * PockParam.dRadialOffset + TOL_TRAPEZOID) ; } break ; // se tutto chiuso, è forzato @@ -3761,9 +3767,9 @@ AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam, // se esiste almeno un aperto if ( nTmpProp > 0) { // se solo lato3 aperto - bool bCheckHead = ( nTmpProp != 8 && nTmpProp != 2) ; if ( nTmpProp == 2) pCrvRes->Invert() ; // entro dall'unico aperto + bool bCheckHead = ( nTmpProp != 8 && nTmpProp != 2) ; if ( bCheckHead) { // recupero gli estremi della curva corrente e la inverto in base alla Testa Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; @@ -3775,9 +3781,15 @@ AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam, pCrvRes->Invert() ; } } + else if ( ! PockParam.bConventionalMilling) { // per sgrossature + Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; + Point3d ptE ; pCrvRes->GetEndPoint( ptE) ; + if ( SqDist( ptE, PockParam.ptEnd) < SqDist( ptE, PockParam.ptEnd) + EPS_SMALL) + pCrvRes->Invert() ; + } // Assegno la Feed - AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; + AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; // Se curva da invertire, inverto if ( PockParam.bInvert) pCrvRes->Invert() ; @@ -3859,8 +3871,7 @@ GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& //---------------------------------------------------------------------------- static bool -GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam, - ICurveComposite* pCrvRes) +GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, PocketParams& PockParam, ICurveComposite* pCrvRes) { // controllo dei parametri if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid()) @@ -3940,6 +3951,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& - E' richiesto che una dimensione del box della curva sia compatibile con il primo Offset, il quale sarebbe una singola curva aperta */ + bool bOkForToolCompensation = false ; PtrOwner pCrvTrap( CreateCurveComposite()) ; if ( IsNull( pCrvTrap)) return false ; @@ -3947,6 +3959,12 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& double dPocketSize ; int nBase, nSecondBase ; bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; + // se è un percorso di Tool Compensation ed è un trapezio ma non svuotabile, provo normalmente + if ( PockParam.bToolCompensation && bOkTrap && ! pCrvTrap->IsValid()) { + PockParam.dRadialOffset -= PockParam.dSideStep ; + bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; + bOkForToolCompensation = true ; + } if ( bOkTrap && pCrvTrap->IsValid()) { // verifico se il trapezio ottenuto deve o meno rispettare il SideStep bool bForcedTrap = false ; @@ -3977,14 +3995,15 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& } } } + if ( bOkForToolCompensation) + PockParam.dRadialOffset += PockParam.dSideStep ; return true ; } //---------------------------------------------------------------------------- static bool -GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParam, - ICRVCOMPOPOVECTOR& vCrvOptCurves) +GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, PocketParams& PockParam, ICRVCOMPOPOVECTOR& vCrvOptCurves) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid()) @@ -7341,10 +7360,14 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio if ( IsNull( pSfrLimit)) return false ; if ( PockParams.SfrLimit.IsValid()) { + const double TOL_LIMIT = 50. * EPS_SMALL ; pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; - pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset - 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + if ( PockParams.bToolCompensation) + dOffs -= PockParams.dSideStep ; + pSfrLimit->Offset( dOffs - TOL_LIMIT, ICurve::OFF_FILLET) ; } // vettore delle curve chiuse Offsettate @@ -7353,7 +7376,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio // scorro i Chunk e i Loop della regione ( se OneWay potrei avere più Chunks) for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { - ICRVCOMPOPOVECTOR vClosedOffs_nC ; + ICRVCOMPOPOVECTOR vCrvChunk ; // loop come curva composita PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) @@ -7371,37 +7394,46 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio } } // le isole aperte vanno percorse - bool bOpenIsland = ( nL > 0 && int( vpCrvs.size()) == 1 && + bool bOpenIsland = ( nL > 0 && ssize( vpCrvs) == 1 && vpCrvs[0]->GetTempProp() == TEMP_PROP_OPEN_EDGE) ; // scorro tutti i tratti omogenei - for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i) { // se tratto chiuso o isola aperta if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE || bOpenIsland) { // Offset per le curve OffsetCurve OffsCrv ; double dOffs = - PockParams.dRad - PockParams.dRadialOffset ; + if ( PockParams.bToolCompensation) + dOffs += PockParams.dSideStep - TOL_COMPENSATION_MIN_RAD ; // se isola aperta, allora l'offset è verso il suo interno if ( bOpenIsland) dOffs *= -1 ; if ( OffsCrv.Make( vpCrvs[i], dOffs, ICurve::OFF_FILLET)) { PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; - while ( ! IsNull( pOffLongestCrv)) { + while ( ! IsNull( pOffLongestCrv) && pOffLongestCrv->IsValid()) { + // se tool compensation effettuo un ulteriore controOffset + if ( PockParams.bToolCompensation) { + OffsetCurve OffsCrv1 ; + if ( ! OffsCrv1.Make( pOffLongestCrv, TOL_COMPENSATION_MIN_RAD, ICurve::OFF_FILLET) || + ! pOffLongestCrv.Set( OffsCrv1.GetLongerCurve())) + return true ; + } // recupero solo i tratti di curva al di fuori della superficie limite if ( pSfrLimit->IsValid()) { CRVCVECTOR ccClass ; if ( pSfrLimit->GetCurveClassification( *pOffLongestCrv, EPS_SMALL, ccClass)) { - for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + for ( int j = 0 ; j < ssize( ccClass) ; ++ j) { if ( ccClass[j].nClass == CRVC_OUT) { // recupero il tratto di curva PtrOwner pCrv( pOffLongestCrv->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; if ( ! IsNull( pCrv) && pCrv->IsValid()) - vClosedOffs_nC.emplace_back( ConvertCurveToComposite( Release( pCrv))) ; + vCrvChunk.emplace_back( ConvertCurveToComposite( Release( pCrv))) ; } } } } else - vClosedOffs_nC.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; + vCrvChunk.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; // passo alla successiva pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; @@ -7410,26 +7442,26 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio } } // se non ho ricavato curve dal Loop nL-esimo, passo al successivo - if ( vClosedOffs_nC.empty()) + if ( vCrvChunk.empty()) continue ; // concateno eventuali percorsi - if ( ! ChainCompoCurves( vClosedOffs_nC)) + if ( ! ChainCompoCurves( vCrvChunk)) return false ; // miglioro le curve - for ( auto& crv : vClosedOffs_nC) - crv->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ; + for ( auto& Crv : vCrvChunk) + Crv->MergeCurves( 10. * EPS_SMALL, ANG_TOL_STD_DEG) ; // determino ora il punto di inizio, il tratto per il LeadIn bool bIsChunkClosed = false ; bool bIsChunkAllOpen = false ; if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bIsChunkClosed, bIsChunkAllOpen)) return false ; - if ( ! AdvanceExtendCurves( vClosedOffs_nC, pSfrOrig, PockParams, true)) + if ( ! AdvanceExtendCurves( vCrvChunk, pSfrOrig, PockParams, false)) return false ; // aggiungo le curve ottenute al vettore - for ( int i = 0 ; i < int( vClosedOffs_nC.size()) ; ++ i) - vClosedOffs.emplace_back( Release( vClosedOffs_nC[i])) ; + for ( int i = 0 ; i < ssize( vCrvChunk) ; ++ i) + vClosedOffs.emplace_back( Release( vCrvChunk[i])) ; } } // se non ho percorsi ho finito @@ -7437,15 +7469,30 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio return true ; // Calcolo ora le Feed e restituisco le curve ottenute - for ( int i = 0 ; i < int( vClosedOffs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vClosedOffs) ; ++ i) { // se ZigZag -> ho percorso i tratti a ZigZag, quindi posso andare a Feed massima - if ( PockParams.nType == POCKET_ZIGZAG) + if ( PockParams.nType == POCKET_ZIGZAG) { AssignMaxFeed( vClosedOffs[i], PockParams) ; + vClosedOffs[i]->SetTempProp( PockParams.bToolCompensation ? TEMP_PROP_CONTOUR_BORDER : TEMP_PROP_BORDER_CURVE, 0) ; + } // se OneWay -> prima percorro queste curva, quindi la Feed è minima - if ( PockParams.nType == POCKET_ONEWAY) + else if ( PockParams.nType == POCKET_ONEWAY) { AssignMinFeed( vClosedOffs[i], PockParams) ; - // assegno la proprità alla curva composita - vClosedOffs[i]->SetTempProp( TEMP_PROP_BORDER_CURVE, 0) ; + vClosedOffs[i]->SetTempProp( PockParams.bToolCompensation ? TEMP_PROP_CONTOUR_BORDER : TEMP_PROP_BORDER_CURVE, 0) ; + } + // se Percorso di Contornatura + else if ( PockParams.bToolCompensation) { + double dFeed = GetMinFeed( PockParams) ; + GetFeedForParam( PockParams.dSideStep, PockParams, dFeed) ; + AssignCustomFeed( vClosedOffs[i], PockParams, dFeed) ; + vClosedOffs[i]->SetTempProp( TEMP_PROP_CONTOUR_BORDER, 0) ; + // se Svuotatura in SpiralOut il contorno esterno deve essere eseguito al contrario ( invert di SpiralIn) + if ( PockParams.nType == POCKET_SPIRALOUT) + vClosedOffs[i]->Invert() ; + } + // se presente flag di inversione, inverto le curve + if ( PockParams.bInvert) + vClosedOffs[i]->Invert() ; // restituisco le curve ottenute vCrvRes.emplace_back( Release( vClosedOffs[i])) ; } @@ -7553,7 +7600,7 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar } // se richiesto, aggiungo le curve chiuse di Bordo - if ( PockParams.bAllowZigZagOneWayBorders && ! PockParams.bPolishing) { + if ( PockParams.bAllowZigZagOneWayBorders && ! PockParams.bPolishing && ! PockParams.bToolCompensation) { // recupero il Chunk nC-esimo PtrOwner pSfrChunk( pSrfPock->CloneChunk( nChunkInd)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid() || @@ -7656,15 +7703,15 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar return false ; // scorro le regioni ideali - for ( int nIs = 0 ; nIs < int( vSrfFlat.size()) ; ++ nIs) { + for ( int nIs = 0 ; nIs < ssize( vSrfFlat) ; ++ nIs) { // copio la superficie ideale ed effettuo il primo Offset PtrOwner pSrfIdeal( CloneSurfFlatRegion( vSrfFlat[nIs])) ; - if ( IsNull( pSrfIdeal) || ! pSrfIdeal->Offset( - dOffs, ICurve::OFF_FILLET)) + if ( IsNull( pSrfIdeal) || ! pSrfIdeal->Offset( - dOffs - dExtra, ICurve::OFF_FILLET)) return false ; // se sono richieste le curve di Bordo, le aggiungo - if ( PockParams.bAllowZigZagOneWayBorders) { + if ( ( PockParams.bAllowZigZagOneWayBorders || PockParams.bToolCompensation) && ! PockParams.bPolishing) { if ( ! GetZigZagOneWayBorderCrvs( vSrfFlat[nIs], pSfrOrig, PockParams, vCrvCompoRes)) return false ; } @@ -7709,10 +7756,9 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar // riempio il vettore di segmenti CRVCVECTOR ccClassSeg ; pSrfIdeal->GetCurveClassification( *pLine, EPS_SMALL, ccClassSeg) ; - 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))) ; + for ( int j = 0 ; j < ssize( ccClassSeg) ; ++ j) { + if ( ccClassSeg[j].nClass == CRVC_IN) { + PtrOwner pCrvSeg( GetCurveLine( pLine->CopyParamRange( ccClassSeg[j].dParS, ccClassSeg[j].dParE))) ; double duF, dLen ; // accorcio leggermente il segmento per non toccare la prima curva di Offset if ( ! pCrvSeg->GetLength( dLen) || @@ -7720,7 +7766,7 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar ! pCrvSeg->GetParamAtLength( dLen - dExtra, duF) || ! pCrvSeg->TrimStartAtLen( dExtra) || ! pCrvSeg->TrimEndAtParam( duF)) - pCrvSeg.Set( GetCurveLine( pLine->CopyParamRange( ccClassSeg[w].dParS, ccClassSeg[w].dParE))) ; + pCrvSeg.Set( GetCurveLine( pLine->CopyParamRange( ccClassSeg[j].dParS, ccClassSeg[j].dParE))) ; // aggiungo il segmento al vettore dei tratti correnti vAddedLines.emplace_back( pCrvSeg->Clone()) ; @@ -7732,24 +7778,13 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar pCrvSegCompo->AddCurve( Release( pCrvSeg)) ; // calcolo la Feed AssignFeedZigZagOneWay( pCrvSegCompo, false, vCrvNull, vLineUnder, vCrvCompoNull, PockParams) ; - // estendo presso lati aperti se richiesto - if ( ! PockParams.bAllClosed) { - Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ; - vtRef.Invert() ; - bool bIsExtended = false ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, GetExtendPathLen( PockParams), bIsExtended)) - return false ; - pCrvSegCompo->GetEndDir( vtRef) ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, GetExtendPathLen( PockParams), bIsExtended)) - return false ; - } 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])) ; + for ( int k = 0 ; k < ssize( vAddedLines) ; ++ k) + vLineUnder.emplace_back( Release( vAddedLines[k])) ; } } @@ -9409,10 +9444,11 @@ CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams& return ( CalcPocketing( pSfr, PockParams.dRad, PockParams.dRadialOffset, PockParams.dSideStep, PockParams.dAngle, PockParams.dOpenMinSafe, nType, PockParams.bSmooth, PockParams.bCalcUnclearedRegs, PockParams.bInvert, PockParams.bAvoidOpt, - PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart, + PockParams.bConventionalMilling, PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart, pSfrLimit, PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.nLiType, PockParams.dLiTang, PockParams.dLiElev, PockParams.nLoType, PockParams.dLoTang, - PockParams.bPolishing, PockParams.dEpicyclesRad, PockParams.dEpicyclesDist, vCrvCompoRes)) ; + PockParams.bPolishing, PockParams.dEpicyclesRad, PockParams.dEpicyclesDist, PockParams.bToolCompensation, + vCrvCompoRes)) ; } //---------------------------------------------------------------------------- @@ -9704,18 +9740,59 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa return true ; } +//---------------------------------------------------------------------------- +static bool +AddContours( const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) +{ + // se contorni non abilitati, non faccio nulla + if ( ! PockParams.bToolCompensation) + return true ; + + // rimuovo tutti i contorni che non sono validi + vCrvCompoRes.erase( + remove_if( vCrvCompoRes.begin(), vCrvCompoRes.end(), []( ICurveComposite* pCrvContour) { + return ( pCrvContour == nullptr || ! pCrvContour->IsValid()) ; }), vCrvCompoRes.end()) ; + + // riporto tutti i contorni nel frame Locale per i conti + for ( auto Iter = vCrvCompoRes.begin() ; Iter != vCrvCompoRes.end() ; ++ Iter) + ( *Iter)->ToLoc( PockParams.frLocXY) ; + + // se devo ripassare i contorni chiusi, tengo una regione di riferimento ( le funzioni successive + // rimuovo i chunk da tale regione se riescono a trovare dei percorsi) + // NB. La regione successivamente verrà estesa presso gli aperti, ma i chiusi non sono mai ricostruiti ! + + // se ho dei percorsi, recupero il punto finale di riferimento ( camberà solo l'inizio delle curve di bordo chiuso, + // le curve di bordo aperte devono mantenere il classico orientamento intrinseco) + if ( ! vCrvCompoRes.empty()) + vCrvCompoRes.back()->GetEndPoint( PockParams.ptEnd) ; + ICRVCOMPOPOVECTOR vCrvContour ; + if ( ! GetZigZagOneWayBorderCrvs( pSfrOrig, pSfrOrig, PockParams, vCrvContour)) + return false ; + vCrvContour.erase( + remove_if( vCrvContour.begin(), vCrvContour.end(), []( ICurveComposite* pCrvContour) { + return ( pCrvContour == nullptr || ! pCrvContour->IsValid()) ; }), vCrvContour.end()) ; + for ( int i = 0 ; i < ssize( vCrvContour) ; ++ i) + vCrvCompoRes.emplace_back( Release( vCrvContour[i])) ; + + // riporto tutte le curve nel frame Globale + for ( auto Iter = vCrvCompoRes.begin() ; Iter != vCrvCompoRes.end() ; ++ Iter) + ( *Iter)->ToGlob( PockParams.frLocXY) ; + + return true ; +} + //---------------------------------------------------------------------------- bool CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, - bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec, + bool bConventionalMilling, bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs, double dMaxOptSize, int nLiType, double dLiTang, double dLiElev, int nLoType, double dLoTang, - bool bPolishing, double dEpicyclesRad, double dEpicyclesDist, ICRVCOMPOPOVECTOR& vCrvCompoRes) + bool bPolishing, double dEpicyclesRad, double dEpicyclesDist, bool bContour, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || - dStep < 10 * EPS_SMALL || + dStep < 10. * EPS_SMALL || ( nType != POCKET_ZIGZAG && nType != POCKET_ONEWAY && nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT && nType != POCKET_CONFORMAL_ZIGZAG && nType != POCKET_CONFORMAL_ONEWAY)) return false ; @@ -9725,9 +9802,10 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double // assegno dati di modulo PocketParams myParams ; + myParams.bToolCompensation = bContour ; myParams.nType = nType ; myParams.dRad = dRad ; - myParams.dRadialOffset = dRadOffs ; + myParams.dRadialOffset = dRadOffs + ( myParams.bToolCompensation ? dStep : 0.0) ; myParams.bSmooth = bSmooth ; myParams.dAngle = dAngle ; myParams.dSideStep = dStep ; @@ -9736,6 +9814,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double myParams.bInvert = bInvert ; myParams.bAvoidOpt = bAvoidOpt ; myParams.bCalcFeed = bCalcFeed ; + myParams.bConventionalMilling = bConventionalMilling ; myParams.bAllowZigZagOneWayBorders = bAllowZigZagOneWayBorders ; myParams.bOptOffsets = ( ! bAllOffs) ; myParams.dMaxOptSize = dMaxOptSize ; @@ -9770,62 +9849,76 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double if ( ! IsSfrAllHomogeneous( pSfr, myParams.bAllClosed, myParams.bAllOpen)) return false ; + // Se richiesti contorni tengo una copia della supericie attuale ( le funzioni sotto potrebbero rimuoverne dei Chunks) + PtrOwner pSfrContour( nullptr) ; + if ( myParams.bToolCompensation) { + if ( ! pSfrContour.Set( CloneSurfFlatRegion( pSfrAdj)) || ! pSfrAdj->IsValid()) + return false ; + } + // ------------ casi ottimizzati ------------------------------------------ ICRVCOMPOPOVECTOR vCrvOptCurves ; if ( ! GetPocketingOptimizedCurves( pSfrAdj, myParams, vCrvOptCurves)) return false ; - for ( int i = 0 ; i < int( vCrvOptCurves.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCrvOptCurves) ; ++ i) { vCrvOptCurves[i]->ToGlob( myParams.frLocXY) ; vCrvCompoRes.emplace_back( Release( vCrvOptCurves[i])) ; } // se ho svuotato tutta la superficie, allora ho finito - if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) + if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) { + // se necessario aggiungo i bordi ed esco + if ( myParams.bToolCompensation) + return AddContours( pSfrContour, myParams, vCrvCompoRes) ; return true ; + } // ------------ recupero le singole curve di svuotatura ------------------- ICRVCOMPOPOVECTOR vCrvSingleCurves ; if ( ! GetSinglePocketingCurves( pSfrAdj, myParams, vCrvSingleCurves)) return false ; - for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCrvSingleCurves) ; ++ i) { vCrvSingleCurves[i]->ToGlob( myParams.frLocXY) ; vCrvCompoRes.emplace_back( Release( vCrvSingleCurves[i])) ; } - // se ho svuotato tutta la superficie, allora ho finito - if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) + if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) { + // se necessario aggiunfo i bordi ed esco + if ( myParams.bToolCompensation) + return AddContours( pSfrContour, myParams, vCrvCompoRes) ; return true ; + } // ------------ estensione lati aperti ------------------------------------ if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams)) return false ; // porto una copia della superficie originale nel frame creato - PtrOwner pSfr_Loc( CloneSurfFlatRegion( pSfr)) ; - if ( IsNull( pSfr_Loc) || ! pSfr_Loc->IsValid() || ! pSfr_Loc->ToLoc( myParams.frLocXY)) + PtrOwner pSfrLoc( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfrLoc) || ! pSfrLoc->IsValid() || ! pSfrLoc->ToLoc( myParams.frLocXY)) return false ; // ------------ calcolo delle curve elementari della superficie ------------------- ICRVCOMPOPOVECTOR vCrvCompoPock ; switch ( nType) { case POCKET_ZIGZAG : - if ( ! AddZigZag( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) + if ( ! AddZigZag( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_ONEWAY : - if ( ! AddOneWay( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) + if ( ! AddOneWay( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_SPIRALIN : - if ( ! AddSpiralIn( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) + if ( ! AddSpiralIn( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_SPIRALOUT : - if ( ! AddSpiralOut( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) + if ( ! AddSpiralOut( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_CONFORMAL_ZIGZAG : case POCKET_CONFORMAL_ONEWAY : - if ( ! AddConformal( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) + if ( ! AddConformal( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock)) return false ; break ; } @@ -9837,11 +9930,17 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double } // riporto tutte le curve ottenute in globale - for ( int i = 0 ; i < int( vCrvCompoPock.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCrvCompoPock) ; ++ i) { vCrvCompoPock[i]->ToGlob( myParams.frLocXY) ; vCrvCompoRes.emplace_back( Release( vCrvCompoPock[i])) ; } + // ------------ aggiunta dei contorni ( se richiesto) -------------------- + if ( myParams.bToolCompensation && nType != POCKET_ONEWAY) { + if ( ! AddContours( pSfrContour, myParams, vCrvCompoRes)) + return false ; + } + return true ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 9191679..95e9d6f 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/RotationMinimizingFrame.cpp b/RotationMinimizingFrame.cpp index cbb878c..c81d7dc 100644 --- a/RotationMinimizingFrame.cpp +++ b/RotationMinimizingFrame.cpp @@ -92,11 +92,18 @@ RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dPa Vector3d vtCurrR = frAct.VersX() ; Vector3d vtCurrT = frAct.VersZ() ; - // punto i-esimo sulla curva e suo vettore tangente + // punto i-esimo sulla curva e suo vettore tangente medio + Point3d ptNextM, ptNextP ; + Vector3d vtNextM, vtNextP ; + if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNextM, &vtNextM) || + ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_PLUS, ptNextP, &vtNextP) || + ! vtNextM.Normalize() || ! vtNextP.Normalize()) + return false ; Point3d ptNext ; Vector3d vtNextT ; - if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) || - ! vtNextT.Normalize()) + ptNext = Media( ptNextM, ptNextP) ; + vtNextT = Media( vtNextM, vtNextP) ; + if ( ! vtNextT.Normalize()) return false ; // controllo per casi degeneri diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 8ccb23d..3ffa6ee 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -1095,7 +1095,7 @@ GetSurfTriMeshSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; // determino algoritmo da usare per calcolare i riferimenti lungo la curva - bool bRMF = vtAx.IsSmall() ; + bool bRMF = ( ! vtAx.IsValid() || vtAx.IsSmall()) ; // riferimento all'inizio della linea guida Point3d ptStart ; @@ -1242,9 +1242,9 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d& if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd)) bIsLine = true ; } - // se la guida è piana + // se la guida è piana e il vettore di riferimento è non definito oppure non nullo Plane3d plGuide ; - if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL)) + if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL) && ( ! vtAx.IsValid() || ! vtAx.IsSmall())) return GetSurfTriMeshSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ; // altrimenti swept 3d