diff --git a/Pocketing.cpp b/Pocketing.cpp index 0c0d1ae..bfbf834 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -3349,10 +3349,6 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, } // eventuale sistemazione archi VerifyArcs( pMCrv) ; - - - int id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCutRegion->Clone()) ; - m_pGeomDB->SetMaterial( id, Color(128,64,0,50)) ; return true ; } @@ -3408,8 +3404,8 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( pCrvBound->CopyParamRange( dOffS, dOffE)) ; PtrOwner pCrvB( pCrvBound->CopyParamRange( dOffE, dOffS)) ; - if ( IsNull( pCrvA) || IsNull( pCrvB)) - return false ; + if ( IsNull( pCrvA) || IsNull( pCrvB)) + return false ; double dLenA ; pCrvA->GetLength( dLenA) ; double dLenB ; pCrvB->GetLength( dLenB) ; if ( dLenA < dLenB) { @@ -4186,10 +4182,10 @@ Pocketing::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptP //---------------------------------------------------------------------------- bool Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTOR& vOffs) -{ +{ // Conservo le curve vOffs originali in vettore Tmp da usare per i calcoli sui percorsi aggiuntivi ICRVCOMPOPOVECTOR vOffsTmp( vOffs.size()) ; - for ( size_t i = 0 ; i < vOffs.size(); i++) + for ( size_t i = 0 ; i < vOffs.size() ; i++) vOffsTmp[i].Set( GetCurveComposite( vOffs[i]->Clone())) ; ISurfFlatRegion * pNewCutRegion = pCutRegion->Clone() ; @@ -4197,10 +4193,10 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTO // analizzo tutte le aree non lavorate int nLoops = pCutRegion->GetLoopCount(0) ; - for ( int i = 1 ; i < nLoops ; i++) { - + for ( int i = 1 ; i < nLoops ; i++) { + // regione non lavorata - ICurveComposite * pResidualCrv = GetCurveComposite( pCutRegion->GetLoop( 0, i)) ; + ICurve * pResidualCrv = pCutRegion->GetLoop( 0, i) ; if ( pResidualCrv == nullptr || ! pResidualCrv->IsValid()) continue ; @@ -4209,11 +4205,10 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTO Point3d ptCrit ; // punto in cui aggiungere il percorso extra double dParCrit ; // parametro corrispondente a ptCrit - if ( ! FindCurveForPathAdd( pResidualCrv, vOffsTmp, idx, ptCrit, dParCrit, vOffs[0])) - return false ; - - - // Calcolo la lunghezza del tratto da aggiungere basandomi sull'angolo e sull'overlap + if ( ! FindCurveForPathAdd( pResidualCrv, vOffsTmp, idx, ptCrit, dParCrit)) + return false ; + + // calcolo la lunghezza del tratto da aggiungere basandomi sull'angolo e sull'overlap Point3d ptNew ; bool bUsePtNew = false ; @@ -4229,12 +4224,12 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTO vOffsTmp[idx]->GetPointTang( dParCrit, ICurve::FROM_PLUS, Point3d(), vt2) ; vt2.Invert() ; double dCosAng = vt1 * vt2 ; - + // calcolo lunghezza basandomi sull'angolo e sull'overlap double dAngSin = sqrt( (1 - dCosAng) / 2) ; double dOverlap = 1 - GetSideStep() / m_TParams.m_dDiam ; double dLen = dAngSin > EPS_ANG_SMALL ? (( m_TParams.m_dDiam / 2 - m_TParams.m_dDiam * dOverlap) / dAngSin - m_TParams.m_dDiam / 2) : - 1.0 ; - + Point3d ptCen ; pResidualCrv->GetCentroid( ptCen) ; Vector3d vtDir = ptCen - ptCrit ; @@ -4243,33 +4238,27 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTO bUsePtNew = dLen > 0 ; } } - - // Percorso aggiuntivo - ICurveComposite * pAddPath = CreateCurveComposite() ; - ISurfFlatRegion * pAddSrf = pCutRegion->Clone() ; - if ( ! ComputeAdditionalPath( ptCrit, ptNew, bUsePtNew, pAddPath, pResidualCrv, vOffsTmp[0], pAddSrf)) + + // calcolo il percorso aggiuntivo + ICurveComposite * pAddPath = CreateCurveComposite() ; + if ( ! ComputeAdditionalPath( ptCrit, ptNew, bUsePtNew, pAddPath, pResidualCrv, vOffsTmp[0], pNewCutRegion)) return false ; - // se non ho aggiunto alcun percorso passo alla prossima regione + // se non ho aggiunto alcun percorso passo alla prossima regione residua if ( pAddPath->GetCurveCount() == 0) continue ; - - // aggiorno la superficie lavorata - if ( pAddSrf->IsValid() && ! pNewCutRegion->Add( *pAddSrf)) - return false ; // nuova curva di offset con tratti aggiuntivi bAddedPaths = true ; - PtrOwner pNewOffs ; - pNewOffs.Set( CreateCurveComposite()) ; + PtrOwner pNewOffs( CreateCurveComposite()) ; double dPar, dParS, dParE ; vOffs[idx]->GetDomain( dParS, dParE) ; vOffs[idx]->GetParamAtPoint( ptCrit, dPar) ; pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dParS, dPar)) ; // fino al punto critico è il vecchio offset - pNewOffs->AddCurve( pAddPath->Clone()) ; // al punto critico aggiungo il nuovo percorso + pNewOffs->AddCurve( pAddPath) ; // al punto critico aggiungo il nuovo percorso if ( abs( dPar - dParS) > EPS_SMALL && abs( dPar - dParE) > EPS_SMALL) pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dPar, dParE)) ; // aggiungo la parte rimanente del vecchio offset - + vOffs[idx].Set( Release( pNewOffs)) ; } @@ -4277,50 +4266,53 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTO if ( bAddedPaths && pNewCutRegion->GetLoopCount( 0) > 1) if ( ! RemoveUncutRegions( pNewCutRegion, vOffs)) return false ; - + return true ; } //---------------------------------------------------------------------------- bool -Pocketing::FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, - double& dMinDistPar, const ICurve * pCrvBound) -{ - nIdxMin = -1 ; - Point3d ptCen ; - if ( ! pCrv->GetCentroid( ptCen)) - return false ; - double dDistMin = INFINITO ; +Pocketing::FindCurveForPathAdd( const ICurve* pResidualCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, + double& dMinDistPar) +{ + nIdxMin = -1 ; + double dMinDist = INFINITO ; - Vector3d vtExtr ; vOffs[0]->GetExtrusion( vtExtr) ; Frame3d frLoc ; frLoc.Set( ORIG, vtExtr) ; // porto le curve in questo riferimento - CurveLocal pCrvLoc( pCrv, GLOB_FRM, frLoc) ; + CurveLocal pCrvLoc( pResidualCrv, GLOB_FRM, frLoc) ; for ( size_t i = 1 ; i < vOffs.size() ; i ++) { - // verifico se la regione da rimuovere ( pCrv) è esterna alla regione racchiusa da vOffs + // verifico se la parte da rimuovere ( pResidualCrv) è esterna alla regione racchiusa da vOffs[i] CurveLocal pOffsLoc( vOffs[i]->Clone(), GLOB_FRM, frLoc) ; - IntersCurveCurve intersCC( *pCrvLoc, *pOffsLoc) ; + IntersCurveCurve intersCC( *pCrvLoc, *pOffsLoc) ; + if ( intersCC.GetRegionCurveClassification() != CCREGC_NULL && intersCC.GetRegionCurveClassification() != CCREGC_IN1) { - // cerco il punto sulla curva di offset a distanza minima da ptCen double dParS, dParE ; vOffs[i]->GetDomain( dParS, dParE) ; + // considero i punti di congiunzione fra le curve di vOffs[i] for ( int j = int( dParS + 0.5) ; j < int( dParE + 0.5) ; j ++) { - ICurveComposite * pLinkPath = CreateCurveComposite() ; + + // calcolo il punto più vicino su pResidualCrv Point3d ptCrv ; - vOffs[i]->GetPointD1D2( j, ICurve::FROM_MINUS, ptCrv) ; - - // calcolo la distanza come il percorso inerno alla regione che li congiunge - if ( ! CalcBoundedLink( ptCrv, ptCen, pCrvBound, pLinkPath)) + vOffs[i]->GetPointD1D2( j, ICurve::FROM_MINUS, ptCrv) ; + DistPointCurve distPtCrv( ptCrv, *pResidualCrv) ; + int nFlag ; + Point3d ptResCrv ; + distPtCrv.GetMinDistPoint( 0, ptResCrv, nFlag) ; + + // calcolo la distanza come lunghezza del percorso interno alla svuotatura che li congiunge + ICurveComposite * pLinkPath = CreateCurveComposite() ; + if ( ! CalcBoundedLink( ptCrv, ptResCrv, vOffs[0], pLinkPath)) continue ; - double dLen ; - if ( pLinkPath->GetLength( dLen) && dLen < dDistMin) { - dDistMin = dLen ; + double dLen ; + if ( pLinkPath->GetLength( dLen) && dLen < dMinDist) { + dMinDist = dLen ; nIdxMin = i ; ptMinDist = ptCrv ; dMinDistPar = j ; @@ -4328,41 +4320,69 @@ Pocketing::FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOV } } } - + if ( nIdxMin == -1 ) - return false ; + return false ; return true ; } //---------------------------------------------------------------------------- bool - Pocketing::ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath, - ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pAddSrf) -{ - ICurveComposite * pResidualCrvClosed = GetCurveComposite( pResidualCrv->Clone()) ; +Pocketing::ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath, + const ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pNewCutRegion) +{ + ICurveComposite * pResidualCrvClosed = GetCurveComposite( pResidualCrv->Clone()) ; if ( ! pResidualCrv->IsClosed()) pResidualCrvClosed->Close() ; - - // verifico che area non sia troppo piccola - double dArea = 0.0 ; - if ( ! pResidualCrvClosed->GetArea( Plane3d(), dArea) && dArea < EPS_SMALL) - return true ; - - // scelta del punto finale - if ( ! bUsePtEnd) { - pResidualCrv->GetCentroid( ptEnd) ; - // se il centroide non è interno alla regione, prendo come punto finale un punto interno - ISurfTriMesh* pResidualSrfTm = GetSurfTriMeshByFlatContour( pResidualCrvClosed) ; - DistPointSurfTm DistPtSTm( ptEnd, *pResidualSrfTm) ; - Point3d ptMinDist ; - if ( DistPtSTm.GetMinDistPoint( ptMinDist) && ! AreSamePointApprox( ptEnd, ptMinDist)) - ptEnd = ptMinDist ; + // Se chiudendo la curva creo autointersezione, conservo la sottoparte di curva più lunga che non si autointerseca + SelfIntersCurve SelfIntersC( *pResidualCrvClosed) ; + if ( SelfIntersC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + SelfIntersC.GetIntCrvCrvInfo( 0, aInfo) ; + double dParS, dParE ; + pResidualCrvClosed->GetDomain( dParS, dParE) ; + ICurveComposite * pCrvTmp1 = GetCurveComposite( pResidualCrvClosed->CopyParamRange( dParS, aInfo.IciA[0].dU)) ; + pCrvTmp1->AddCurve( pResidualCrvClosed->CopyParamRange( aInfo.IciB[0].dU, dParE)) ; + ICurveComposite * pCrvTmp2 = GetCurveComposite( pResidualCrvClosed->CopyParamRange( aInfo.IciA[0].dU, aInfo.IciB[0].dU)) ; + double dLen1 = 0.0, dLen2 = 0.0 ; + pCrvTmp1->GetLength( dLen1) ; + pCrvTmp2->GetLength( dLen2) ; + + pResidualCrvClosed = dLen1 > dLen2 ? pCrvTmp1->Clone() : pCrvTmp2->Clone() ; } - // se il punto iniziale e finale coincidono, sceglo un nuovo ptEnd - if ( AreSamePointApprox( ptStart, ptEnd)) { + // verifico che area non sia troppo piccola + double dArea = 0.0 ; + Plane3d plPlane ; + if ( pResidualCrvClosed->GetArea( plPlane, dArea) && dArea < 10 * EPS_SMALL) + return true ; + + // inverto direzione della curve per essere coerente con pAddSrf quando credo la superficie + if ( AreOppositeVectorApprox( plPlane.GetVersN(), pNewCutRegion->GetNormVersor())) + pResidualCrvClosed->Invert() ; + + // scelta del punto finale + if ( ! bUsePtEnd) { + pResidualCrv->GetCentroid( ptEnd) ; + + ISurfTriMesh* pResidualSrfTm = GetSurfTriMeshByFlatContour( pResidualCrvClosed) ; + dArea = 0.0 ; + if ( pResidualSrfTm != nullptr && pResidualSrfTm->GetArea( dArea) && dArea < 10 * EPS_SMALL) + return true ; + + // se regione è abbastanza grande e il centroide non è interno alla regione chiamo la funzione specifica + if ( dArea > 5) { + DistPointSurfTm DistPtSTm( ptEnd, *pResidualSrfTm) ; + Point3d ptMinDist ; + if ( DistPtSTm.GetMinDistPoint( ptMinDist) && ! AreSamePointApprox( ptEnd, ptMinDist)) + return AdditionalPathExternalCentroid( ptStart, pAddPath, pResidualCrvClosed, pCrvBound, pNewCutRegion) ; + } + } + + // se il punto iniziale e finale coincidono, scelgo un nuovo ptEnd + if ( AreSamePointEpsilon( ptStart, ptEnd, 1e-2)) { Point3d ptMid ; pResidualCrv->GetMidPoint( ptMid) ; Vector3d vtDir = ptMid - ptStart ; @@ -4370,8 +4390,8 @@ bool double len = Dist( ptStart, ptMid) + 10 * EPS_SMALL - m_TParams.m_dDiam / 2 ; ptEnd = ptStart + len * vtDir ; } - - // creo il percorso fra ptStart e ptEnd senza uscire dalla svuotatura + + // creo il percorso fra ptStart e ptEnd senza uscire dalla svuotatura if ( ! CalcBoundedLink( ptStart, ptEnd, pCrvBound, pAddPath)) return false ; @@ -4380,10 +4400,8 @@ bool // regione svuotata da pAddPath ICurveComposite * pAddPathTmp = CreateCurveComposite() ; - pAddPathTmp->AddPoint( ptStart) ; pAddPathTmp->AddCurve( pAddPath->Clone()) ; pAddPathTmp->AddCurve( pReturnPath->Clone()) ; - Vector3d vtExtr ; pResidualCrv->GetExtrusion( vtExtr) ; pAddPathTmp->SetExtrusion( vtExtr) ; @@ -4393,14 +4411,15 @@ bool ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ; ISurfFlatRegion * pToolSrf = CreateSurfFlatRegion() ; pToolSrf->AddExtLoop( pCrvOffs->Clone()) ; + while ( OffsCrv.GetCurveCount() != 0) { + ICurve * pCrvOffs2 = OffsCrv.GetCurve() ; + pToolSrf->AddIntLoop( pCrvOffs2->Clone()) ; + } // aggiorno la superficie lavorata - if ( ! pAddSrf->IsValid()) - pAddSrf = pToolSrf->Clone() ; - else - pAddSrf->Add( *pToolSrf->Clone()) ; + if ( ! pNewCutRegion->Add( *pToolSrf)) + return false ; - // porto le curva in locale per farne intersezione Frame3d frLoc ; frLoc.Set( ORIG, vtExtr) ; @@ -4410,37 +4429,82 @@ bool IntersCurveCurve intersCC( *pResidualCrvLoc, *pOffsCrvLoc) ; CRVCVECTOR ccClass ; intersCC.GetCurveClassification( 0, ccClass) ; - + // ricorsione su eventuali aree non lavorate rimaste size_t nFirst = 0 ; size_t nLast = ccClass.size() ; - // verifico se posso trattare in una volta sola la parte inziale e finale della curva + // verifico se posso trattare in una volta sola la parte inziale e finale della curva if ( pResidualCrv->IsClosed() && ccClass.front().nClass == CRVC_OUT && ccClass.back().nClass == CRVC_OUT) { ICurveComposite* pNewResidualCrv = CreateCurveComposite() ; pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.back().dParS, ccClass.back().dParE)) ; pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.front().dParS, ccClass.front().dParE)) ; ICurveComposite * pNewAddPath = CreateCurveComposite() ; - if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pAddSrf)) + if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pNewCutRegion)) return false ; pAddPath->AddCurve( pNewAddPath->Clone()) ; nFirst = 1 ; nLast = ccClass.size() - 1 ; } - + for ( size_t i = nFirst ; i < nLast ; i++) { - if ( ccClass[i].nClass == CRVC_OUT ) { ICurve * pNewResidualCrv = pResidualCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE) ; ICurveComposite * pNewAddPath = CreateCurveComposite() ; - if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pAddSrf)) + if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pNewCutRegion)) return false ; - pAddPath->AddCurve( pNewAddPath->Clone()) ; - } + pAddPath->AddCurve( pNewAddPath) ; + } } - pAddPath->AddCurve( pReturnPath->Clone()) ; // percorso di ritorno - return true ; + pAddPath->AddCurve( pReturnPath) ; // percorso di ritorno + return true ; } + +//---------------------------------------------------------------------------- +bool +Pocketing::AdditionalPathExternalCentroid( const Point3d ptStart, ICurveComposite * pAddPath, ICurveComposite * pResidualCrv, + const ICurve * pCrvBound, ISurfFlatRegion * pNewCutRegion) +{ + DistPointCurve distPtCrv( ptStart, *pResidualCrv) ; + double dParam ; + int nFlag ; + Point3d ptEnd ; + distPtCrv.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + distPtCrv.GetMinDistPoint( 0, ptEnd, nFlag) ; + pResidualCrv->ChangeStartPoint( dParam) ; + + if ( ! CalcBoundedLink( ptStart, ptEnd, pCrvBound, pAddPath)) + return false ; + + ICurveComposite * pReturnPath = pAddPath->Clone() ; // percorso di ritorno + pReturnPath->Invert() ; + + pAddPath->AddCurve( pResidualCrv) ; + pAddPath->AddCurve( pReturnPath) ; + + // area coperta da pAddPath + ISurfFlatRegion * pToolSrf = CreateSurfFlatRegion() ; + OffsetCurve OffsCrvPlus ; + OffsCrvPlus.Make( pAddPath, m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pToolSrf->AddExtLoop( pCrvOffPlus->Clone()) ; + + OffsetCurve OffsCrvMinus ; + OffsCrvMinus.Make( pAddPath, - m_TParams.m_dDiam / 2 - 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurveComposite * pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetLongerCurve()) ; + while ( pCrvOffMinus != nullptr) { + if ( GetCurveRadius( pCrvOffMinus) > EPS_ZERO) + pToolSrf->AddIntLoop( pCrvOffMinus) ; + pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetCurve()) ; + } + + // aggiorno la superficie lavorata + if ( ! pNewCutRegion->Add( *pToolSrf)) + return false ; + + return true ; +} \ No newline at end of file diff --git a/Pocketing.h b/Pocketing.h index f3f3e62..c419936 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -88,10 +88,12 @@ class Pocketing : public Machining bool CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) ; bool RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTOR& vOffs) ; - bool FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, - double& dMinDistPar, const ICurve * pCrvBound) ; + bool FindCurveForPathAdd( const ICurve * pResidualCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, + double& dMinDistPar) ; bool ComputeAdditionalPath( const Point3d ptStart, Point3d ptNew, bool bUsePtEnd, ICurveComposite * pAddPath, - ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pAddSrf) ; + const ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pNewCutRegion) ; + bool AdditionalPathExternalCentroid( const Point3d ptStart, ICurveComposite * pAddPath, ICurveComposite * pResidualCrv, + const ICurve * pCrvBound, ISurfFlatRegion * pNewCutRegion) ; bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICurve* pCrvBound, ICurveComposite* pCrvLink) ; bool CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad,