From 21afe8165ced7fe6dea0ece9df6060437dc50362 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 20 May 2025 17:28:05 +0200 Subject: [PATCH] EgtGeomKernel : - In CalcPocketing aggiunto controllo su Feed per lati aperti - In CalcPocketing inizio stesura funzioni per Biarchi. --- CalcPocketing.cpp | 325 +++++++++++++++++++++++++++++----------------- 1 file changed, 203 insertions(+), 122 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 4af806b..14ff319 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -76,6 +76,7 @@ struct PocketParams { double dOpenEdgeRad = 0. ; // raggio effettivo di estensione degli aperti } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket +static double BIARC_MAX_LEN = 200. ; // massima lunghezza oltre la quale il biarco viene smussato typedef vector VICRVCOMPOPOVECTOR ; //--------------------------------------------------------------------------- @@ -389,29 +390,52 @@ CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nSt //---------------------------------------------------------------------------- static bool -AssignFeedForOpenEdge( ICurveComposite* pCrv, const ICurveComposite* pCrvOF_orig, +AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdges, const PocketParams& PockParams) { + // NB. *pSfrOpenEdges deve essere una regione che all'esterno contiene i lati considerati aperti + // Solo ai tratti esterni vengono assegnate le Feed + // 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) ; - GetFeedForParam( PockParams.dOpenEdgeRad, PockParams, dFeed) ; - pCrv->SetCurveTempParam( u, dFeed, 0) ; + // se non ho una regione di classificazione, non faccio nulla + if ( pSfrOpenEdges == nullptr || ! pSfrOpenEdges->IsValid()) + return true ; + + // classifico la curva in base alla regione + CRVCVECTOR ccClass ; + if ( pSfrOpenEdges->GetCurveClassification( *pCrv, EPS_SMALL, ccClass)) { + PtrOwner pNewCrv( CreateCurveComposite()) ; + if ( IsNull( pNewCrv)) + return false ; + for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { + // recupero il tratto di curva corrente + PtrOwner pCrvRange( ConvertCurveToComposite( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; + if ( ! IsNull( pCrvRange) && pCrvRange->IsValid()) { + // se il tratto non è interno, calcolo la sua Feed + if ( ccClass[i].nClass != CRVC_IN) { + double dFeed = GetMinFeed( PockParams) ; + GetFeedForParam( 2. * PockParams.dRad - PockParams.dOpenEdgeRad, PockParams, dFeed) ; + AssignCustomFeed( pCrvRange, PockParams, dFeed) ; + } + // aggiungo il tratto alla sottocurva + if ( ! pNewCrv->AddCurve( Release( pCrvRange))) + return false ; } } + // assegno la curva calcolata + pNewCrv->SetTempProp( pCrv->GetTempProp( 0), 0) ; + pNewCrv->SetTempProp( pCrv->GetTempProp( 1), 1) ; + pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ; + pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ; + double dThick ; pCrv->GetThickness( dThick) ; + pNewCrv->SetThickness( dThick) ; + Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; + pNewCrv->SetExtrusion( vtExtr) ; + pCrv->CopyFrom( pNewCrv) ; } - else - AssignMaxFeed( pCrv, PockParams) ; return true ; } @@ -516,7 +540,7 @@ SimplifyCurveByFeeds( ICurveComposite* pCrvCompo, const PocketParams& PockParam, //---------------------------------------------------------------------------- static bool AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, bool bIsLink, - bool bFirstOffs, const ICurveComposite* pCrv_orig, const PocketParams& PockParams, + bool bFirstOffs, const ISurfFlatRegion* pSfrOpenEdges, const PocketParams& PockParams, double dToll) { // controllo la validità della curva @@ -537,7 +561,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo // se non ho una superificie svuotata, allora esco ( con Feed Minima) if ( pSrfRemoved == nullptr || ! pSrfRemoved->IsValid() || pSrfRemoved->GetChunkCount() == 0) { // controllo eventuali sovrapposizioni con lati aperti - return AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; + return AssignFeedForOpenEdge( pCrv, pSfrOpenEdges, PockParams) ; } // parametro di Offset per regione svuotata ( restringo la superficie in maniera appropriata) @@ -567,9 +591,8 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo if ( IsNull( pCrv_sez)) continue ; // curva troppo piccola, passo alla successiva // controllo se interno o fuori alla regione ( regolando quindi la Feed) - double dCurrFeed = GetMinFeed( PockParams) ; - if ( ccClass[i].nClass == CRVC_IN) // se interna alla regione rimossa... - dCurrFeed = GetMaxFeed( PockParams) ; + double dCurrFeed = ( ccClass[i].nClass == CRVC_IN ? GetMaxFeed( PockParams) : + GetMinFeed( 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) ; @@ -581,13 +604,14 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo pCrv->Clear() ; pCrv->AddCurve( Release( pCrv_new)) ; + // cerco di uniformare i tratti ricavati 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) ; + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) { + double dFeed ; pCrv->GetCurveTempParam( nU, dFeed, 0) ; + if ( abs( dFeed - GetMinFeed( PockParams)) < 5 * EPS_SMALL) + IntMinFeed.Add( nU, nU + 1) ; } double dParS = EPS_SMALL ; double dParE = EPS_SMALL ; // a questo intervallo tolgo tutti i sottotratti di lunghezza inferiore alla tolleranza richiesta @@ -600,13 +624,13 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo 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, GetMaxFeed( PockParams), 0) ; + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) { + if ( ! IntMinFeed_noSmall.IsInside( nU + 0.5)) + pCrv->SetCurveTempParam( nU, GetMaxFeed( PockParams), 0) ; } } else { // ---------------- NEL CASO DI LINK ---------------- - // le curve con lunghezza < dToll vanno modificate + // le curve con lunghezza inferiore alla tolleranza vanno modificate for ( int j = 0 ; j < pCrv->GetCurveCount() ; ++ j) { double dLen = EPS_SMALL ; pCrv->GetCurve( j)->GetLength( dLen) ; @@ -646,8 +670,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo } if ( bFirstOffs) - AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; - + AssignFeedForOpenEdge( pCrv, pSfrOpenEdges, PockParams) ; return true ; } @@ -4664,7 +4687,7 @@ ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) // controllo dei parametri if ( pBiArcLink == nullptr) return false ; - if ( dToll > 0.99 || dToll < 0.01) + if ( dToll > 1. - 10. * EPS_SMALL || dToll < 10. * EPS_SMALL) return false ; pNewBiArc->Clear() ; @@ -4673,8 +4696,8 @@ ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) pBiArcLink->GetDomain( dUS, dUE) ; // prendo i due archi della curva BiArco - PtrOwner pArc1( pBiArcLink->CopyParamRange( dUS, ( dUS + dUE) / 2)) ; - PtrOwner pArc2( pBiArcLink->CopyParamRange(( dUS + dUE ) / 2, dUE)) ; + PtrOwner pArc1( pBiArcLink->CopyParamRange( dUS, ( dUS + dUE) / 2.)) ; + PtrOwner pArc2( pBiArcLink->CopyParamRange(( dUS + dUE ) / 2., dUE)) ; if ( IsNull( pArc1) || ! pArc1->IsValid() || IsNull( pArc2) || ! pArc2->IsValid()) return false ; @@ -4710,13 +4733,57 @@ ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) return true ; } +//------------------------------------------------------------------------------ +static bool +CalcSpecialSmoothBiArc( const ICurveComposite* pCrvBiArc, const ICRVCOMPOPOVECTOR& vOffIslands, + const PocketParams& PockParams, ICurveComposite* pCrvLink) +{ + // controllo della curva + if ( pCrvBiArc == nullptr || ! pCrvBiArc->IsValid() || + pCrvLink == nullptr) + return false ; + pCrvLink->Clear() ; + // controllo che la lunghezza sia sufficiente + double dLen ; pCrvBiArc->GetLength( dLen) ; + if ( dLen < 2 * PockParams.dRad + 50 * EPS_SMALL) + return false ; + // costruisco il tratto lineare + double dULineS, dULineE ; + Point3d ptLineS, ptLineE ; + if ( ! pCrvBiArc->GetParamAtLength( PockParams.dRad, dULineS) || + ! pCrvBiArc->GetPointD1D2( dULineS, ICurve::FROM_MINUS, ptLineS) || + ! pCrvBiArc->GetParamAtLength( dLen - PockParams.dRad, dULineE) || + ! pCrvBiArc->GetPointD1D2( dULineE, ICurve::FROM_MINUS, ptLineE)) + return false ; + // costruisco il collegamento lineare + PtrOwner pLine( CreateCurveComposite()) ; + if ( IsNull( pLine) || + ! CalcBoundedLink( ptLineS, ptLineE, vOffIslands, pLine)) + return false ; + // creo i due raccordi + PtrOwner pCrvStartJoint( pCrvBiArc->CopyParamRange( 0., dULineS)) ; + PtrOwner pCrvEndJoint( pCrvBiArc->CopyParamRange( dULineE, pCrvBiArc->GetCurveCount())) ; + if ( IsNull( pCrvStartJoint) || IsNull( pCrvEndJoint) || + ! pCrvStartJoint->IsValid() || ! pCrvEndJoint->IsValid()) + return false ; + // definisco il BiArco speciale + if ( ! pCrvLink->AddCurve( Release( pCrvStartJoint)) || + ! pCrvLink->AddCurve( Release( pLine)) || + ! pCrvLink->AddCurve( Release( pCrvEndJoint))) + return false ; + // smusso + ModifyCurveToSmoothed( pCrvLink, PockParams, PockParams.dRad / 4., PockParams.dRad / 4., false) ; + return true ; +} + //------------------------------------------------------------------------------ static bool CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, double dParMeet, const ICRVCOMPOPOVECTOR& vOffIslands, - const PocketParams& PockParams, ICurveComposite* pCrvLink) + const PocketParams& PockParams, ICurveComposite* pCrvLink, bool& bSpecial) { // se senza smusso, ritorno tratto lineare + bSpecial = false ; if ( ! PockParams.bSmooth) return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ; @@ -4739,10 +4806,10 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const if ( IsNull( pBiArcLink)) return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ; - // se BiArco troppo grande allora lo modifico - double dLenBiArc ; - pBiArcLink->GetLength( dLenBiArc) ; - if ( dLenBiArc > 200) { + // se BiArco troppo grande allora lo modifico (ne tengo una copia per eventuale gestione speciale) + PtrOwner pCrvBiArc_clone( ConvertCurveToComposite( pBiArcLink->Clone())) ; + double dLenBiArc ; pBiArcLink->GetLength( dLenBiArc) ; + if ( dLenBiArc > BIARC_MAX_LEN) { PtrOwner pCrvNewBiArcS( CreateBasicCurveComposite()) ; ModifyBiArc( pBiArcLink, 0.2, pCrvNewBiArcS) ; pBiArcLink.Set( pCrvNewBiArcS) ; @@ -4856,42 +4923,37 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM pCrvLink->Clear() ; // curva finale da restituire - PtrOwner ptCrvFinal( CreateBasicCurveComposite()) ; - if ( IsNull( ptCrvFinal)) + PtrOwner pCrvFinal( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvFinal)) return false ; - // Prendo i punti, i vettori tangenti e i parametri di essi per le curve - Point3d ptSS, ptSE, ptES, ptEE ; - Vector3d vS, vE ; - double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; - dUSS = 0 ; dUSE = 0 ; - pCrvS->GetEndPoint( ptSE) ; - pCrvS->GetStartPoint( ptSS) ; - pCrvE->GetStartPoint( ptES) ; - pCrvE->GetEndPoint( ptEE) ; - pCrvS->GetEndDir( vS) ; - pCrvE->GetStartDir( vE) ; - pCrvS->GetDomain( dUSS, dUSE) ; - pCrvE->GetDomain( dUES, dUEE) ; - pCrvS->GetLength( dLenS) ; - pCrvE->GetLength( dLenE) ; + // recupero gli estremi delle due curve ( S = Start, E = End) + Point3d ptSS ; pCrvS->GetStartPoint( ptSS) ; + Point3d ptSE ; pCrvS->GetEndPoint( ptSE) ; + Point3d ptES ; pCrvE->GetStartPoint( ptES) ; + Point3d ptEE ; pCrvE->GetEndPoint( ptEE) ; + // recupero i versori per il BiArco + Vector3d vS ; pCrvS->GetEndDir( vS) ; + Vector3d vE ; pCrvE->GetStartDir( vE) ; + // recupero i domini delle curve + double dUSS, dUSE ; pCrvS->GetDomain( dUSS, dUSE) ; + double dUES, dUEE ; pCrvE->GetDomain( dUES, dUEE) ; + // recupero le lunghezze delle curve + double dLenS ; pCrvS->GetLength( dLenS) ; + double dLenE ; pCrvE->GetLength( dLenE) ; - // se ho una curva di primo Offset allora non devo accorciarla ... ( si per bordi esterni che per isole) + // se ho una curva di primo Offset allora non devo accorciarla ( sia per bordi esterni che per isole) for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) { if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE)) - dLenPercS = 0 ; + dLenPercS = 0. ; if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE)) - dLenPercE = 0 ; + dLenPercE = 0. ; } double dLStepS = ( dLenPercS < EPS_SMALL ? 0. : PockParams.dRad) ; double dLStepE = ( dLenPercE < EPS_SMALL ? 0. : PockParams.dRad) ; dLenE = 0 ; - /* - calcolo il biArco tra il punto iniziale e finale dei due offset consecutivi - se richiesto lo smusso -> accorcio entrambi i tratti di Offset e, riuscendo, si sotituisce - il biArco calcolato prima con quest'ultimo - */ + // recupero il numero massimo di iterazioni per il calcolo del BiArco int nMaxIter = 2 ; if ( ! PockParams.bSmooth) nMaxIter = 1 ; @@ -4901,46 +4963,45 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM while ( nIter < nMaxIter) { // calcolo il biArco - PtrOwner ptBiArc( CreateBasicCurveComposite()) ; - if ( ! CalcBoundedSmoothedLink( ptSE, vS, ptES, vE, 0.5, vFirstOffset, PockParams, ptBiArc) || - ptBiArc->GetCurveCount() == 0) + bool bSpecial = false ; + PtrOwner pCrvBiArc( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvBiArc) || + ! CalcBoundedSmoothedLink( ptSE, vS, ptES, vE, 0.5, vFirstOffset, PockParams, pCrvBiArc, bSpecial) || + pCrvBiArc->GetCurveCount() == 0) return false ; + pCrvFinal->Clear() ; + pCrvFinal.Set( pCrvBiArc->Clone()) ; - ptCrvFinal->Clear() ; - ptCrvFinal.Set( ptBiArc->Clone()) ; - - if ( dLenPercE == 0 && dLenPercS == 0 ) + // se non devo cercarne altri, allora tengo quest'ultimo + if ( dLenPercE == 0 && dLenPercS == 0 || bSpecial) break ; - - // se ho trovato un BiArco valido, allora accorcio le due curve di Offset - dLenS -= dLStepS ; + // altrimentik, calcolo un nuovo BiArco, estendendo i suoi estremi + #if 0 // nel caso volessi estendere anche prima del punto finale + dLenS -= dLStepS ; + #endif dLenE += dLStepE ; // ricalcolo il punto iniziale e finale pCrvS->GetParamAtLength( dLenS, dUSE) ; - pCrvS->GetPointD1D2( dUSE, ICurve::FROM_MINUS, ptSE) ; + if ( ! pCrvS->GetPointD1D2( dUSE, ICurve::FROM_MINUS, ptSE, &vS)) + return false ; + vS.Normalize() ; pCrvE->GetParamAtLength( dLenE, dUES) ; - pCrvE->GetPointD1D2( dUES, ICurve::FROM_PLUS, ptES) ; - - // ricalcolo il vettore tangente iniziale e finale - PtrOwner pCrvS_clone( CloneCurveComposite( pCrvS)) ; - PtrOwner pCrvE_clone( CloneCurveComposite( pCrvE)) ; - pCrvS_clone->ChangeStartPoint( dUSE) ; - pCrvE_clone->ChangeStartPoint( dUES) ; - pCrvS_clone->GetStartDir( vS) ; - pCrvE_clone->GetStartDir( vE) ; + if ( ! pCrvE->GetPointD1D2( dUES, ICurve::FROM_PLUS, ptES, &vE)) + return false ; + vE.Normalize() ; ++ nIter ; } - pCrvLink->AddCurve( Release( ptCrvFinal)) ; // ultimo arco valido trovato + pCrvLink->AddCurve( Release( pCrvFinal)) ; // ultimo arco valido trovato return true ; } //---------------------------------------------------------- static bool GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, - const ICurveComposite* pCrv_orig, const PocketParams& PockParams, ISurfFlatRegion* pSrfToCut) + const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ISurfFlatRegion* pSrfToCut) { // controllo dei parametri @@ -4948,7 +5009,10 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& return false ; pSrfToCut->Clear() ; - // 1) creo la regione esterna + // creo la regione esterna ( definita dalle curve di primo Offset) + // NB. Questa regione è diversa dalla pSfrOrig : + // - i tratti chiusi sono Offsettati di R + OffsR() + // - i tratti aperti sono stati estesi all'esterno PtrOwner pSrfExtern( CreateSurfFlatRegion()) ; if ( IsNull( pSrfExtern)) return false ; @@ -4964,8 +5028,20 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& } } - // ---- le seguenti regioni sono distinte per calcolar emeglio la Feed ---- - // Creo la regione svuotata dal Tool negli Offset, nei Links e sia dagli Offsets che dai Links + // 2) creo la regione che all'esterno contiene i lati aperti + // NB. Prendendo la superficie originale ( con lati Open/Close impostati), se effettuo un + // Offset interno dell'estensione degli aperti, tutto ciò che è all'esterno di tale regione è classificato + // come lato aperto + PtrOwner pSfrForOpenEdges( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrForOpenEdges)) + return false ; + if ( pSfrOrig != nullptr && pSfrOrig->IsValid()) { + if ( ! pSfrForOpenEdges.Set( CloneSurfFlatRegion( pSfrOrig)) || + ! pSfrForOpenEdges->Offset( 1000 * EPS_SMALL, ICurve::OFF_FILLET)) + return false ; + } + + // definisco la regione rimossa dall'utensile PtrOwner pSfrTool( CreateSurfFlatRegion()) ; if ( IsNull( pSfrTool)) return false ; @@ -4983,11 +5059,15 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& // Feed bool bFirstOffs = false ; - Point3d ptStart ; vOffs[i]->GetStartPoint( ptStart) ; - for ( int j = 0 ; j < int( vFirstOffs.size()) && ! bFirstOffs ; ++ j) - bFirstOffs = vFirstOffs[j]->IsPointOn( ptStart, 100 * EPS_SMALL) ; + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) + bFirstOffs = true ; + else { + Point3d ptStart ; vOffs[i]->GetStartPoint( ptStart) ; + for ( int j = 0 ; j < int( vFirstOffs.size()) && ! bFirstOffs ; ++ j) + bFirstOffs = vFirstOffs[j]->IsPointOn( ptStart, 100 * EPS_SMALL) ; + } // calcolo gli intervalli di Feed per la curva di Offset - if ( ! AssignFeedSpiral( vOffs[i], pSfrTool, false, bFirstOffs, pCrv_orig, PockParams, 2 * PockParams.dRad / 3)) + if ( ! AssignFeedSpiral( vOffs[i], pSfrTool, false, bFirstOffs, pSfrForOpenEdges, PockParams, 2 * PockParams.dRad / 3)) return false ; // aggiorno la superificie svuotata PtrOwner pSrfToolRegOffi( GetSurfFlatRegionFromFatCurve( vOffs[i]->Clone() , PockParams.dRad + 5 * EPS_SMALL, false, false)) ; @@ -5013,7 +5093,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& PtrOwner pCrvLink( ConvertCurveToComposite( vLinks[nLink_Ind]->Clone())) ; // calcolo gli intervalli di Feed per la curva di Link if ( IsNull( pCrvLink) || ! pCrvLink->IsValid() || - ! AssignFeedSpiral( pCrvLink, pSfrTool, true, false, pCrv_orig, PockParams, 2 * PockParams.dRad / 3)) + ! AssignFeedSpiral( pCrvLink, pSfrTool, true, false, pSfrForOpenEdges, PockParams, 2 * PockParams.dRad / 3)) return false ; // aggiorno la regione svuotata PtrOwner pSrfToolRegLinki( GetSurfFlatRegionFromFatCurve( pCrvLink->Clone(), PockParams.dRad + 5 * EPS_SMALL, false, false)) ; @@ -5235,9 +5315,10 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs } // recupero le due direzioni per i Biarchi bool bSameDir = AreSameVectorEpsilon( vt1, vt2, 2 * EPS_SMALL) ; + bool bSpecial = false ; // se parallele, allora trasformo in una circonferenza if ( bSameDir) { - if ( ! CalcBoundedSmoothedLink( ptMain, V_INVALID, ptCentroid, V_INVALID, 0., vOffsFirstCurve, PockParams, pCrvCurl)) + if ( ! CalcBoundedSmoothedLink( ptMain, V_INVALID, ptCentroid, V_INVALID, 0., vOffsFirstCurve, PockParams, pCrvCurl, bSpecial)) continue ; Vector3d vtStartCheck ; pCrvCurl->GetStartDir( vtStartCheck) ; if ( AreOppositeVectorApprox( vtStartCheck, vt1)) @@ -5256,8 +5337,8 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs PtrOwner pCrvBiArc1( CreateCurveComposite()) ; PtrOwner pCrvBiArc2( CreateCurveComposite()) ; if ( IsNull( pCrvBiArc1) || IsNull( pCrvBiArc2) || - ! CalcBoundedSmoothedLink( ptMain, vt1, ptCentroid, vtDir, bSameDir ? 0. : 0.5, vOffsFirstCurve, PockParams, pCrvBiArc1) || - ! CalcBoundedSmoothedLink( ptCentroid, vtDir, ptMain, vt2, bSameDir ? 0. : 0.5, vOffsFirstCurve, PockParams, pCrvBiArc2)) + ! CalcBoundedSmoothedLink( ptMain, vt1, ptCentroid, vtDir, bSameDir ? 0. : 0.5, vOffsFirstCurve, PockParams, pCrvBiArc1, bSpecial) || + ! CalcBoundedSmoothedLink( ptCentroid, vtDir, ptMain, vt2, bSameDir ? 0. : 0.5, vOffsFirstCurve, PockParams, pCrvBiArc2, bSpecial)) continue ; // aggiorno la curva a ricciolo @@ -5282,6 +5363,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs // se la curva a ricciolo non svuota il Chunk nC-esimo -> percorro il bordo di tale Chunk if ( pSfrChunk->IsValid() || pSfrChunk->GetChunkCount() > 0) { + // so che il punto più vicino alla curva è ptCloser // ricavo dunque il punto più vicino sul bordo del Chunk nC-esimo PtrOwner pCompoChunkBorder( ConvertCurveToComposite( pSfrUncleared->GetLoop( nC, 0))) ; @@ -5297,10 +5379,15 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs double dUS = 0. ; pCompoChunkBorder->GetParamAtPoint( ptCloserOnChunk, dUS) ; pCompoChunkBorder->ChangeStartPoint( dUS) ; + /* Creo due curve composite rappresentanti un piccolo tratto tangente sulla curva di Offset attuale; questi servono per la partenza e l'arrivo dei biArchi */ + if ( bSameDir) { + pt1 = ptMain ; + pt2 = ptMain ; + } PtrOwner pCompoHelpS( CreateCurveComposite()) ; if ( IsNull( pCompoHelpS) || ! pCompoHelpS->AddPoint( pt1 - vt1 / 4) || ! vt1.Normalize() || ! pCompoHelpS->AddLine( pt1)) @@ -5309,6 +5396,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs if ( IsNull( pCompoHelpE) || ! pCompoHelpE->AddPoint( pt2) || ! vt2.Normalize() || ! pCompoHelpE->AddLine( pt2 + vt2 / 4)) continue ; + /* creo il Biarco iniziale ( nel caso non si riuscisse diventa un segmento lineare) @@ -5330,6 +5418,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs // accorgio il bordo dell'Offset in raccordo al BiArco iniziale if ( dMyU > EPS_SMALL) pCompoChunkBorder->TrimStartAtParam( dMyU) ; + /* creo il Biarco finale ( nel caso non si riuscisse diventa un segmento lineare) @@ -5347,6 +5436,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs if ( ! pCrvBiArc2->GetStartPoint( ptMyPoint) || ! pCompoChunkBorder->GetParamAtPoint( ptMyPoint, dMyU)) continue ; + // la curva a ricciolo ora diventa l'unione di pCrvBiArc1 - pCompoChunkBorder - pCrvBiArc2 pCrvCurl->Clear() ; // smusso la curva di bordo del Chunk ( è aperta) @@ -5372,12 +5462,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs continue ; // aggiungo il tratto finale di Offset pCrvTest->AddCurve( ConvertCurveToBasicComposite( pMyOffs->CopyParamRange( dURef2, pMyOffs->GetCurveCount()))) ; - // nel caso di direzioni parallele manca uno smusso - //if ( bSameDir) { - // double dSmoothPar = PockParams.dRad / 8. ; - // ModifyCurveToSmoothed( pCrvTest, PockParams, dSmoothPar, dSmoothPar, false) ; - //} - // provo a controllare che i punti inzili e finali coincidano, in caso aggiorno il nuovo Offset + // provo a controllare che i punti inziali e finali coincidano, in caso aggiorno il nuovo Offset Point3d ptStart_Old ; vOffs[nInd]->GetStartPoint( ptStart_Old) ; Point3d ptEnd_Old ; vOffs[nInd]->GetEndPoint( ptEnd_Old) ; Point3d ptStart_New ; pCrvTest->GetStartPoint( ptStart_New) ; @@ -5405,16 +5490,13 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con // scorro tutte le curva di Offset for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { - // ricavo il punto inziale della curva corrente Point3d ptS ; if ( ! vOffs[i]->GetStartPoint( ptS)) return false ; - int nNextInd = -1 ; // indice della curva successiva double dMinDist = INFINITO ; // distanza tra questa curva e la successiva Point3d ptStartNext ; // punto iniziale della curva successiva - // tra le curve successive cerco la curva interna e più vicina ad essa for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) { IntersCurveCurve IntCC( *vOffs[i], *vOffs[j]) ; @@ -5457,7 +5539,6 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con // scambio la curva i+1 esima con la j-esima ( se non sono già in ordine) if ( nNextInd != i + 1) swap( vOffs[nNextInd], vOffs[i+1]) ; - // cambio il suo punto iniziale nel punto più vicino tovato double dUS ; if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL)) @@ -5476,31 +5557,30 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con if ( IsNull( pCrvLink)) return false ; // NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset - if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, - ( i == 0 ? 0. : 10 * EPS_SMALL), 10 * EPS_SMALL, pCrvLink) || + double dLenPercS = ( i == 0 ? 0. : 10 * EPS_SMALL) ; + double dLenPercE = 10 * EPS_SMALL ; + if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) || ! pCrvLink->IsValid()) { - // se non sono riuscito, cerco una strada più semplice - // ripristino le curve + // se non sono riuscito, cerco una strada più semplice ripristinando le curve pCrvLink->Clear() ; vOffs[i].Set( pCrv_i) ; // chiuso vOffs[i+1].Set( pCrv_ii) ; // chiuso - // recupero i vettori tangente iniziali ( le curve sono chiuse ) + // recupero i vettori tangenti iniziali ( le curve sono chiuse ) Vector3d vtS, vtE ; if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE)) return false ; // creo il bi-arco tra esse - if ( CalcBoundedSmoothedLink( ptS, vtS, ptStartNext, vtE, 0.5, vOffsFirstCurve, PockParams, pCrvLink)) + bool bSpecial = false ; + if ( CalcBoundedSmoothedLink( ptS, vtS, ptStartNext, vtE, 0.5, vOffsFirstCurve, PockParams, pCrvLink, bSpecial)) vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento else return false ; - continue ; // passo alla curva i+1 esima successiva } // per sicurezza aggiorno i nuovi punti e i nuovi parametri double dUNewS, dUNewE ; - if ( ! pCrvLink->GetStartPoint( ptS) || - ! pCrvLink->GetEndPoint( ptStartNext) || + if ( ! pCrvLink->GetEndPoint( ptStartNext) || ! vOffs[i]->GetParamAtPoint( ptS, dUNewS) || ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUNewE)) return false ; @@ -5650,7 +5730,7 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po //---------------------------------------------------------------------------- static bool -CalcSpiral( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, int& nReg, Point3d& ptStart, +CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart, ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops, ICurveComposite* pMCrv, bool& bMidOut, Vector3d& vtMidOut) { // inizializzo il percorso come vuoto @@ -5814,7 +5894,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, int // controllo eventuali parti non svuotate ( e setto la Feed degli Offset e dei Link)... PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; - if ( GetUnclearedRegionAndSetFeed( vOffsFirstCurve, vOffs, vLinks, vCrvOrigChunkLoops[0], PockParams, pSfrUncleared)) { + if ( GetUnclearedRegionAndSetFeed( vOffsFirstCurve, vOffs, vLinks, pSfrOrig, PockParams, pSfrUncleared)) { // modifico i percorsi if ( ! RemoveExtraParts( pSfrUncleared, vOffs, vOffsFirstCurve, PockParams)) return false ; @@ -6379,7 +6459,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, // calcolo il percorso di svuotatura bool bSomeOpen ; Vector3d vtMidOut ; - if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bSomeOpen, vtMidOut)) + if ( ! CalcSpiral( pSfrChunk, pSfrOrig, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bSomeOpen, vtMidOut)) return false ; // se terminate le regioni, esco @@ -6456,7 +6536,7 @@ AddSpiralOut( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, // calcolo il percorso di svuotatura bool bSomeOpen ; Vector3d vtMidOut ; - if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bSomeOpen, vtMidOut)) + if ( ! CalcSpiral( pSfrChunk, pSfrOrig, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bSomeOpen, vtMidOut)) return false ; // se terminate le regioni, esco @@ -7093,7 +7173,8 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket ! pCrvOffs0->GetStartPoint( ptS) || ! pCrvOffs1->GetStartPoint( ptE)) return false ; // creo il bi-arco tra esse - if ( ! CalcBoundedSmoothedLink( ptS, vtS, ptE, vtE, 0.5, vCrvChunk, PockParams, pCrvLink) || + bool bSpecial = false ; + if ( ! CalcBoundedSmoothedLink( ptS, vtS, ptE, vtE, 0.5, vCrvChunk, PockParams, pCrvLink, bSpecial) || ! pCrvLink->IsValid()) return false ; } @@ -7621,7 +7702,7 @@ CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* //---------------------------------------------------------------------------- static bool -ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, +ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, ICURVEPOVECTOR& vCrvLinks) { // controllo dei parametri @@ -7641,7 +7722,7 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketPara PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; if ( IsNull( pSfrUncleared)) return false ; - if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, nullptr, PockParams, pSfrUncleared)) { + if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) { // estendo i percorsi di Offset se richiesto if ( ! RemoveExtraParts( pSfrUncleared, vCrvOffs, vCrvFirstOffs, PockParams)) return false ; @@ -8490,7 +8571,7 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, // flag per controllo bool bOk = true ; // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed - bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, PockParams, vCrvOffs, vCrvLink) ; + bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ; // concateno Offset e Links ICRVCOMPOPOVECTOR vCrvPaths ; bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ;