diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 539a225..a40159c 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -55,6 +55,7 @@ struct PocketParams { double dOpenMinSafe = 5. ; // estensione minima di sicurezza double dMaxOptSize = 0. ; // dimensione per ottimizzazione double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag + double dSmooth = 5. ; // parametro di smusso per link ( raccordo ) double dLiTang = INFINITO ; // valore di LeadIn in ingresso bool bCalcUnclearedRegs = true ; // flag per calcolare o meno le regioni non svuotate bool bOptOffsets = true ; // flag per evitare Offset non necessari @@ -1015,7 +1016,7 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite* //---------------------------------------------------------------------------- static bool ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams, - const Vector3d& vtFirstOut, bool bEndOrStart, bool& bOkExtended) + const Vector3d& vtFirstOut, bool bEndOrStart, double dExtension, bool& bOkExtended) { /* Estensione della curva pCompo con un segmento lineare. @@ -1056,7 +1057,7 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa // ruoto il versore d'uscita Vector3d vtRotOut = GetRotate( vtFirstOut, Z_AX, - vAngles[i]) ; // calcolo il punto di caduta dell'utensile - Point3d ptFall = pt + vtRotOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + Point3d ptFall = pt + vtRotOut * dExtension ; // controllo che sia sufficientemente distante dalla superficie limite bool bInside = true ; bool bOkOut = true ; @@ -1170,29 +1171,10 @@ GetHomogeneousParts( ICurveComposite* pCrvCompo, const PocketParams& PockParams, return true ; } -//---------------------------------------------------------------------------- -static bool -GetFirstOffsCrvFromSfr( const ISurfFlatRegion* pSfr, double dOffs, ICRVCOMPOPOVECTOR& vCrvFirstOffs) -{ - // controllo dei parametri - if ( pSfr == nullptr || ! pSfr->IsValid()) - return false ; - vCrvFirstOffs.clear() ; - - // creo la regione mediante Offset - PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) - return false ; - - // inserisco le curve orientante - return ( GetSfrCrvCompoLoops( pSfrOffs, vCrvFirstOffs)) ; -} - //--------------------------------------------------------------------------- static bool CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockParams, - const Vector3d& vtTanS_, const Vector3d& vtTanE_, const double dRad, - ISurfFlatRegion* pSfrInc) + const double dRad, ISurfFlatRegion* pSfrInc) { // controllo dei parametri if ( pCrv == nullptr || ! pCrv->IsValid()) @@ -1318,11 +1300,11 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI pCrvBorder == nullptr || ! pCrvBorder->IsValid() || pCrvBorder->GetCurveCount() == 0) return false ; - // definisco la regione di incidenza + // definisco la regione di incidenza ( leggermente più grande ) PtrOwner pSfrInc( CreateSurfFlatRegion()) ; if ( IsNull( pSfrInc)) return false ; - if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, vtTanS, vtTanE, dRad + 75 * EPS_SMALL, pSfrInc)) { + if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, dRad + 75. * EPS_SMALL, pSfrInc)) { pSfrInc.Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCrvBorder), dRad + 75 * EPS_SMALL, false, false)) ; if ( IsNull( pSfrInc) || ! pSfrInc->IsValid()) return false ; @@ -1347,12 +1329,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI double dArea ; Plane3d plCheck ; if ( ! pCrvCompo->GetArea( plCheck, dArea)) return false ; - bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ; + bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10. * EPS_SMALL) ; // scorro il vettore creato... - for ( int c = 0 ; c < int( vCrvToCheck.size()) ; ++ c) { + for ( int i = 0 ; i < int( vCrvToCheck.size()) ; ++ i) { // 1) recupero la curva corrente - PtrOwner pCrvCurr( vCrvToCheck[c]->Clone()) ; + PtrOwner pCrvCurr( vCrvToCheck[i]->Clone()) ; if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid()) return false ; // 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi ) @@ -1360,12 +1342,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI if ( ! GetHomogeneousParts( pCrvCurr, PockParams, vpCrvs)) return false ; // 3) considero solo i tratti chiusi - for ( int cl = 0 ; cl < int( vpCrvs.size()) ; ++ cl) { - if ( vpCrvs[cl]->GetTempProp() == TEMP_PROP_OPEN_EDGE) + for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { + if ( vpCrvs[nU]->GetTempProp() == TEMP_PROP_OPEN_EDGE) continue ; // 4) effettuo l'Offset della curva di metà dDiamJ OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5 - 20 * EPS_SMALL, PockParams.nOffsType)) + if ( ! OffsCrv.Make( vpCrvs[nU], - dDiamJ / 2. - 20. * EPS_SMALL, PockParams.nOffsType)) return false ; // 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; @@ -1373,7 +1355,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI // 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo") bool bSquareEnds = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; bool bSquareMids = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; - PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, bSquareEnds, bSquareMids)) ; + PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ / 2., bSquareEnds, bSquareMids)) ; if ( IsNull( pSfrBean) || ! pSfrBean->IsValid()) return false ; // inverto se necessario @@ -1381,7 +1363,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI pSfrBean->Invert() ; // 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro bool bDiscard = false ; - if ( ! bIsIsland) { // se tratto un loop esterno + if ( ! bIsIsland) { + // se tratto un loop esterno PtrOwner pSfrBean_test( CloneSurfFlatRegion( pSfrBean)) ; if ( IsNull( pSfrBean_test) || ! pSfrBean_test->IsValid()) return false ; @@ -1390,7 +1373,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI ! pSfrBean_test->IsValid() || pSfrBean_test->GetChunkCount() == 0) ; } - else if ( bIsAllOpen && bIsIsland) { // se isola aperta + else if ( bIsAllOpen && bIsIsland) { + // se isola aperta for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) { for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) { if ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) == REGC_IN1) { @@ -1424,8 +1408,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI PtrOwner pSfrLimit( PockParams.SfrLimit.Clone()) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; - // piccolo Offset per sicurezza - pSfrLimit->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + pSfrLimit->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ; pSfrInc->Subtract( *pSfrLimit) ; // rimuovo la regione limite // può capitare che la regione Limite mi crei più Chunk sulla pSfrInc @@ -1574,7 +1557,6 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI } return true ; - } //---------------------------------------------------------------------------- @@ -1601,9 +1583,14 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI if ( PockParams.bAllowZigZagOneWayBorders && ( PockParams.nType == POCKET_ZIGZAG || PockParams.nType == POCKET_ONEWAY)) dRad += PockParams.dOffsExtra ; - // se lavorazione a ZigZag con smusso, esco di Step/2 per pulire gli aperti + // se lavorazione a ZigZag con smusso if ( PockParams.nType == POCKET_ZIGZAG && PockParams.bSmooth) - dRad += max( PockParams.dSideStep / 2, PockParams.dRad / 8) ; + dRad += PockParams.bSmooth ; + // se lavorazione Conformal + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + if ( PockParams.dRad - PockParams.dSideStep > 0) + dRad -= PockParams.dSideStep ; + } // salvo il raggio trovato PockParams.dOpenEdgeRad = dRad ; @@ -1639,25 +1626,21 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI // controllo che sia almeno lungo quanto il diametro utensile double dLen = 0. ; vpCrvs[i]->GetLength( dLen) ; - if ( dLen > PockParams.dRad * 2 - 5 * EPS_SMALL) { - // ricavo la tangenze dei lati chiusi agli estremi di questa curva - Vector3d vtTanS = V_INVALID ; - Vector3d vtTanE = V_INVALID ; - if ( i != 0) { - if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente - ! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo... - return false ; - vtTanE.Invert() ; // invertita - } - if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i])) + // ricavo la tangenze dei lati chiusi agli estremi di questa curva + Vector3d vtTanS = V_INVALID ; + Vector3d vtTanE = V_INVALID ; + if ( i != 0) { + if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente + ! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo... return false ; + vtTanE.Invert() ; // invertita } - else - nCurrTmpProp = TEMP_PROP_CLOSE_EDGE ; + if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i])) + return false ; } // assegno le proprietà di lato Aperto/Chiuso per la curva corrente for ( int u = 0 ; u < vpCrvs[i]->GetCurveCount() ; ++ u) - vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, 0) ; + vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, TEMP_PROP_CLOSE_EDGE) ; // aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa) if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) { // per sicurezza, se gli estremi non coincidono, creo un piccolo raccordo lineare @@ -1840,14 +1823,14 @@ AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr, Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ; vtStart.Invert() ; bool bIsStartExtended = false ; - if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, bIsStartExtended)) + if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsStartExtended)) return false ; // se aperta, controllo la fine if ( ! bIsClosed) { // ricavo vettore tangente finale e provo ad estendere Vector3d vtEnd ; vCrvCompo[i]->GetEndDir( vtEnd) ; bool bIsEndExtended = false ; - if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, bIsEndExtended)) + if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsEndExtended)) return false ; if ( bIsEndExtended) break ; @@ -2155,7 +2138,6 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, PocketParams& PockParams, return true ; } - //---------------------------------------------------------------------------- static bool ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) @@ -2295,7 +2277,6 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) if ( ! pSrfFinal->IsValid()) return false ; - // chiudo le isole che risultano ambigue ( quindi non omgenee) for ( int nC = 0 ; nC < pSrfFinal->GetChunkCount() ; ++ nC) { for ( int nL = 1 ; nL < pSrfFinal->GetLoopCount( nC) ; ++ nL) { @@ -3662,7 +3643,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->GetStartDir( vtMidOut) ; vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; bool bIsExtended ; - ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, bIsExtended) ; + ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsExtended) ; } // se invece lavorazione in SpiralOut, inverto il percorso else if ( PockParam.nType == POCKET_SPIRALOUT) @@ -3694,11 +3675,11 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsStartExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, bIsStartExtended)) + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) return false ; pCrvRes->GetEndDir( vtRef) ; bool bIsEndExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, bIsEndExtended)) + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, PockParam.dRad + PockParam.dOpenMinSafe, bIsEndExtended)) return false ; if ( bIsEndExtended && ! bIsStartExtended) pCrvRes->Invert() ; @@ -4943,7 +4924,7 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const return false ; } // La curva necessita di un ulteriore smusso, in quanto tagliata su un bordo - ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dRad / 4., PockParams.dRad / 4., false) ; + ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dSmooth, PockParams.dSmooth, false) ; // nel caso speciale della circonferenza, devo impostare il punto iniziale if ( dParMeet < EPS_ZERO) { if ( pCompoTest->IsClosed()) { // sempre... @@ -6064,7 +6045,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co } // smusso le curve di offset ( ad eccezione di quelle di primo Offset) - double dSmoothPar = PockParams.dRad / 8. ; + double dSmoothPar = PockParams.dSmooth / SQRT2 ; for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { if ( i >= nCrvFirstOffs) ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ; @@ -6664,7 +6645,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, bool bIsExtended = false ; if ( bSomeOpen) - ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ; + ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended) ; // inserisco le curve nel vettore vCrvCompoRes.emplace_back( Release( pMCrv)) ; @@ -6946,10 +6927,10 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsExtended = false ; - if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false,bIsExtended)) + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; vpCrvs[nU]->GetEndDir( vtRef) ; - if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, bIsExtended)) + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; } } @@ -7147,10 +7128,10 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsExtended = false ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false,bIsExtended)) + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; pCrvSegCompo->GetEndDir( vtRef) ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, bIsExtended)) + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; } vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ; @@ -7412,7 +7393,7 @@ CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocke if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { // effettuo smusso del tratto lineare SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, bFirstIterOffs0, bFirstIterOffs1, - PockParams.dRad / 5., TOL) ; + PockParams.dSmooth, TOL) ; // per sicurezza aggiorno i nuovi punti e i nuovi parametri double dUNewE ; Point3d ptStartNext ; @@ -7953,21 +7934,37 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const ISurfFlatR return false ; if ( vCrvOffs.empty()) return true ; - /* - dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del - raggio utensile e dell'offset radiale. La ricerca delle zone non svuotate avviene all'interno - di questa regione - */ - ICRVCOMPOPOVECTOR vCrvFirstOffs ; - if ( ! GetFirstOffsCrvFromSfr( pSfrPock, - PockParams.dRad - PockParams.dRadialOffset, vCrvFirstOffs)) + + // definisco la regione di ricerca delle aree non svuotate come la regione originale + PtrOwner pSfrBorder( CloneSurfFlatRegion( pSfrPock)) ; + if ( IsNull( pSfrBorder) || ! pSfrBorder->IsValid()) + return false ; + + // dalla superficie originale, rimuovo le parti definite dai lati chiusi + double dOffs = PockParams.dRad + PockParams.dRadialOffset - 2. * EPS_SMALL ; + ICRVCOMPOPOVECTOR vpCrvs ; + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return false ; + PtrOwner pSfrToDiscard( GetSurfFlatRegionFromFatCurve( pCompoLoop->Clone(), dOffs, false, false)) ; + if ( IsNull( pSfrToDiscard) || ! pSfrToDiscard->IsValid()) + return false ; + if ( ! pSfrBorder->Subtract( *pSfrToDiscard)) + return false ; + } + } + ICRVCOMPOPOVECTOR vCrvBorder ; + if ( ! GetSfrCrvCompoLoops( pSfrBorder, vCrvBorder)) return false ; // determino eventuale regioni con parti non svuotate e imposto la Feed alle curve PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; if ( IsNull( pSfrUncleared)) return false ; - if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) { + if ( GetUnclearedRegionAndSetFeed( vCrvBorder, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) { // estendo i percorsi di Offset se richiesto - if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvFirstOffs, PockParams)) + if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvBorder, PockParams)) return false ; } @@ -8058,14 +8055,24 @@ AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const IS } // estendo il percorso sul tratto iniziale e finale ( se ammissibile) - Vector3d vtTan ; vCrvPaths[i]->GetStartDir( vtTan) ; - vtTan.Invert() ; - bool bOkExtension ; - if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtension)) - return false ; - vCrvPaths[i]->GetEndDir( vtTan) ; - if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtension)) - return false ; + Vector3d vtTanS, vtTanE ; + vCrvPaths[i]->GetStartDir( vtTanS) ; vtTanS.Invert() ; + vCrvPaths[i]->GetEndDir( vtTanE) ; + const int MAXTRY = 8 ; + bool bOkStartExtension = false, bOkEndExtension = false ; + for ( int j = 0 ; j <= MAXTRY ; ++ j) { + if ( bOkStartExtension && bOkEndExtension) + break ; + double dDist = PockParams.dOpenMinSafe + j * ( PockParams.dRad / ( 1. * MAXTRY)) ; + if ( ! bOkStartExtension) { + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanS, false, dDist, bOkStartExtension)) + return false ; + } + if ( ! bOkEndExtension) { + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanE, true, dDist, bOkEndExtension)) + return false ; + } + } } return true ; @@ -8336,7 +8343,7 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid()) return false ; - const double EXTENSION_VAL = 1000. ; + const double EXTENSION_VAL = 5000. ; // ricavo il punto finale della guida Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ; @@ -8365,7 +8372,9 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* Point3d ptPoly ; PL.GetFirstPoint( ptPoly) ; while ( PL.GetNextPoint( ptPoly)) { - if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL)) + Vector3d vtDir = ptPoly - ptEndGuide ; + vtDir.Normalize() ; + if ( ! pSeg->Set( ptEndGuide, ptEndGuide + vtDir * EXTENSION_VAL)) return false ; // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; @@ -8582,7 +8591,6 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS ICRVCOMPOPOVECTOR vpCrvs ; PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() || - ! AdjustCloseEdgesForConformalGuide( pCrvExtLoop, PockParam) || ! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvs)) return false ; if ( ! bOk) @@ -8747,10 +8755,94 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS } // smusso le curve di Offset ( ad eccezione di quelle generate alla prima iterazione) - double dSmoothPar = PockParam.dRad / 8. ; for ( int i = 1 ; i < int( vCrvOffs.size()) ; ++ i) { for ( int j = 0 ; j < int( vCrvOffs[i].size()) ; ++ j) - ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, dSmoothPar, dSmoothPar, false) ; + ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, PockParam.dSmooth, PockParam.dSmooth, false) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes) +{ + // verifica validità della superficie + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + // il tipo può essere solo SpiralIn o SpiralOut + if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT) + return false ; + // calcolo il percorso di svuotatura spiral + 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.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion(), + PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, PockParams.nLiType, + vCrvCompoRes)) ; +} + +//---------------------------------------------------------------------------- +static bool +GetOrigChunkForConformal( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrOrig, + set& setChunks) +{ + // NB. funzione migliorabile... potrei calcolare tutto all'inizio senza ripetere le intersezioni + // controllo validità delle regioni + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + + // se la superficie originale ha un solo Chunk allora è lui stesso + if ( pSfrOrig->GetChunkCount() == 1) { + setChunks.insert( 0) ; + return true ; + } + + // essendo la pSfrChunk estesa, cerco quale chunk di pSfrOrig ha una intersezione valida + for ( int nC = 0 ; nC < pSfrOrig->GetChunkCount() ; ++ nC) { + // se il Chunk è già stato analizzato in precedenza, passo al successivo + if ( setChunks.find( nC) != setChunks.end()) + continue ; + // recupero il Chunk corrente + PtrOwner pSfrChunkOrig( pSfrOrig->CloneChunk( nC)) ; + if ( IsNull( pSfrChunkOrig) || ! pSfrChunkOrig->IsValid()) + return false ; + // controllo se esiste l'intersezione + if ( pSfrChunkOrig->Intersect( *pSfrChunk) && pSfrChunkOrig->IsValid()) + setChunks.insert( nC) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CreateSurfFromOtherChunks( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrOther, const set& setChunks) +{ + // controllo della regione + if ( pSfr == nullptr || + pSfrOther == nullptr || ! pSfrOther->IsValid()) + return false ; + + // se non ho indici di Chunk non faccio nulla + if ( setChunks.empty()) + return true ; + + // scorro gli indici dei Chunks + for ( auto it = setChunks.begin() ; it != setChunks.end() ; ++ it) { + // recupero l'indice del Chunk + int nChunk = *it ; + // recupero il Chunk come regione piana + PtrOwner pSfrChunk( pSfrOther->CloneChunk( nChunk)) ; + if ( ! IsNull( pSfrChunk) && pSfrChunk->IsValid()) { + if ( ! pSfr->IsValid()) + pSfr->CopyFrom( pSfrChunk) ; + else if ( ! pSfr->Add( *pSfrChunk)) + return false ; + } } return true ; @@ -8767,99 +8859,119 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, return true ; // se superifice tutta aperta, lavoro in SPIRAL_IN - if ( PockParams.bAllOpen) { - PockParams.nType = POCKET_SPIRALIN ; - return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; - } + if ( PockParams.bAllOpen) + return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALIN, PockParams, vCrvCompoRes)) ; // se superficie tutta chiusa, lavoro in SPIRAL_OUT - if ( PockParams.bAllClosed) { - PockParams.nType = POCKET_SPIRALOUT ; - return ( AddSpiralOut( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; - } + if ( PockParams.bAllClosed) + return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALOUT, PockParams, vCrvCompoRes)) ; + + // definisco eventuali regioni da lavorare in SpiralIn e SpiralOut + PtrOwner pSfrSpiralIn( CreateSurfFlatRegion()) ; + PtrOwner pSfrSpiralOut( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || IsNull( pSfrSpiralOut)) + return false ; + // NB. La supercicie pSfrPock è estesa presso i lati aperti, quindi il suo numero di Chunk potrebbe + // essere differente dal numero di Chunk della superficie originale di svuotatura. Tengo un insieme di + // di indici dei Chunk che devono essere lavorati in SpiralIn e in SpiralOut + set setIndChunkSpiralIn ; + set setIndChunkSpiralOut ; // scorro i chunk della superficie da lavorare for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + // controllo se il Chunk ha tutte proprietà omogenee tra loro bool bClose, bOpen ; if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bClose, bOpen)) return false ; + // recupero il Chunk come regione piana PtrOwner pSfrChunk( pSfrPock->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; - // se Chunk tutto aperto, lo lavoro in SPIRAL_IN + + // --- se Chunk tutto aperto, aggiorno i Chunk della superficie originale da lavorare in SpiralIn if ( bOpen) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - if ( ! AddSpiralIn( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) return false ; - PockParams.nType = nType ; + continue ; } - // se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT + // --- se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT else if ( bClose) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALOUT ; - if ( ! AddSpiralOut( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralOut)) + continue ; } - // se Chunk non omogeneo - else { - // ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk - VICRVCOMPOPOVECTOR vvCrvOffs ; - if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs)) + // --- se chunk non omogoneo, ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk + VICRVCOMPOPOVECTOR vvCrvOffs ; + if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs)) + return false ; + + // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) + if ( vvCrvOffs.empty()) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) return false ; - // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) - if ( vvCrvOffs.empty()) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - } - else { - // definisco vettore degli Offset e dei Link - ICRVCOMPOPOVECTOR vCrvOffs ; - ICURVEPOVECTOR vCrvLink ; - // ordino le curve di Offset e raccordo - if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) { - // se calcolare i raccordi risulta troppo ambiguo o complesso, ritorno a SpiralIn - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - continue ; - } - // flag per controllo - bool bOk = true ; - // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed - bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ; - // concateno Offset e Links - ICRVCOMPOPOVECTOR vCrvPaths ; - bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ; - // estendo per lati aperti ed ordino i percorsi trovati - bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ; - if ( ! bOk) { - // se qualche passaggio restituisce errore, provo in SpiralIn - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - } - else { - // aggiungo i percorsi ricavati - for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) - vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; - } - } + continue ; + } + + // definisco i vettori ordinati degli Offset e dei Link + ICRVCOMPOPOVECTOR vCrvOffs ; + ICURVEPOVECTOR vCrvLink ; + if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) + return false ; + continue ; + } + + // flag per controllo + bool bOk = true ; + // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed + bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ; + // concateno Offset e Links + ICRVCOMPOPOVECTOR vCrvPaths ; + bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ; + // estendo per lati aperti ed ordino i percorsi trovati + bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ; + + // se qualche passaggio restituisce errore, provo in SpiralIn + if ( ! bOk) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) + return false ; + continue ; + } + // altrimenti aggiungo i percorsi ricavati + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) + vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; + } + + // se ho superfici da lavorare in SpiralIn, aggiungo le curve + if ( ! setIndChunkSpiralIn.empty()) { + // costruisco la regione di SpiralIn + PtrOwner pSfrSpiralIn( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || + ! CreateSurfFromOtherChunks( pSfrSpiralIn, pSfrOrig, setIndChunkSpiralIn)) + return false ; + // recupero le curve di Pocketing SpiralIn + ICRVCOMPOPOVECTOR vCrvSpiralIn ; + if ( ! CalcSpiralPocketing( pSfrSpiralIn, POCKET_SPIRALIN, PockParams, vCrvSpiralIn)) + return false ; + for ( int i = 0 ; i < int( vCrvSpiralIn.size()) ; ++ i) { + if ( vCrvSpiralIn[i] != nullptr && vCrvSpiralIn[i]->IsValid()) + vCrvCompoRes.emplace_back( Release( vCrvSpiralIn[i])) ; + } + } + // se ho superfici da lavorare in SpiralOut, aggiungo le curve + if ( ! setIndChunkSpiralOut.empty()) { + // costruisco la regione di SpiralOut + PtrOwner pSfrSpiralOut( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || + ! CreateSurfFromOtherChunks( pSfrSpiralOut, pSfrOrig, setIndChunkSpiralOut)) + return false ; + // recupero le curve di Pocketing SpiralOut + ICRVCOMPOPOVECTOR vCrvSpiralOut ; + if ( ! CalcSpiralPocketing( pSfrSpiralOut, POCKET_SPIRALOUT, PockParams, vCrvSpiralOut)) + return false ; + for ( int i = 0 ; i < int( vCrvSpiralOut.size()) ; ++ i) { + if ( vCrvSpiralOut[i] != nullptr && vCrvSpiralOut[i]->IsValid()) + vCrvCompoRes.emplace_back( Release( vCrvSpiralOut[i])) ; } } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 9e30757..658e2a7 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ