diff --git a/Pocketing.cpp b/Pocketing.cpp index c7dee8d..71fd199 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -1250,7 +1250,15 @@ Pocketing::GetCurvesAndPartialVolume( SelData Id, ICURVEPLIST& lstPC, ISurfTriMe // inverto per definire il volume di pocketing pStm->Invert() ; // la superficie diventa il suo volume di svuotatura - if ( ! SetPocketingVolume( ptCenter, pStm)) + PNTVECTOR vPts ; + vPts.push_back( ptCenter) ; + for ( int f = 0 ; f < pStm->GetFacetCount() ; ++ f) { + Point3d ptC ; Vector3d vtN ; + if ( ! pStm->GetFacetCenter( f, ptC, vtN)) + return false ; + vPts.push_back( ptC) ; + } + if ( ! SetPocketingVolume( vPts, pStm)) return false ; // ricavo la Depth double dDepth = 0. ; @@ -1461,18 +1469,23 @@ Pocketing::Chain( int nGrpDestId) return false ; // verifico che siano curve chiuse ( devono delimitare l'area da svuotare) + PNTVECTOR vPts ; for ( int u = 0 ; u < int( vCrvCompo.size()) ; ++ u) { if ( ! vCrvCompo[u]->IsClosed()) { m_pMchMgr->SetLastError( 2402, "Error in Pocketing : Open Contour") ; return false ; } + Point3d ptInside ; + if ( ! vCrvCompo[u]->GetCentroid( ptInside)) + return false ; + vPts.push_back( ptInside) ; + for ( int uu = 0 ; uu < vCrvCompo[u]->GetCurveCount() ; ++ uu) { + if ( ! vCrvCompo[u]->GetCurve( uu)->GetMidPoint( ptInside)) + return false ; + vPts.push_back( ptInside) ; + } } - // ricavo il centro della prima curva - Point3d ptInside ; - if ( ! vCrvCompo[0]->GetCentroid( ptInside)) - return false ; - // creazione della TriMesh di pocketing PtrOwner pStmCurve_Volume( CreateSurfTriMesh()) ; if ( IsNull( pStmCurve_Volume) || @@ -1484,7 +1497,7 @@ Pocketing::Chain( int nGrpDestId) } // intersezione della Trimesh con il finito -> rivavo il volume di svuotatura - if ( ! SetPocketingVolume( ptInside, pStmCurve_Volume)) { + if ( ! SetPocketingVolume( vPts, pStmCurve_Volume)) { m_pMchMgr->SetLastError( 2433, "Error in Pocketing : Volume not defined") ; return false ; } @@ -1725,10 +1738,17 @@ Pocketing::CalcOffsExtensionsForCurves( const ICurveComposite* pCrvCompo, const ! vtN.IsValid() || vtN.IsSmall()) return false ; - // ricavo il centroide della curva + // ricavo il centroide della curva e i punti inziali delle sottocurve + PNTVECTOR vPts ; Point3d ptC ; if ( ! pCrvCompo->GetCentroid( ptC)) return false ; + vPts.push_back( ptC) ; + for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u) { + if ( ! pCrvCompo->GetCurve( u)->GetStartPoint( ptC)) + return false ; + vPts.push_back( ptC) ; + } // creo un frame coerente con la curva e la direzione di svuotatura Frame3d frCurr ; frCurr.Set( ptC, vtN) ; @@ -1738,7 +1758,7 @@ Pocketing::CalcOffsExtensionsForCurves( const ICurveComposite* pCrvCompo, const // recupero la part corrente PtrOwner pStmPart( CreateSurfTriMesh()) ; if ( IsNull( pStmPart) || - ! GetCurrentPart( ptC, pStmPart)) + ! GetCurrentPart( vPts, pStmPart)) return false ; // taglio la part con il piano definito dalla curva @@ -1895,7 +1915,7 @@ Pocketing::GetExtendedLoopToFitStmVolume( ICurveComposite* pCrvLoop, const doubl //---------------------------------------------------------------------------- bool -Pocketing::GetCurrentPart( const Point3d& ptInside, ISurfTriMesh* pStmPart) +Pocketing::GetCurrentPart( const PNTVECTOR& vPtInside, ISurfTriMesh* pStmPart) { // controllo MachManager e database geometrico if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) @@ -1931,12 +1951,15 @@ Pocketing::GetCurrentPart( const Point3d& ptInside, ISurfTriMesh* pStmPart) return false ; // porto la Trimesh in globale pStmRawPart->LocToLoc( frPart, GLOB_FRM) ; - // controllo se il punto è interno a tale Part - DistPointSurfTm DistPtStm( ptInside, *pStmRawPart) ; - double dDist ; DistPtStm.GetDist( dDist) ; - if ( DistPtStm.IsPointInside() || DistPtStm.IsSmall()) { - pStmPart->CopyFrom( pStmRawPart) ; - return pStmPart->IsValid() && pStmPart->GetTriangleCount() > 0 ; + // controllo se esiste un punto interno ad essa + for ( int p = 0 ; p < int( vPtInside.size()) ; ++ p) { + DistPointSurfTm DistPtStm( vPtInside[p], *pStmRawPart) ; + double dDist ; DistPtStm.GetDist( dDist) ; + if ( DistPtStm.IsPointInside() || DistPtStm.IsSmall()) { + // se interno, allora prendo restituisco la Part + pStmPart->CopyFrom( pStmRawPart) ; + return pStmPart->IsValid() && pStmPart->GetTriangleCount() > 0 ; + } } } } @@ -1956,7 +1979,7 @@ Pocketing::GetCurrentPart( const Point3d& ptInside, ISurfTriMesh* pStmPart) //---------------------------------------------------------------------------- bool -Pocketing::SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm) +Pocketing::SetPocketingVolume( const PNTVECTOR& vPtInside, ISurfTriMesh* pStm) { // controllo parametro if ( pStm == nullptr || ! pStm->IsValid()) @@ -1965,7 +1988,7 @@ Pocketing::SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm) // recupero il Current Part PtrOwner pStmCurrRawPart( CreateSurfTriMesh()) ; if ( IsNull( pStmCurrRawPart) || - ! GetCurrentPart( ptInside, pStmCurrRawPart)) + ! GetCurrentPart( vPtInside, pStmCurrRawPart)) return false ; // interseco la TriMesh complessiva di pocketing con il finito, ottenendo il volume di svuotatura @@ -2117,10 +2140,18 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) } // recupero la Part in cui è contenuto il volume + PNTVECTOR vPts ; Point3d ptC ; pStm_PartVolume->GetCentroid( ptC) ; + vPts.push_back( ptC) ; + for ( int f = 0 ; f < pStm_PartVolume->GetFacetCount() ; ++ f) { + Vector3d vtN ; + if ( ! pStm_PartVolume->GetFacetCenter( f, ptC, vtN)) + return false ; + vPts.push_back( ptC) ; + } PtrOwner pStm_Part( CreateSurfTriMesh()) ; if ( IsNull( pStm_Part) || - ! GetCurrentPart( ptC, pStm_Part)) { + ! GetCurrentPart( vPts, pStm_Part)) { m_pMchMgr->SetLastError( 2434, "Error in Pocketing : Part not Found") ; return false ; } @@ -2368,8 +2399,8 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) return false ; break ; case POCKET_SUB_SPIRALIN : - if ( ! AddSpiralIn( vSrfSliced, vCrvOEWithFlags, vbChangedPrec, vVtTrasl, vSrfLimit, vtTool, vtTool, dDepth, dElev, - dMaxElev, dOkStep, bSplitArcs, dExtraLenInOut)) + if ( ! AddSpiralIn( vSrfSliced, vCrvOEWithFlags, vbChangedPrec, vVtTrasl, vSrfLimit, + vtTool, vtTool, dDepth, dElev, dMaxElev, dOkStep, bSplitArcs, dExtraLenInOut)) return false ; break ; case POCKET_SUB_SPIRALOUT : @@ -3944,8 +3975,8 @@ Pocketing::AddZigZag( ISURFFRPOVECTOR& vSfr, const std::vectorIsClosed()) { bool bOutTmp = false ; - if ( ! SetBetterPtStartForSubChunks( vCrvIslMergeBorders[x], pSrfChunk, - vPtStart[x], vVtMidOut[x], bOutTmp)) + //if ( ! SetBetterPtStartForSubChunks( vCrvIslMergeBorders[x], pSrfChunk, + // vPtStart[x], vVtMidOut[x], bOutTmp)) return false ; vbMidOut[x] = bOutTmp ; // vector::reference da Bit a Bool } @@ -4047,8 +4078,8 @@ Pocketing::AddZigZag( ISURFFRPOVECTOR& vSfr, const std::vector::reference da Bit a Bool // se richiesto, la inverto @@ -4261,11 +4292,11 @@ Pocketing::AddZigZag( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } + //if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, + // bSplitArcs, bOutRawLeadIn || m_bOpenOutRaw)) { + // m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + // return false ; + //} } // elaborazioni sulla curva corrente //double dMinFeed = GetFeed() * GetSideStep() / m_TParams.m_dDiam ; @@ -4395,11 +4426,11 @@ Pocketing::AddZigZag( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError(2415, "Error in Pocketing : LeadIn not computable"); - return false; - } + //if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, + // bSplitArcs, vCrvInfo[u].bMidOut || bForcedOutStart)) { + // m_pMchMgr->SetLastError(2415, "Error in Pocketing : LeadIn not computable"); + // return false; + //} } // elaborazioni sulla curva corrente @@ -5751,9 +5782,9 @@ Pocketing::AddOneWay( ISURFFRPOVECTOR& vSfr, const std::vector::reference da Bit a Bool // riporto i valori nel sistema di riferimento corretto @@ -5856,10 +5887,10 @@ Pocketing::AddOneWay( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } + //if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs, vbMidOut[u] || vbForcedOutStart[u])) { + // m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + // return false ; + //} } // elaborazioni sulla curva corrente //double dMinFeed = GetFeed() * GetSideStep() / m_TParams.m_dDiam ; @@ -5990,10 +6021,10 @@ Pocketing::AddOneWay( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } + //if ( ! AddLeadIn( ptP, ptS, frLocI.VersX(), vtExtr, pSrfLeanInOut, nullptr, !m_Params.m_bInvert, bSplitArcs, true)) { + // m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + // return false ; + //} // punto finale Point3d ptE ; @@ -6119,9 +6150,9 @@ Pocketing::AdjustTrapezoidSpiralLeadInLeadOutForSideAngle( ICurveComposite* pMCr //---------------------------------------------------------------------------- bool Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& vCrvOrig, BOOLVECTOR& vbChangedPrec, - VCT3DVECTOR& vVtTrasl, ISURFFRPOVECTOR& vSrfLimit, const Vector3d& vtTool, const Vector3d& vtExtr, - const double dDepth, const double dElev, const double dMaxElev, const double dOkStep, const bool bSplitArcs, - const double dExtraLenInOut) + VCT3DVECTOR& vVtTrasl, ISURFFRPOVECTOR& vSrfLimit, const Vector3d& vtTool, + const Vector3d& vtExtr, const double dDepth, const double dElev, const double dMaxElev, + const double dOkStep, const bool bSplitArcs, const double dExtraLenInOut) { // recupero distanze di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; @@ -6140,7 +6171,8 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& ICRVCOMPOPOVECTOR vRCrv ; // vettore delle curve dei percorsi di ritorno dello step precedente vector vvtMidOut ; // vettore dei versori delle direzioni di uscita dello step precedente INTVECTOR vnRegTot ; // vettore dei numeri delle regioni formate dal primo Offset nello step precedente - BOOLVECTOR vbOptTrap ; + BOOLVECTOR vbOptTrap ; // vettore di flag per casi ottimizzati + Point3d ptEndPath ; // punto finale del percorso di svuotatura attuale } ; SpiralData SDStepPrec ; // informazioni Spiral attuali int nOffs_act = 0 ; // Shift indice dei vettori causato da nReg @@ -6156,6 +6188,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& SDStepCurr.vnRegTot = SDStepPrec.vnRegTot ; SDStepCurr.vvtMidOut = SDStepPrec.vvtMidOut ; SDStepCurr.vbOptTrap = SDStepPrec.vbOptTrap ; + SDStepCurr.ptEndPath = SDStepPrec.ptEndPath ; } // se superficie non valida, passo alla prossima @@ -6167,6 +6200,9 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& if ( IsNull( pSrfLeanInOut)) return false ; + // punto finale dello step precedente + Point3d ptEndPrec = ( j == 1 ? P_INVALID : SDStepPrec.ptEndPath) ; + // creo le entità per lo step corrente ICRVCOMPOPOVECTOR vMCrv, vRCrv ; BOOLVECTOR vbOut ; @@ -6235,7 +6271,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& nRegTot = nReg ; // calcolo il percorso di svuotatura - if ( ! CalcSpiral( pSrfChunk, nRegTot, ptStart, vtMidOut, bMidOut, bSplitArcs, pMCrv, pRCrv, + if ( ! CalcSpiral( pSrfChunk, nRegTot, ptStart, ptEndPrec, vtMidOut, bMidOut, bSplitArcs, pMCrv, pRCrv, vCrvOrig[j-1][nInd], j == 1 ? true : vbChangedPrec[j-1], bOptimizedTrap)) return false ; @@ -6264,6 +6300,9 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& SDStepCurr.vvtMidOut.push_back( vtMidOut) ; // memorizzo caso ottimizzato SDStepCurr.vbOptTrap.push_back( bOptimizedTrap) ; + // sovrascrivo sempre il punto finale ( lo aggiorno in caso di più chunks) + Point3d ptEnd ; pMCrv->GetEndPoint( ptEnd) ; + SDStepCurr.ptEndPath = ptEnd ; } // controlli per entrate da fuori al grezzo @@ -6272,7 +6311,9 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& if ( bOutStart && ! bOptimizedTrap) { // calcolo il punto fuori per il LeadIn Point3d ptOut = ptStart + vtMidOut * ( 0.5 * m_TParams.m_dDiam + max( dSafeZ, m_dOpenMinSafe)) ; - ptOut.Translate( vVtTrasl[j-1]) ; // lo traslo allo step corrente + IGeoPoint3d* ptOUTTTTT( CreateGeoPoint3d()) ; ptOUTTTTT->Set( ptOut) ; + int b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, ptOUTTTTT->Clone()) ; + m_pGeomDB->SetMaterial( b, BLUE) ; double dStElev ; // controllo l'elevazione bOutStart = ( ! GetElevation( m_nPhase, ptOut, vtTool, 0.5 * m_TParams.m_dDiam, vtTool, dStElev) || dStElev < EPS_SMALL) ; @@ -6282,7 +6323,6 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& Point3d ptStart ; pMCrv->GetStartPoint( ptStart) ; pRCrv->AddPoint( ptStart) ; } - ptOut.Translate( -vVtTrasl[j-1]) ; // lo ritraslo sulla curva // aggiungo un tratto lineare all'inizio del percorso di svuotatura pMCrv->AddLine( ptOut, false) ; // aggiungo un tratto lineare alla fine del percorso di svuotatura @@ -6445,7 +6485,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& } // aggiungo attacco SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { + if ( ! AddLeadIn( vMCrv[i], ptP1, ptStart, vtStart, V_INVALID, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; return false ; } @@ -6458,9 +6498,15 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& Point3d ptCurr ; GetCurrPos( ptCurr) ; // ricavo il punto che devo raggiungere Point3d ptDest ; vMCrv[i]->GetStartPoint( ptDest) ; + // modifico il punto di destinazione a seconda del tipo di attacco per tangenza + Vector3d vtEnd = vtStart ; + if ( ! vbOut[i]) { + if ( ! SetLeadInPointStart( ptCurr, vtTool, !m_Params.m_bInvert, vtStart, ptDest)) + return false ; + } // calcolo il percorso di ritorno del percorso attuale if ( IsNull( pRCrv) || - ! CalcLinkOnStep( ptCurr, ptDest, vSfr[j-2], vSrfLimit[j-2], pRCrv)) { + ! CalcLinkOnStep( ptCurr, ptDest, vSfr[j-2], ! SDStepCurr.vbOptTrap[i] ? vSrfLimit[j-2] : CreateSurfFlatRegion(), pRCrv)) { m_pMchMgr->SetLastError( 2441, "Error in Pocketing : Return path not computable") ; return false ; } @@ -6472,7 +6518,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& Point3d ptAbove ; GetCurrPos( ptAbove) ; // aggiungo attacco ( solo collegamento ) SetFeed( GetStartFeed()) ; - if ( ! AddLeadIn( ptAbove, ptStart, vtStart, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { + if ( ! AddLeadIn( vMCrv[i], ptAbove, ptStart, vtStart, vtEnd, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; return false ; } @@ -6531,7 +6577,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& SDStepPrec.vnRegTot = SDStepCurr.vnRegTot ; SDStepPrec.vvtMidOut = SDStepCurr.vvtMidOut ; SDStepPrec.vbOptTrap = SDStepCurr.vbOptTrap ; - + SDStepPrec.ptEndPath = SDStepCurr.ptEndPath ; } return true ; @@ -6663,6 +6709,76 @@ bool GetApproxCurveDP( const ICurveComposite* pCrvCompo, const double dToll, ICu } +//---------------------------------------------------------------------------- +bool +Pocketing::SetLeadInPointStart( const Point3d& ptCurr, const Vector3d vtN, const bool& bAtLeft, + Vector3d& vtStart, Point3d& ptDest) +{ + /* + ptCurr -> punto iniziale in cui si trova l'utensile + ( e' il punto finale del percoso di svuotatura allo step attuale) + vtN -> versore direzione del tool + bAtLeft -> flag per indicare se il percorso è invertito o meno + vtStart -> versore direzione iniziale del successivo percorso di svuotatura + ( questo versore viene modificato per il collegamento in tangenza ) + ptDest -> punto tangente all'elica + */ + + switch ( GetLeadInType()) + { + case POCKET_LI_HELIX : { + // raggio dell'elica + double dRad = min( 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam), m_dMaxHelixRad) ; + if ( dRad < - EPS_SMALL) + return false ; + // porto tutto nel piano XY + Frame3d frXY ; frXY.Set( ptCurr, vtN) ; + // ricavo il centro dell'elica + Vector3d vtCen = vtStart ; + vtCen.Rotate( vtN, 0, ( bAtLeft ? 1 : - 1)) ; + Point3d ptCen = ptDest + vtCen * dRad ; + // porto il centro nel frame locale e traslo allo step corrente + ptCen.ToLoc( frXY) ; ptCen.z = 0 ; + // calcolo il vettore diretto verso ptCen + Vector3d vtOC = ptCen - ORIG ; + // lunghezza di tale vettore + double dDist = vtOC.Len() ; + // rendo tale vettore un versore + vtOC.Normalize() ; + // se la distanza è inferiore o uguale al raggio ritorno + if ( dDist < dRad + EPS_SMALL) + return true ; + // lunghezza delle due tangenti + double dLen = sqrt( dDist * dDist - dRad * dRad) ; + if ( dLen < 100 * EPS_SMALL) + return true ; + // ricavo l'angolo in base al triangolo rettangolo creato + double dAngRot = acos( dLen / dDist) * RADTODEG ; + // vettore direzione per tangente destra + Vector3d vtDirR = vtOC ; vtDirR.Rotate( Z_AX, dAngRot) ; + // vettore direzione per tangente sinistra + Vector3d vtDirL = vtOC ; vtDirL.Rotate( Z_AX, - dAngRot) ; + // punto tangenza a destra + Point3d ptTR = ORIG + vtDirL * dLen ; + // punto tangenza a sinistra + Point3d ptTL = ORIG + vtDirR * dLen ; + // devo scegliere il punto che segue in direzione tangente l'arco + ptDest = ptTL ; + if ( bAtLeft) + ptDest = ptTR ; + // aggiorno il nuovo vettore direzione iniziale e il nuovo punto di destinazione + vtStart = ptDest - ORIG ; + vtStart.ToGlob( frXY) ; + vtStart.Normalize() ; + ptDest.ToGlob( frXY) ; + } + break ; + default: + break ; + } + return true ; +} + //---------------------------------------------------------------------------- bool Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFlatRegion* pSfr, @@ -6689,7 +6805,7 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFl Point3d ptEProj = ptE ; ptEProj.ToLoc( frCurr) ; ptEProj.z = 0 ; // Se il punto proiettato coincide con l'ORIG ( ptS) allora ho già finito ( il collegamento non serve) - if ( AreSamePointEpsilon( ORIG, ptEProj, 10 * EPS_SMALL)) + if ( AreSamePointEpsilon( ORIG, ptEProj, 200 * EPS_SMALL)) return true ; // creo un Segmento tra l'ORIG ( ptS) e la proiezione del punto finale @@ -6702,7 +6818,7 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFl // rientranze di contorni chiusi ) -> controllo la superficie limite ( offsettata del raggio del tool) bool bIsAllSecure = ! pSfrLimit->IsValid() ; CRVCVECTOR ccClass ; - PtrOwner pSfrDanger( pSfrLimit->CreateOffsetSurf( 0.5 * m_TParams.m_dDiam - 5 * EPS_SMALL, + PtrOwner pSfrDanger( pSfrLimit->CreateOffsetSurf( 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL, ICurve::OFF_FILLET)) ; if ( ! bIsAllSecure && ( IsNull( pSfrDanger) || ! pSfrDanger->IsValid() || ! pSfrDanger->ToLoc( frCurr) || @@ -6723,13 +6839,10 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFl // 1) ricavo i bisettori dell'Offset interno del raggio della regione da svuotare ( ed eventuale offset radiale) // ( I Bisettori sono quindi accorciati presso i loro estremi ) ICURVEPOVECTOR vCrvBisectors ; - PtrOwner pSfrSafe( pSfr->CreateOffsetSurf( - 0.5 * m_TParams.m_dDiam - GetOffsR() - 5 * EPS_SMALL, + PtrOwner pSfrSafe( pSfr->CreateOffsetSurf( - 0.5 * m_TParams.m_dDiam - GetOffsR() + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrSafe) || ! pSfrSafe->IsValid()) - return false ; - Voronoi* pVRONI( pSfrSafe->GetVoronoiObject()) ; - if ( pVRONI == nullptr || - ! pVRONI->CalcMedialAxis( vCrvBisectors, Voronoi::WMAT_LEFT) || + if ( IsNull( pSfrSafe) || ! pSfrSafe->IsValid() || + ! pSfrSafe->CalcMedialAxis( vCrvBisectors, Voronoi::WMAT_LEFT) || vCrvBisectors.empty()) return false ; @@ -6745,9 +6858,9 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFl vCrvBisectors.clear() ; // calcolo il percorso ottimale ( Dijkstra) PtrOwner pCrvPath( CreateCurveComposite()) ; - if ( IsNull( pCrvPath) || - ! ChooseBestBisectorPath( vCompoBisChain, ORIG, ptEProj, pCrvPath)) + if ( IsNull( pCrvPath)) return false ; + ChooseBestBisectorPath( vCompoBisChain, ORIG, ptEProj, pCrvPath) ; double dMAxElev = 0. ; @@ -7323,9 +7436,9 @@ Pocketing::AddSpiralOut( ISURFFRPOVECTOR& vSfr, const std::vectorGetCurveCount() == 0) @@ -7514,10 +7627,10 @@ Pocketing::AddSpiralOut( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } + //if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { + // m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + // return false ; + //} } // ... se devo aggiungere l'uscita del percorso precedente e calcolare l'entrata // per il percorso attuale @@ -7541,10 +7654,10 @@ Pocketing::AddSpiralOut( ISURFFRPOVECTOR& vSfr, const std::vectorSetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; - return false ; - } + //if ( ! AddLeadIn( ptAbove, ptStart, vtStart, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { + // m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; + // return false ; + //} } } @@ -7607,8 +7720,9 @@ Pocketing::AddSpiralOut( ISURFFRPOVECTOR& vSfr, const std::vectorAddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSrfAct->Clone()) ; PtrOwner pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) return false ; @@ -7781,8 +7896,9 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt return true ; // cambio il punto iniziale della prima Curva di Offset + Point3d ptRef = ptEndPrec ; ptRef.ToLoc( frPocket) ; Point3d ptNewStart ; - if ( SetBetterPtStartForSubChunks( vOffs[0], pSrfToWork, ptStart, vtMidOut, bMidOut)) + if ( SetBetterPtStartForSubChunks( vOffs[0], pSrfToWork, ptRef, frPocket, ptStart, vtMidOut, bMidOut)) vOffs[0]->GetStartPoint( ptNewStart) ; else return false ; @@ -8003,8 +8119,10 @@ Pocketing::OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double Point3d ptNext ; pL.GetFirstPoint( ptNext) ; vPts.push_back( ptNext) ; - while ( pL.GetNextPoint( ptNext)) - vPts.push_back( ptNext) ; + while ( pL.GetNextPoint( ptNext)) { + vPts.push_back( Media( vPts.back(), ptNext)) ; // inserisco il punto medio + vPts.push_back( ptNext) ; // inserisco il punto successivo + } // per ogni coppia di punti calcolo la distanza massima e minima dal centro del cerchio locale ( ORIG) double dMaxDist = 0. ; @@ -10187,9 +10305,10 @@ Pocketing::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, con //---------------------------------------------------------------------------- bool -Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - ISurfFlatRegion* pSrfChunk, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, - bool bNoneForced, bool bSkipControl) +Pocketing::AddLeadIn( const ICurveComposite* pCrvCompo, const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, + const Vector3d& vtEnd, const Vector3d& vtN, ISurfFlatRegion* pSrfChunk, + const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, bool bNoneForced, + bool bSkipControl) { // Assegno il tipo int nType = GetLeadInType() ; @@ -10206,7 +10325,11 @@ Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3 double dRad = min( 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam), m_dMaxHelixRad) ; Point3d ptCen = ptP1 + vtCen * dRad ; double dDeltaN = ( ptStart - ptP1) * vtN ; - double dAngCen = ceil( - dDeltaN / ( m_Params.m_dLiElev + 20 * EPS_SMALL)) * ( bAtLeft ? ANG_FULL : - ANG_FULL) ; + double dExtraAng = 0. ; + if ( vtEnd.IsValid()) + vtEnd.GetAngle( vtStart, dExtraAng) ; + double dAngCen = ( bAtLeft ? dExtraAng : - dExtraAng) + + ceil( - dDeltaN / ( m_Params.m_dLiElev + 20 * EPS_SMALL)) * ( bAtLeft ? ANG_FULL : - ANG_FULL) ; // verifico se fattibile if ( bSkipControl || VerifyLeadInHelix( pSrfChunk, ptCen, dRad)) { // creo l'elica @@ -10231,23 +10354,105 @@ Pocketing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3 } // Se zigzag e fattibile lo creo if ( nType == POCKET_LI_ZIGZAG) { + // dati dello zigzag double dDeltaN = ( ptStart - ptP1) * vtN ; int nStep = int( ceil( - dDeltaN / ( m_Params.m_dLiElev + 20 * EPS_SMALL))) ; double dStep = - dDeltaN / nStep ; - Point3d ptPa = ptP1 + vtStart * 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam) ; - Point3d ptPb = ptP1 - vtStart * 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam) ; - // verifico se fattibile - if ( bSkipControl || VerifyLeadInZigZag( pSrfChunk, ptPa, ptPb)) { - for ( int i = 1 ; i <= nStep ; ++ i) { - if ( AddLinearMove( ptPa - vtN * ( i - 0.75) * dStep, MCH_CL_LEADIN) == GDB_ID_NULL) - return false ; - if ( AddLinearMove( ptPb - vtN * ( i - 0.25) * dStep, MCH_CL_LEADIN) == GDB_ID_NULL) - return false ; - } - return ( AddLinearMove( ptStart, MCH_CL_LEADIN) != GDB_ID_NULL) ; + + // ricavo la curva di primo Offset dal percorso + PtrOwner pCrvCompoFirstOffs( CreateCurveComposite()) ; + if ( IsNull( pCrvCompoFirstOffs)) + return false ; + for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u) { + Point3d ptEnd ; pCrvCompo->GetCurve( u)->GetEndPoint( ptEnd) ; + pCrvCompoFirstOffs->AddCurve( pCrvCompo->GetCurve( u)->Clone()) ; + if ( AreSamePointApprox( ptEnd, ptStart)) + break ; + } + // per sicurezza... + pCrvCompoFirstOffs->Close() ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvCompoFirstOffs->Clone()) ; + IGeoPoint3d* ptSSSS( CreateGeoPoint3d()) ; ptSSSS->Set( ptStart) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, ptSSSS->Clone()) ; + // la traslo della quantità richiesta ( il percorso a ZigZag incomincia sopra al piano di pocketing) + pCrvCompoFirstOffs->Translate( - vtN * dDeltaN) ; + double dLen, dUA, dUB ; + if ( pCrvCompoFirstOffs->GetParamAtLength( 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam), dUA) && + pCrvCompoFirstOffs->GetLength( dLen) && + pCrvCompoFirstOffs->GetParamAtLength( dLen - 0.5 * ( m_Params.m_dLiTang, m_TParams.m_dDiam), dUB)) + { + // recupero le due sottocurve per definire il percorso a ZigZag + PtrOwner pCrvA( pCrvCompoFirstOffs->CopyParamRange( 0., dUA)) ; + PtrOwner pCrvB( pCrvCompoFirstOffs->CopyParamRange( dUB, pCrvCompoFirstOffs->GetCurveCount())) ; + if ( IsNull( pCrvA) || IsNull( pCrvB) || ! pCrvA->IsValid() || ! pCrvB->IsValid()) + return false ; + + // inverto la curva sinistra + pCrvB->Invert() ; + int A = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvA->Clone()) ; + m_pGeomDB->SetMaterial( A, RED) ; + int B = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvB->Clone()) ; + m_pGeomDB->SetMaterial( B, BLUE) ; + + // traslo MAX_NUM_PT punti della curva lungo -vtN e creo quindi le curve per lo ZigZag + const int MAX_NUM_PT = 100 ; + PtrOwner pCrvA_ZigZag( CreateCurveComposite()) ; + PtrOwner pCrvB_ZigZag( CreateCurveComposite()) ; + PtrOwner pCrvA_ZigZag_I( CreateCurveComposite()) ; + PtrOwner pCrvB_ZigZag_I( CreateCurveComposite()) ; + if ( IsNull( pCrvA_ZigZag) || IsNull( pCrvB_ZigZag) || + IsNull( pCrvA_ZigZag_I) || IsNull( pCrvB_ZigZag_I)) + return false ; + + Point3d ptS ; pCrvA->GetStartPoint( ptS) ; + pCrvA_ZigZag->AddPoint( ptS) ; + pCrvB_ZigZag->AddPoint( ptS) ; + ptS.Translate( - vtN * 0.5 * dStep) ; + pCrvA_ZigZag_I->AddPoint( ptS) ; + pCrvB_ZigZag->AddPoint( ptS) ; + ptS.Translate( - vtN * 0.5 * dStep) ; + pCrvB_ZigZag_I->AddPoint( ptS) ; + + double dLenRef = 0.5 * min( m_Params.m_dLiTang, m_TParams.m_dDiam) ; + PNTVECTOR vPtA ; PNTVECTOR vPtB ; + for ( int j = 1 ; j <= MAX_NUM_PT ; ++ j) { + double dParA ; pCrvA->GetParamAtLength( j * ( dLenRef / MAX_NUM_PT), dParA) ; + Point3d ptA ; pCrvA->GetPointD1D2( dParA, ICurve::FROM_MINUS, ptA) ; + Point3d ptA_z = ptA ; ptA_z.Translate( - vtN * j * ( 0.25 * dStep / MAX_NUM_PT)) ; + pCrvA_ZigZag->AddLine( ptA_z) ; + Point3d ptA_z_I = ptA ; ptA_z_I.Translate( - vtN * ( 0.25 * dStep) * ( 2.0 - ( 1. * j) / MAX_NUM_PT)) ; + pCrvA_ZigZag_I->AddLine( ptA_z_I) ; + double dParB ; pCrvB->GetParamAtLength( j * ( dLenRef / MAX_NUM_PT), dParB) ; + Point3d ptB ; pCrvB->GetPointD1D2( dParB, ICurve::FROM_MINUS, ptB) ; + Point3d ptB_z = ptB ; ptB_z.Translate( - vtN * ( 0.25 * dStep) * ( 2.0 + ( 1. * j) / MAX_NUM_PT)) ; + pCrvB_ZigZag->AddLine( ptB_z) ; + Point3d ptB_z_I = ptB ; ptB_z_I.Translate( - vtN * ( 0.25 * dStep) * ( 4 - ( 1. * j) / MAX_NUM_PT)) ; + pCrvB_ZigZag_I->AddLine( ptB_z_I) ; + } + + // abbellisco le curve + pCrvA_ZigZag->MergeCurves( 500 * EPS_SMALL, 500 * EPS_ANG_SMALL) ; + pCrvA_ZigZag_I->MergeCurves( 500 * EPS_SMALL, 500 * EPS_ANG_SMALL) ; + pCrvA_ZigZag_I->Invert() ; + pCrvB_ZigZag->MergeCurves( 500 * EPS_SMALL, 500 * EPS_ANG_SMALL) ; + pCrvB_ZigZag_I->MergeCurves( 500 * EPS_SMALL, 500 * EPS_ANG_SMALL) ; + pCrvB_ZigZag_I->Invert() ; + + // per ogni step copio le curve + for ( int i = 1 ; i <= nStep ; ++ i) { + if ( AddCurveMove( pCrvA_ZigZag, MCH_CL_LEADIN) == GDB_ID_NULL || + AddCurveMove( pCrvA_ZigZag_I, MCH_CL_LEADIN) == GDB_ID_NULL || + AddCurveMove( pCrvB_ZigZag, MCH_CL_LEADIN) == GDB_ID_NULL || + AddCurveMove( pCrvB_ZigZag_I, MCH_CL_LEADIN) == GDB_ID_NULL) + return false ; + pCrvA_ZigZag->Translate( - vtN * dStep) ; + pCrvA_ZigZag_I->Translate( - vtN * dStep) ; + pCrvB_ZigZag->Translate( - vtN * dStep) ; + pCrvB_ZigZag_I->Translate( - vtN * dStep) ; + } + return true ; } - // altrimenti diretto else { nType = POCKET_LI_NONE ; if ( m_TParams.m_nType == TT_MILL_NOTIP) @@ -10409,7 +10614,7 @@ Pocketing::GetRadiusForStartEndElevation( void) const //---------------------------------------------------------------------------- bool Pocketing::GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOtherCrv, - Point3d& ptMid, Vector3d& vtMidOrt) + const Frame3d& frPocket, Point3d& ptMid, Vector3d& vtMidOrt) { // recupero il vettore estrusione Vector3d vtExtr = Z_AX ; @@ -10424,6 +10629,14 @@ Pocketing::GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOV } pMyCrv = pCompo->GetNextCurve() ; } + // salvo il punto iniziale e la direzione d'uscita del primo lato aperto valido che trovo + // NB. Il primo valido non significa il migliore, potrebbe infatti essere il lato aperto più lungo + // ma essere all'interno del grezzo... cerco di dare priorità ai lati sul grezzo + + // flag per la presenza di un primo lato aperto valido per entrare + bool bFirstOpenValid = false ; + Point3d ptFirstOpenValid = P_INVALID ; + Vector3d vtFirstOpenValid = V_INVALID ; // richiedo lunghezza superiore a diametro utensile più doppio offset radiale double dRefLen = ( bAllOpen ? 0 : m_TParams.m_dDiam + 2 * GetOffsR() - EPS_SMALL) ; double dMaxLen = dRefLen ; @@ -10469,9 +10682,9 @@ Pocketing::GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOV if ( bFound && dLen + dLenAgg > dRefLen && abs( dLen + dLenAgg - dMaxLen) < LEN_TOL) { Point3d ptTest ; pCrv->GetMidPoint( ptTest) ; - if (( m_bAboveHead && ptTest.z > ptMid.z + 100 * EPS_SMALL) || - ( ! m_bAboveHead && ptTest.z < ptMid.z - 100 * EPS_SMALL) || - ( abs( ptTest.z - ptMid.z) < 100 * EPS_SMALL && ptTest.y < ptMid.y - 100 * EPS_SMALL)) { + if (( m_bAboveHead && ptTest.z > ptMid.z + 100 * EPS_SMALL) || + ( ! m_bAboveHead && ptTest.z < ptMid.z - 100 * EPS_SMALL) || + ( abs( ptTest.z - ptMid.z) < 100 * EPS_SMALL && ptTest.y < ptMid.y - 100 * EPS_SMALL)) { dMaxLen = max( dMaxLen, dLen + dLenAgg) ; ptMid = ptTest ; // vettore ortogonale verso l'esterno (ruotato -90deg attorno a estrusione) @@ -10479,24 +10692,50 @@ Pocketing::GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOV vtMidOrt.Rotate( vtExtr, 0, -1) ; } } - // se più lunga ( o non già trovata ) + // se più lunga ( o non già trovata) else if ( dLen + dLenAgg > dMaxLen || !bFound) { dMaxLen = dLen + dLenAgg ; double dParIn ; - // cerco il parametro di tale curva (0 < dParIn < 1) migliore per entrata + // cerco il parametro di tale curva (0 < dParIn < 1) migliore per l'entrata if ( GetParamForPtStartOnEdge( pCrv, pCompo, vOtherCrv, dParIn)) { pCrv->GetPointD1D2( dParIn, ICurve::FROM_PLUS, ptMid) ; PtrOwner pCompoClone( CloneCurveComposite( pCompo)) ; - if( IsNull( pCompoClone)) + if ( IsNull( pCompoClone)) return false ; double dU ; pCompoClone->GetParamAtPoint( ptMid, dU) ; pCompoClone->ChangeStartPoint( dU) ; pCompoClone->GetStartDir( vtMidOrt) ; vtMidOrt.Rotate( vtExtr, 0, -1) ; - bFound = true ; - if ( nPriorityOpenEdge == 0) - return true ; + // salvo l'indice di questo lato aperto se si tratta del primo valido + if ( ! bFirstOpenValid) { + bFirstOpenValid = true ; + ptFirstOpenValid = ptMid ; + vtFirstOpenValid = vtMidOrt ; + } + // controllo se questa quantità è effettivamente fuori dal grezzo + // ( privilegio i lati aperti che sono effettivamente sul bordo del grezzo) + // punto iniziale nel sistema di riferimento globale + Point3d ptStart ; pCompoClone->GetStartPoint( ptStart) ; + ptStart.ToGlob( frPocket) ; + // vettore d'uscita nel sistema di riferimento globale + Vector3d vtMidOut = vtMidOrt ; + vtMidOut.ToGlob( frPocket) ; + // ricavo la SafeZ + double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; + Point3d ptOut = ptStart + vtMidOut * ( 0.5 * m_TParams.m_dDiam + GetOffsR() + + ( 0.5 * m_TParams.m_dDiam + max( dSafeZ, m_dOpenMinSafe))) ; + // controllo l'elevazione sopra a quel punto + double dElev = 0. ; + if ( ! GetElevation( m_nPhase, ptOut, frPocket.VersZ(), m_TParams.m_dDiam, m_TParams.m_dLen, + frPocket.VersZ(), dElev)) + return false ; + // se non vi è elevazione, il lato aperto trovato è il privilegiato + if ( dElev < EPS_SMALL) { + bFound = true ; + if ( nPriorityOpenEdge > -1) + return true ; + } } } dLenPrev = dLen ; @@ -10509,6 +10748,14 @@ Pocketing::GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOV pCrv = ( bNextOk ? pNextCrv : nullptr) ; } + // se non ho trovato un lato aperto valido fuori dal grezzo, ma ho trovato un lato aperto + // generico accettabile + if ( ! bFound && bFirstOpenValid) { + ptMid = ptFirstOpenValid ; + vtMidOrt = vtFirstOpenValid ; + bFound = true ; + } + return bFound ; } @@ -10836,7 +11083,8 @@ Pocketing::CreateSurfFrIncidence( const ICurveComposite* pCrv, const double dRad //---------------------------------------------------------------------------- bool -Pocketing::AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, bool bOrder) +Pocketing::AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, bool bOrder, + Point3d ptRef) { // se cerco semplicemente il tratto lineare chiuso più lungo ... if ( ! bOrder) { @@ -10894,6 +11142,31 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& // un'entrata sufficientemente distante da isole e da altre curve della curva stessa su cui cerco l'entrata ... else { + // se ho un punto di riferimento, allora come prima cosa controllo il lato chiuso più vicino + if ( ptRef.IsValid()) { + double dMinDist = INFINITO ; + int nIndCrvMinDist = - 1 ; + for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) { + DistPointCurve DPC( ptRef, *pCompo->GetCurve( u)) ; + double dCurrDist = INFINITO ; + if ( DPC.GetDist( dCurrDist) && dCurrDist < dMinDist) { + nIndCrvMinDist = u ; + dMinDist = dCurrDist ; + } + } + // se avessi curve alla stessa distanza ( circa) non controllo le altre, mi accontento della + // prima curva trovata + if ( nIndCrvMinDist != -1) { + // controllo che il lato chiuso sia sufficientemente lungo + double dLen = 0. ; + pCompo->GetCurve( nIndCrvMinDist)->GetLength( dLen) ; + if ( dLen > m_TParams.m_dDiam + 2 * GetOffsR() + 500 * EPS_SMALL) { + pCompo->ChangeStartPoint( nIndCrvMinDist + 0.5) ; + return true ; + } + } + } + // creo un vettore di indici che definisce l'ordine delle curve chiuse in base alla lunghezza INTVECTOR vInd ; vInd.reserve( pCompo->GetCurveCount()) ; @@ -10929,9 +11202,9 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& dMaxLen = -INFINITO ; } - if (( int)vInd.size() == 0) { + if ( vInd.empty()) { // se questa condizione fosse vera allora non sono riuscito ad entrare da nessun lato aperto in precedenza e non - // ho nemmeno un lato chiuso disponibile per entrare... + // ho nemmeno un lato chiuso disponibile per entrare... ( forzo l'entrata a metà del primo lato) pCompo->ChangeStartPoint( 0.5) ; return true ; } @@ -10948,8 +11221,8 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& } if ( ! bOk) { - // se non riesco ad entrare da nessun lato chiuso, considerando che in precedenza ho già provato ad - // entrare da tutti i lati aperti... + // se non riesco ad entrare da nessun lato chiuso, considerando che in precedenza ho già provato ad + // entrare da tutti i lati aperti... pCompo->ChangeStartPoint( vInd[0] + 0.5) ; return true ; } @@ -11133,6 +11406,7 @@ Pocketing::ProjectStmOnPlane( const ISurfTriMesh* pStmAbove, const Plane3d plPoc if ( ! GetSfrByStm( pStmDown, pSfrUp1, plPock, V_NULL, 0., 0.)) return false ; + // 7) Controllo validità e creo la FlatRegion da restituire if ( ! IsNull( pSfrUp) && pSfrUp->IsValid()) { // se Up valida, allora inizio a sostituire if ( AreOppositeVectorApprox( pSfrUp->GetNormVersor(), plPock.GetVersN())) @@ -11420,7 +11694,7 @@ Pocketing::GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) //---------------------------------------------------------------------------- bool Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISurfFlatRegion* pSrfToWork, - Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) + const Point3d& ptEndPrec, const Frame3d& frPocket, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) { // ============================= INFO ============================================================== // pCrvOffsAct -> Curva di Offset su cui cercare ptStart, vtMidOut, bMidOpen @@ -11430,7 +11704,7 @@ Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISu // controllo dei parametri if ( pCrvOffsAct == nullptr || ! pCrvOffsAct->IsValid() || pCrvOffsAct->GetCurveCount() == 0 || - pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) + pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) return false ; // clono le curva su cui devo entrare @@ -11449,8 +11723,8 @@ Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISu // hanno generato delle curve sulla pCrv ( curva da cui devo entrare ) INTVECTOR vIndex ; - // scorro tutte le curve presenti in pCrv ( curva da cui devo entrare ) - for ( int i = 0 ; i < ( int)pCrv->GetCurveCount() ; ++ i) { + // scorro tutte le curve presenti in pCrv ( curva da cui devo entrare) + for ( int i = 0 ; i < pCrv->GetCurveCount() ; ++ i) { // nProp0 -> #curva il cui Offset ha generato la curva i-esima di pCrv int nProp0 ; pCrv->GetCurveTempProp( i, nProp0, 0) ; @@ -11460,7 +11734,7 @@ Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISu if ( nProp0 > 0) { // se questa curva non è un "raccordo" di Offset // controllo per maggiore sicurezza che effettivamente nProp1 sia un indice valido per il vettore dei Loops e // che nProp0 non sia maggiore del numero di curve del loop nProp1-esimo del vettore dei Loops della pSrfToWork - if ( nProp1 >= 0 && nProp1 < ( int)vCrvLoops.size() && nProp0 < vCrvLoops[nProp1]->GetCurveCount()) { + if ( nProp1 >= 0 && nProp1 < int( vCrvLoops.size()) && nProp0 < vCrvLoops[nProp1]->GetCurveCount()) { // aggiorno il vettore di indici ... if ( find( vIndex.begin(), vIndex.end(), nProp1) == vIndex.end()) vIndex.push_back( nProp1) ; @@ -11475,31 +11749,52 @@ Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISu pCrv->SetCurveTempProp( i, 0, 0) ; } else - pCrv->SetCurveTempProp( i, 1, 0) ; // <- tmp prop = 0 + pCrv->SetCurveTempProp( i, 1, 0) ; } - // cambio il punto iniziale della curva all'inizio del lato aperto più lungo ( se presente) + // se ho dei lati aperti... double dLenMax = EPS_SMALL ; int nCrvForMax = 0 ; if ( bSomeOpen) { - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { - int nTmpProp = 0 ; - double dLenAct = EPS_SMALL ; - if ( pCrv->GetCurveTempProp( u, nTmpProp, 0) && nTmpProp == 1 && - pCrv->GetCurve( u)->GetLength( dLenAct) && dLenAct > dLenMax) { - dLenMax = dLenAct ; - nCrvForMax = u ; + // ... e sono al primo Step, cerco la curva Aperta più lunga ( scelgo la prima che trovo) ... + if ( ! ptEndPrec.IsValid()) { + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + int nTmpProp = 0 ; + double dLenAct = EPS_SMALL ; + if ( pCrv->GetCurveTempProp( u, nTmpProp, 0) && nTmpProp == 1 && + pCrv->GetCurve( u)->GetLength( dLenAct) && dLenAct > dLenMax) { + dLenMax = dLenAct ; + nCrvForMax = u ; + } } + // il punto iniziale della curva sarà il punto iniziale della sottocurva trovata + pCrv->ChangeStartPoint( nCrvForMax) ; + } + // ... se invece non sono al primo Step, cerco la prima curva aperta più vicina al punto finale + else { + int nIndClosesOpenCrv = -1 ; + double dMinDist = INFINITO ; + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + if ( pCrv->GetCurve( u)->GetTempProp( 0) == 1) { + DistPointCurve DPC( ptEndPrec, *pCrv->GetCurve( u)) ; + double dCurrDist = INFINITO ; + if ( DPC.GetDist( dCurrDist) && dCurrDist < dMinDist) { + dMinDist = dCurrDist ; + nIndClosesOpenCrv = u ; + } + } + } + // il punto iniziale della curva sarà il punto iniziale della sottocurva trovata + pCrv->ChangeStartPoint( nIndClosesOpenCrv) ; } - pCrv->ChangeStartPoint( nCrvForMax) ; } // creo un vettore con tutti i Loops della pSwfToWork per i quali, mediante l'Offset, non hanno // generato alcuna curva presente nella pCrv ( quella da cui devo entrare) ICRVCOMPOPOVECTOR vOtherCrv ; - for ( int i = 0 ; i < ( int)vCrvLoops.size() ; ++ i) { + for ( int i = 0 ; i < int( vCrvLoops.size()) ; ++ i) { bool bOk = true ; - for ( int j = 0 ; j < ( int)vIndex.size() && bOk ; ++ j) { + for ( int j = 0 ; j < int( vIndex.size()) && bOk ; ++ j) { if ( i == vIndex[j]) bOk = false ; } @@ -11509,16 +11804,22 @@ Pocketing::SetBetterPtStartForSubChunks( ICurveComposite* pCrvOffsAct, const ISu // cerchiamo un punto valido per l'entrata ... bMidOut = false ; - if ( bSomeOpen) // se ho dei lati aperti, cerco il più lungo - bMidOut = GetParamOnOpenSide( pCrv, vOtherCrv, ptStart, vtMidOut) ; + if ( bSomeOpen) // se ho dei lati aperti, cerco un parametro ideale per entrare + bMidOut = GetParamOnOpenSide( pCrv, vOtherCrv, frPocket, ptStart, vtMidOut) ; if ( bMidOut) { // se ho trovato e valido, allora imposto il punto inziale trovato + if ( ptEndPrec.IsValid()) { + IGeoPoint3d* ptE( CreateGeoPoint3d()) ; ptE->Set( ptEndPrec) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, ptE->Clone()) ; + } + int b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrv->Clone()) ; + m_pGeomDB->SetMaterial( b, BLUE) ; const double LEN_OUT = 5 ; double dPar ; int nFlag ; bMidOut = ( DistPointCurve( ptStart + LEN_OUT * vtMidOut, *pCrv).GetParamAtMinDistPoint( 0, dPar, nFlag) && pCrv->ChangeStartPoint( dPar)) ; } if ( ! bMidOut) // alla peggio, ordino i lati lunghi per lunghezza e cerco un'entrata valida - AdjustContourStart( pCrv, vOtherCrv, true) ; + AdjustContourStart( pCrv, vOtherCrv, true, ptEndPrec) ; // ora che ho deciso quale sia il punto iniziale, lo imposto effettivamente sulla curva di Offset passata alla funzione double dUS ; @@ -11708,7 +12009,15 @@ Pocketing::GetSfrByStm( const ISurfTriMesh* pStm, ISurfFlatRegion* pSfr, const P continue ; } - SrfChunkDef.AddCurve( Release( pCrv_proj)) ; // aggiungo le curve proiettate + // per sicurezza cambio il suo punto iniziale a metà del lato più lungo + ICRVCOMPOPOVECTOR VNULL ; + PtrOwner pCrv_projCompo( ConvertCurveToComposite( pCrv_proj->Clone())) ; + if ( IsNull( pCrv_projCompo)) + return false ; + for ( int u = 0 ; u < pCrv_projCompo->GetCurveCount() ; ++ u) + pCrv_projCompo->SetCurveTempProp( u, 0, 0) ; + AdjustContourStart( pCrv_projCompo, VNULL) ; + SrfChunkDef.AddCurve( Release( pCrv_projCompo)) ; // aggiungo le curve proiettate } // recupero la FlatRegion @@ -11844,7 +12153,7 @@ Pocketing::GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveCompos return false ; // diametro reale da tenere in considerazione - double dDiam = m_TParams.m_dDiam + GetOffsR() ; + double dDiam = m_TParams.m_dDiam + 2 * GetOffsR() ; pCrvTrap->Clear() ; // resterà vuota se il caso non è ottimizzato nBase = -1 ; @@ -11901,192 +12210,321 @@ Pocketing::GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveCompos for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u) { int nTmpProp ; if ( pCrvCompo->GetCurveTempProp( u, nTmpProp, 0) && nTmpProp == 0) { - ++nClosedSide ; + ++ nClosedSide ; vIndClosedSides.push_back( u) ; } } - // clono la curva Compo - PtrOwner pCrvCompo_c( CloneCurveComposite( pCrvCompo)) ; - if ( IsNull( pCrvCompo_c)) - return false ; - - // tolleranza - const double TOLL = 50 * EPS_SMALL ; - // se tutti lati aperti - if ( nClosedSide == 0) { - // ricavo il box minimo della curva aperta ( passo dalla polyLine) - PolyLine PL ; Point3d ptCen ; double dWidth ; - if ( ! pCrvCompo->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || - ! PL.GetMinAreaRectangleXY( ptCen, vtDir, dWidth, dPocketSize)) + switch ( nClosedSide) { + // TUTTI I LATI SONO APERTI + case 0 : { + // ricavo il box minimo della curva aperta ( passo dalla polyLine) + PolyLine PL ; Point3d ptCen ; double dWidth ; + if ( ! pCrvCompo->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || + ! PL.GetMinAreaRectangleXY( ptCen, vtDir, dWidth, dPocketSize)) return false ; - // controllo dimY ( dHeight), se troppo estesa, non è un caso ottimizzato - if ( dPocketSize > dDiam + TOLL) - return true ; - // inverto il frame attuale - frTrap.Set( ptCen, Z_AX, vtDir) ; - if ( ! frTrap.IsValid()) - return false ; - // creo il rettangolo del Box - pCrvTrap->AddPoint( Point3d( - 0.5 * dWidth, - 0.5 * dPocketSize, 0)) ; - pCrvTrap->AddLine( Point3d( 0.5 * dWidth, - 0.5 * dPocketSize, 0)) ; - pCrvTrap->AddLine( Point3d( 0.5 * dWidth, 0.5 * dPocketSize, 0)) ; - pCrvTrap->AddLine( Point3d( - 0.5 * dWidth, 0.5 * dPocketSize, 0)) ; - pCrvTrap->Close() ; - pCrvTrap->ToGlob( frTrap) ; - Point3d ptNewOrig ; pCrvTrap->GetStartPoint( ptNewOrig) ; - frTrap.Set( ptNewOrig, Z_AX, vtDir) ; - // imposto tutte le 4 curve come aperte - for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) - pCrvTrap->SetCurveTempProp( u, 1, 0) ; - // imposto le basi - nBase = 0 ; - nSecondBase = 2 ; - } - // se un lato chiuso - else if ( nClosedSide == 1) { - // prendo l'unica curva chiusa - const ICurve* pCrvCurr = pCrvCompo->GetCurve( vIndClosedSides[0]) ; - if ( pCrvCurr == nullptr) - return false ; - // controllo se lineare ( altrimenti non è ottimizzato) - if ( pCrvCurr->GetType() != CRV_LINE) - return true ; - // prendo la direzione del tratto lineare - pCrvCurr->GetStartDir( vtDir) ; - // prendo il punto iniziale - Point3d ptStart ; pCrvCurr->GetStartPoint( ptStart) ; - // creo il riferimento basato su questo tratto - frTrap.Set( ptStart, Z_AX, vtDir) ; - if ( ! frTrap.IsValid()) - return false ; - // porto la curva Compo ( clonandola) nel frame - pCrvCompo_c->ToLoc( frTrap) ; - // ricavo il box complessivo in questo frame - BBox3d BBox ; - pCrvCompo_c->GetLocalBBox( BBox) ; - // controllo dimY ( se troppo grande o lato chiuso non sul bordo del box => caso non ottimizzato) - if (( BBox.GetDimY() < dDiam + TOLL || BBox.GetDimX() < dDiam + TOLL) && BBox.GetMin().y > - TOLL) { + // controllo dimY ( dHeight), se troppo estesa, non è un caso ottimizzato + if ( dPocketSize > dDiam + TOLL_TRAPEZOID) + return true ; + // inverto il frame attuale + frTrap.Set( ptCen, Z_AX, vtDir) ; + if ( ! frTrap.IsValid()) + return false ; // creo il rettangolo del Box - pCrvTrap->AddPoint( BBox.GetMin()) ; - pCrvTrap->AddLine( BBox.GetMin() + BBox.GetDimX() * X_AX) ; - pCrvTrap->AddLine( BBox.GetMax()) ; - pCrvTrap->AddLine( BBox.GetMax() - BBox.GetDimX() * X_AX) ; + pCrvTrap->AddPoint( Point3d( - 0.5 * dWidth, - 0.5 * dPocketSize, 0)) ; + pCrvTrap->AddLine( Point3d( 0.5 * dWidth, - 0.5 * dPocketSize, 0)) ; + pCrvTrap->AddLine( Point3d( 0.5 * dWidth, 0.5 * dPocketSize, 0)) ; + pCrvTrap->AddLine( Point3d( - 0.5 * dWidth, 0.5 * dPocketSize, 0)) ; pCrvTrap->Close() ; - // porto in globale pCrvTrap->ToGlob( frTrap) ; - // imposto tutte le curve come aperte tranne la prima ( estendo il solo lato chiuso come base del Box) + Point3d ptNewOrig ; pCrvTrap->GetStartPoint( ptNewOrig) ; + frTrap.Set( ptNewOrig, Z_AX, vtDir) ; + // imposto tutte le 4 curve come aperte for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) - pCrvTrap->SetCurveTempProp( u, u == 0 ? 0 : 1, 0) ; - - // memorizzo la dimensione Y - dPocketSize = BBox.GetDimY() ; - - // se il lato chiuso non può essere la base, allora sarà l'aperto ( del box) - if ( BBox.GetDimY() > dDiam + TOLL) { - dPocketSize = BBox.GetDimX() ; - pCrvTrap->ChangeStartPoint( 1.) ; - Point3d ptORIG ; pCrvTrap->GetStartPoint( ptORIG) ; - pCrvTrap->GetStartDir( vtDir) ; - frTrap.Set( ptORIG, Z_AX, vtDir) ; + pCrvTrap->SetCurveTempProp( u, 1, 0) ; + // imposto le basi + nBase = 0 ; + nSecondBase = 2 ; + } + // 1 LATO CHIUSO ( LINEARE) + case 1 : { + int nType = -1 ; + if ( ! GetBoxCrvOptTrap( vIndClosedSides[0], pCrvCompo, dDiam, nType, pCrvTrap)) + return false ; + if ( nType != -1) { + // imposto tutte le curve come aperte tranne la prima ( estendo il solo lato chiuso come base del Box) + for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) + pCrvTrap->SetCurveTempProp( u, u == 0 ? 0 : 1, 0) ; + // memorizzo la dimensione di svuotatura + pCrvTrap->GetCurve( 1)->GetLength( dPocketSize) ; + // imposto le basi + nBase = 0 ; + nSecondBase = 2 ; } } - - // imposto le basi - nBase = 0 ; - nSecondBase = 2 ; - } - else { - // cerco la base - // Def di base : - // lato lineare chiuso, box nella sua direzione con DimY < 1.5 dDiam, box dei restanti chiusi ( almeno 1) - // con dimY < dDiam e lato lineare come lato del box ( è possibile trovare una seconda base, come altro lato chiuso - // parallelo alla base principale con distanza da essa circa il dDiam) - - bool bBaseFound = false ; // flag per individuare base principale - BBox3d BBox ; // Box per base principale - // scorro i chiusi alla ricerca di una possibile base principale - for ( int i = 0 ; i < pCrvCompo->GetCurveCount() && ! bBaseFound ; ++ i) { - nBase = i ; // aggiorno l'indice - // prendo la curva - const ICurve* pCrvCurr = pCrvCompo->GetCurve( i) ; - if ( pCrvCurr == nullptr) - return false ; - // controllo se lineare, altrimenti passo alla successiva - if ( pCrvCurr->GetType() != CRV_LINE) - continue ; - // prendo la direzione del tratto lineare - pCrvCurr->GetStartDir( vtDir) ; - // prendo il punto iniziale - Point3d ptStart ; pCrvCurr->GetStartPoint( ptStart) ; - // creo il riferimento basato su questo tratto - frTrap.Set( ptStart, Z_AX, vtDir) ; - if ( ! frTrap.IsValid()) - return false ; - // porto la curva Compo ( clonandola) nel frame - pCrvCompo_c.Set( pCrvCompo->Clone()) ; - pCrvCompo_c->ToLoc( frTrap) ; - // calcolo il box - pCrvCompo_c->GetLocalBBox( BBox) ; - // controllo dimY e dimX per il box - bool bDimYOk = BBox.GetDimY() < dDiam + TOLL && BBox.GetMin().y > - TOLL ; - bool bDimXOk = BBox.GetDimX() < dDiam + TOLL && BBox.GetMin().y > - TOLL ; - // se entrambe le dimensioni superano il diametro, questo lato non è la base, cerco il successivo - if ( !bDimXOk && !bDimYOk) - continue ; - // se dimY accettabile - if ( bDimYOk) { - bool bOk = false ; - if ( ! CheckTrapezoidClosedEdgePosition( pCrvCompo_c, i, BBox.GetDimY(), vIndClosedSides, bOk, pCrvTrap)) - return false ; - if ( bOk) { - // pCrvTrap contiene il trapezio - nBase = 0 ; - nSecondBase = 2 ; - dPocketSize = BBox.GetDimY() ; - pCrvTrap->ToGlob( frTrap) ; - bBaseFound = true ; - } - else { - // cerco la seconda base - if ( ! CheckSecondBaseTrapezoid( pCrvCompo_c, i, nSecondBase)) + // 2 LATI CHIUSI ( LINEARI, CONSECUTIVI O PARALLELI) + case 2 : { + // controllo se entrambi sono lineari + if ( pCrvCompo->GetCurve( vIndClosedSides[0])->GetType() == CRV_LINE && + pCrvCompo->GetCurve( vIndClosedSides[0])->GetType() == CRV_LINE) { + // se lineari, ricavo i punti estremanti e le direzioni + Point3d ptS0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartPoint( ptS0) ; + Point3d ptS1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetStartPoint( ptS1) ; + Point3d ptE0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetEndPoint( ptE0) ; + Point3d ptE1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetEndPoint( ptE1) ; + Vector3d vtDir0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartDir( vtDir0) ; + Vector3d vtDir1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetStartDir( vtDir1) ; + // CASO PARALLELI ( la base è indifferente) + if ( AreOppositeVectorEpsilon( vtDir0, vtDir1, 5 * EPS_SMALL)) { + int nType = -1 ; + // prendo come base il primo chiuso + if ( ! GetBoxCrvOptTrap( vIndClosedSides[0], pCrvCompo, dDiam, nType, pCrvTrap)) return false ; - if ( nSecondBase != -1) { - // verifico che una delle due sia chiusa ( TO DO) - if ( pCrvCompo_c->GetCurve( nBase)->GetTempProp( 0) == 0 || - pCrvCompo_c->GetCurve( nSecondBase)->GetTempProp( 0) == 0) { - // se ho trovato la seconda base - if ( ! PreparareTrapezoidTwoBases( pCrvCompo_c, BBox, i, nSecondBase, bOk, pCrvTrap)) - return false ; - if ( bOk) { - // pCrvTrap contiene il trapezio - nBase = 0 ; - dPocketSize = BBox.GetDimY() ; - pCrvTrap->ToGlob( frTrap) ; - bBaseFound = true ; + if ( nType != -1) { + // memorizzo la dimensione di svuotatura + pCrvTrap->GetCurve( 1)->GetLength( dPocketSize) ; + // controllo che la distanza tra i due chiusi sia effettivamente circa il raggio + double dDist = 0. ; + DistPointCurve DPL( ptS0, *pCrvCompo->GetCurve( vIndClosedSides[1]), false) ; + if ( DPL.GetDist( dDist) && abs( dDist - dDiam) < TOLL_TRAPEZOID) { + // imposto tutte le curve di indice dispari aperte + for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) + pCrvTrap->SetCurveTempProp( u, u % 2 == 0 ? 0 : 1, 0) ; + // imposto le basi + nBase = 0 ; + nSecondBase = 2 ; + } + else + pCrvTrap->Clear() ; + } + } + // CASO CONSECUTIVI + bool bOk_0_1 = AreSamePointApprox( ptS1, ptE0) ; // chiuso1 . chiuso0 + bool bOk_1_0 = AreSamePointApprox( ptS0, ptE1) ; // chiuso0 . chiuso1 + if ( bOk_0_1 || bOk_1_0) { + // provo con il primo lato + int nType = -1 ; + // prendo come base il primo chiuso + if ( ! GetBoxCrvOptTrap( vIndClosedSides[0], pCrvCompo, dDiam, nType, pCrvTrap)) + return false ; + if ( nType == -1) { + // provo con l'altro + if ( ! GetBoxCrvOptTrap( vIndClosedSides[1], pCrvCompo, dDiam, nType, pCrvTrap)) + return false ; + if ( nType != -1) { + // spaw tra gli indici e flags + swap( vIndClosedSides[0], vIndClosedSides[1]) ; + swap( bOk_0_1, bOk_1_0) ; + } + } + Point3d ptH1, ptH2 ; + if ( nType == 1 || nType == 2) { + double dLen1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetLength( dLen1) ; + pCrvTrap->GetCurve( 1)->GetLength( dPocketSize) ; + // i lati inclinati chiusi definiscono il Box + if ( abs( dLen1 * ( vtDir0 ^ vtDir1).Len() - dPocketSize) < TOLL_TRAPEZOID) { + // creo la curva a trapezio + if ( bOk_0_1) { + pCrvTrap->GetCurve( 2)->GetEndPoint( ptH1) ; + pCrvTrap->GetCurve( 3)->GetEndPoint( ptH2) ; + pCrvTrap->Clear() ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->AddLine( ptH1) ; + pCrvTrap->AddLine( ptH2) ; + pCrvTrap->Close() ; + pCrvTrap->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) + pCrvTrap->SetCurveTempProp( u, u < 2 == 0 ? 0 : 1, 0) ; } + else { + pCrvTrap->GetCurve( 0)->GetEndPoint( ptH1) ; + pCrvTrap->GetCurve( 1)->GetEndPoint( ptH2) ; + pCrvTrap->Clear() ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddLine( ptH1) ; + pCrvTrap->AddLine( ptH2) ; + pCrvTrap->AddLine( ptS1) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + pCrvTrap->SetCurveTempProp( 0, 0, 0) ; + for ( int u = 1 ; u < pCrvTrap->GetCurveCount() -1 ; ++ u) + pCrvTrap->SetCurveTempProp( u, 1, 0) ; + pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() -1, 0, 0) ; + } + // imposto le basi + nBase = 0 ; + nSecondBase = pCrvTrap->GetCurveCount() - 2 ; + } + else + pCrvTrap->Clear() ; + } + else if ( nType == 0) { + if ( bOk_0_1) { + pCrvTrap->GetCurve( 0)->GetEndPoint( ptH1) ; + pCrvTrap->GetCurve( 1)->GetEndPoint( ptH2) ; + pCrvTrap->Clear() ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->AddLine( ptH1) ; + pCrvTrap->AddLine( ptH2) ; + pCrvTrap->Close() ; + pCrvTrap->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + for ( int u = 0 ; u < pCrvTrap->GetCurveCount() ; ++ u) + pCrvTrap->SetCurveTempProp( u, u < 2 == 0 ? 0 : 1, 0) ; + pCrvTrap->ChangeStartPoint( 1.) ; + // imposto le basi + nBase = 0 ; + nSecondBase = pCrvTrap->GetCurveCount() - 2 ; + } + else { + pCrvTrap->GetCurve( 0)->GetEndPoint( ptH1) ; + pCrvTrap->GetCurve( 1)->GetEndPoint( ptH2) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddLine( ptH1) ; + pCrvTrap->AddLine( ptH2) ; + pCrvTrap->AddLine( ptS1) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + pCrvTrap->SetCurveTempProp( 0, 0, 0) ; + for ( int u = 1 ; u < pCrvTrap->GetCurveCount() -1 ; ++ u) + pCrvTrap->SetCurveTempProp( u, 1, 0) ; + pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() -1, 0, 0) ; + pCrvTrap->ChangeStartPoint( 1.) ; + // imposto le basi + nBase = 0 ; + nSecondBase = pCrvTrap->GetCurveCount() - 2 ; } } } } - // se dimX accettabile - if ( bDimYOk) { - // TODO : + } + // 3 LATI CHIUSI ( LINEARI e CONSECUTIVI) + case 3 : { + // prendo i 3 lati chiusi + const ICurve* pCrv0 = pCrvCompo->GetCurve( vIndClosedSides[0]) ; + const ICurve* pCrv1 = pCrvCompo->GetCurve( vIndClosedSides[1]) ; + const ICurve* pCrv2 = pCrvCompo->GetCurve( vIndClosedSides[2]) ; + if ( pCrv0 == nullptr || pCrv1 == nullptr || pCrv2 == nullptr) + return false ; + // controllo che siano lineari + if ( pCrv0->GetType() == CRV_LINE && pCrv1->GetType() == CRV_LINE && pCrv2->GetType() == CRV_LINE) { + // prendo i punti iniziali e finali + Point3d ptStart0 ; pCrv0->GetStartPoint( ptStart0) ; + Point3d ptEnd0 ; pCrv0->GetEndPoint( ptEnd0) ; + Point3d ptStart1 ; pCrv1->GetStartPoint( ptStart1) ; + Point3d ptEnd1 ; pCrv1->GetEndPoint( ptEnd1) ; + Point3d ptStart2 ; pCrv2->GetStartPoint( ptStart2) ; + Point3d ptEnd2 ; pCrv2->GetEndPoint( ptEnd2) ; + + // controllo che siano consecutivi e cambio l'ordine se necessario + bool bOk = true ; + if ( AreSamePointApprox( ptEnd0, ptStart1) && AreSamePointApprox( ptEnd1, ptStart2)) + ; + else if ( AreSamePointApprox( ptEnd1, ptStart2) && AreSamePointApprox( ptEnd2, ptStart0)) { + swap( vIndClosedSides[0], vIndClosedSides[1]) ; + swap( vIndClosedSides[1], vIndClosedSides[2]) ; + } + else if ( AreSamePointApprox( ptEnd2, ptStart0) && AreSamePointApprox( ptEnd0, ptStart1)) { + swap( vIndClosedSides[0], vIndClosedSides[2]) ; + swap( vIndClosedSides[2], vIndClosedSides[1]) ; + } + else // se non consecutivi + bOk = false ; + + // se i tre lati sono ( mediante lo swap) consecutivi... + if ( bOk) { + // controllo se la dimensione Y del lato 1 è valida ( il resto è gestito di seguito) + int nType = -1 ; + if ( ! GetBoxCrvOptTrap( vIndClosedSides[1], pCrvCompo, dDiam, nType, pCrvTrap)) + return false ; + if ( nType == 1) { + // bisgna controllare la lunghezza dei chiusi + double dLen0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetLength( dLen0) ; + double dLen2 ; pCrvCompo->GetCurve( vIndClosedSides[2])->GetLength( dLen2) ; + pCrvTrap->GetCurve( 1)->GetLength( dPocketSize) ; + Vector3d vtDir0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartDir( vtDir0) ; + Vector3d vtDir1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetStartDir( vtDir1) ; + Vector3d vtDir2 ; pCrvCompo->GetCurve( vIndClosedSides[2])->GetStartDir( vtDir2) ; + // i lati inclinati chiusi definiscono il Box + if ( abs( dLen2 * ( vtDir1 ^ vtDir2).Len() - dPocketSize) < TOLL_TRAPEZOID && + abs( dLen0 * ( vtDir1 ^ vtDir0).Len() - dPocketSize) < TOLL_TRAPEZOID) { + // creo la curva a trapezio + pCrvTrap->Clear() ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[2])->Clone()) ; + pCrvTrap->Close() ; + for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u) + pCrvTrap->SetCurveTempProp( u, u < 3 ? 0 : 1 , 1) ; + pCrvTrap->ChangeStartPoint( 1.) ; + // imposto le basi + nBase = 0 ; + nSecondBase = pCrvTrap->GetCurveCount() - 2 ; + } + } + } } } - - // se non ho trovato una base principale => non è ottimizzato - if ( ! bBaseFound) - return true ; } - // la curva a trapezio deve evere 4 lati - if ( pCrvTrap->GetCurveCount() != 4) { + + // se non ho trovato delle basi, allora cerco in maniera generale un trapezoide ( se esiste) + if ( nBase == -1) { + bool bOK = false ; + for ( int u = 0 ; u < pCrvCompo->GetCurveCount() && !bOK ; ++ u) { + // cerco un lato chiuso ( esiste per forza) + if ( pCrvCompo->GetCurve( u)->GetTempProp( 0) == 0) { + // controllo se il lato corrente può essere una base + int nType = -1 ; + if ( ! GetBoxCrvOptTrap( u, pCrvCompo, dDiam, nType, pCrvTrap)) + return false ; + // se è una base valida + if ( nType != -1) { + // ricavo la dimensione di svuotatura + pCrvTrap->GetCurve( 1)->GetLength( dPocketSize) ; + // ricavo la sua direzione iniziale + Vector3d vtBaseDir ; pCrvCompo->GetCurve( u)->GetStartDir( vtBaseDir) ; + // ricavo il suo punto iniziale + Point3d ptBaseStart ; pCrvCompo->GetCurve( u)->GetStartPoint( ptBaseStart) ; + // ricavo il suo punto finale + Point3d ptBaseEnd ; pCrvCompo->GetCurve( u)->GetEndPoint( ptBaseEnd) ; + // cerco il lato chiuso lineare parallelo ad esso e distante circa dPocketSize + for ( int uu = 0 ; uu < pCrvCompo->GetCurveCount() && !bOK ; ++ uu) { + if ( uu == u || + pCrvCompo->GetCurve( uu)->GetType() != CRV_LINE || + pCrvCompo->GetCurve( uu)->GetTempProp() != 0) + continue ; + Vector3d vtSecondBaseDir ; pCrvCompo->GetCurve( uu)->GetStartDir( vtSecondBaseDir) ; + if ( ! AreOppositeVectorEpsilon( vtBaseDir, vtSecondBaseDir, 5 * EPS_SMALL)) + continue ; + Point3d ptSecondBaseStart ; pCrvCompo->GetCurve( uu)->GetStartPoint( ptSecondBaseStart) ; + double dDist = 0. ; + DistPointCurve DPL( ptBaseStart, *pCrvCompo->GetCurve( uu), false) ; + if ( DPL.GetDist( dDist) && abs( dDist - dDiam) < TOLL_TRAPEZOID) { + nBase = u ; + nSecondBase = uu ; + if ( ! PreparareTrapezoidTwoBases( pCrvCompo, dDiam, nType, nBase, nSecondBase, bOK, pCrvTrap)) + return false ; + } + } + } + } + } + } + + // la curva a trapezio deve evere almeno 4 lati + if ( pCrvTrap->GetCurveCount() < 4 || nBase == -1 || nSecondBase == -1) { pCrvTrap->Clear() ; return true ; } + // ricostruisco il frame del trapezio + Point3d ptS ; pCrvTrap->GetStartPoint( ptS) ; + Vector3d vtS ; pCrvTrap->GetStartDir( vtS) ; + if ( ! frTrap.Set( ptS, Z_AX, vtS) || ! frTrap.IsValid()) + return false ; // se parametro MaxOptSize non compatibile => non è ottimizzato double dMaxOptSize ; @@ -12097,6 +12535,63 @@ Pocketing::GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveCompos return true ; } +//---------------------------------------------------------------------------- +bool +Pocketing::GetBoxCrvOptTrap( const int nCrv, const ICurveComposite* pCrvCompo, const double dDiam, int& nType, + ICurveComposite* pCrvBox) +{ + nType = - 1 ; + // prendo la curva + const ICurve* pCrvCurr = pCrvCompo->GetCurve( nCrv) ; + if ( pCrvCurr == nullptr) + return false ; + // controllo se lineare, altrimenti passo alla successiva + if ( pCrvCurr->GetType() != CRV_LINE) + return true ; + // prendo la direzione del tratto lineare + Vector3d vtDir ; pCrvCurr->GetStartDir( vtDir) ; + // prendo il punto iniziale + Point3d ptStart ; pCrvCurr->GetStartPoint( ptStart) ; + // creo il riferimento basato su questo tratto + Frame3d frTrap ; frTrap.Set( ptStart, Z_AX, vtDir) ; + if ( ! frTrap.IsValid()) + return false ; + // porto la curva Compo ( clonandola) nel frame e calcolo il suo BBox + BBox3d BBox ; + PtrOwner pCrvCompo_c( CloneCurveComposite( pCrvCompo)) ; + if ( IsNull( pCrvCompo_c) || ! pCrvCompo_c->IsValid() || + ! pCrvCompo_c->ToLoc( frTrap) || + ! pCrvCompo_c->GetLocalBBox( BBox)) + return false ; + // controllo dimY e dimX per il box + bool bDimYOk = BBox.GetDimY() < dDiam + TOLL_TRAPEZOID && BBox.GetMin().y > - TOLL_TRAPEZOID ; + bool bDimXOk = BBox.GetDimX() < dDiam + TOLL_TRAPEZOID && BBox.GetMin().y > - TOLL_TRAPEZOID ; + // controllo dimensioni ammissibili + if ( ! bDimXOk && ! bDimYOk) + return true ; // se nessuna + else if ( ! bDimXOk) + nType = 1 ; // se dimY + else if ( ! bDimYOk) + nType = 0 ; // se dimX + else + nType = 2 ; // se entrambe + + // creo il rettangolo del Box + pCrvBox->Clear() ; + pCrvBox->AddPoint( BBox.GetMin()) ; + pCrvBox->AddLine( BBox.GetMin() + BBox.GetDimX() * X_AX) ; + pCrvBox->AddLine( BBox.GetMax()) ; + pCrvBox->AddLine( BBox.GetMax() - BBox.GetDimX() * X_AX) ; + pCrvBox->Close() ; + + // determino il punto inziale della curva + if ( nType == 0) + pCrvBox->ChangeStartPoint( 1.) ; + + pCrvBox->ToGlob( frTrap) ; + return true ; +} + //---------------------------------------------------------------------------- bool Pocketing::CheckTrapezoidClosedEdgePosition( const ICurveComposite* pCrvCompo, const int nCrvInd, const double dDimBoxY, @@ -12109,112 +12604,124 @@ Pocketing::CheckTrapezoidClosedEdgePosition( const ICurveComposite* pCrvCompo, c // controllo che ci siano due o tre lati chiusi int nClosedEdge = int( vIndClosedSides.size()) ; - if ( nClosedEdge != 3) + if ( nClosedEdge != 3 && nClosedEdge != 2) return true ; - // TO DO se 2 chiusi consecutivi + gesitone archi - - // prendo i 3 lati chiusi - const ICurve* pCrv0 = pCrvCompo->GetCurve( vIndClosedSides[0]) ; - const ICurve* pCrv1 = pCrvCompo->GetCurve( vIndClosedSides[1]) ; - const ICurve* pCrv2 = pCrvCompo->GetCurve( vIndClosedSides[2]) ; - if ( pCrv0 == nullptr || pCrv1 == nullptr || pCrv2 == nullptr) - return false ; - // controllo che siano lineari - if ( pCrv0->GetType() != CRV_LINE || pCrv1->GetType() != CRV_LINE || pCrv2->GetType() != CRV_LINE) - return true ; - // prendo i punti iniziali e finali - Point3d ptStart0 ; pCrv0->GetStartPoint( ptStart0) ; - Point3d ptEnd0 ; pCrv0->GetEndPoint( ptEnd0) ; - Point3d ptStart1 ; pCrv1->GetStartPoint( ptStart1) ; - Point3d ptEnd1 ; pCrv1->GetEndPoint( ptEnd1) ; - Point3d ptStart2 ; pCrv2->GetStartPoint( ptStart2) ; - Point3d ptEnd2 ; pCrv2->GetEndPoint( ptEnd2) ; - // controllo che siano consecutivi e cambio l'ordine se necessario - if ( AreSamePointApprox( ptEnd0, ptStart1) && AreSamePointApprox( ptEnd1, ptStart2)) - ; - else if ( AreSamePointApprox( ptEnd1, ptStart2) && AreSamePointApprox( ptEnd2, ptStart0)) { - swap( vIndClosedSides[0], vIndClosedSides[1]) ; - swap( vIndClosedSides[1], vIndClosedSides[2]) ; - } - else if ( AreSamePointApprox( ptEnd2, ptStart0) && AreSamePointApprox( ptEnd0, ptStart1)) { - swap( vIndClosedSides[0], vIndClosedSides[2]) ; - swap( vIndClosedSides[2], vIndClosedSides[1]) ; - } - else // se non consecutivi - return true ; - - // se sono consecuti, ma la base non è il lato centrale, esco ( la ritroverò successivamente) - if ( vIndClosedSides[1] != nCrvInd) - return true ; - - // parametri lavorazione - double dDiam = m_TParams.m_dDiam ; - - // -------------- creo il bordo del trapezio estendendo i lati obliqui se possibile ------------------------ - // estendo - PtrOwner pEdge0( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; - PtrOwner pEdge2( pCrvCompo->GetCurve( vIndClosedSides[2])->Clone()) ; - Point3d ptS0 ; pEdge0->GetStartPoint( ptS0) ; - Point3d ptE2 ; pEdge2->GetEndPoint( ptE2) ; - if ( abs( ptS0.y - dDimBoxY) > TOLL_TRAPEZOID) { - Vector3d vtDir ; pEdge0->GetStartDir( vtDir) ; - double dSinT = sqrt( 1 - vtDir.x * vtDir.x) ; - if ( dSinT > TOLL_TRAPEZOID) { - pEdge0->ExtendStartByLen(( dDimBoxY - ptS0.y) / dSinT) ; - pEdge0->GetStartPoint( ptS0) ; + // se sono 2 + if ( nClosedEdge == 2) { + // ricavo direzioni + Vector3d vtStart0 ; pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartDir( vtStart0) ; + Vector3d vtStart1 ; pCrvCompo->GetCurve( vIndClosedSides[1])->GetStartDir( vtStart1) ; + // se opposte + if ( AreOppositeVectorEpsilon( vtStart0, vtStart1, 5 * EPS_SMALL)) { + } + } - if ( abs( ptE2.y - dDimBoxY) > TOLL_TRAPEZOID) { - Vector3d vtDir ; pEdge2->GetStartDir( vtDir) ; - double dSinT = sqrt( 1 - vtDir.x * vtDir.x) ; - if ( dSinT > TOLL_TRAPEZOID) { - pEdge2->ExtendEndByLen(( dDimBoxY - ptE2.y) / dSinT) ; - pEdge2->GetEndPoint( ptE2) ; + else { + // se sono 3 + // prendo i 3 lati chiusi + const ICurve* pCrv0 = pCrvCompo->GetCurve( vIndClosedSides[0]) ; + const ICurve* pCrv1 = pCrvCompo->GetCurve( vIndClosedSides[1]) ; + const ICurve* pCrv2 = pCrvCompo->GetCurve( vIndClosedSides[2]) ; + if ( pCrv0 == nullptr || pCrv1 == nullptr || pCrv2 == nullptr) + return false ; + // controllo che siano lineari + if ( pCrv0->GetType() != CRV_LINE || pCrv1->GetType() != CRV_LINE || pCrv2->GetType() != CRV_LINE) + return true ; + // prendo i punti iniziali e finali + Point3d ptStart0 ; pCrv0->GetStartPoint( ptStart0) ; + Point3d ptEnd0 ; pCrv0->GetEndPoint( ptEnd0) ; + Point3d ptStart1 ; pCrv1->GetStartPoint( ptStart1) ; + Point3d ptEnd1 ; pCrv1->GetEndPoint( ptEnd1) ; + Point3d ptStart2 ; pCrv2->GetStartPoint( ptStart2) ; + Point3d ptEnd2 ; pCrv2->GetEndPoint( ptEnd2) ; + // controllo che siano consecutivi e cambio l'ordine se necessario + if ( AreSamePointApprox( ptEnd0, ptStart1) && AreSamePointApprox( ptEnd1, ptStart2)) + ; + else if ( AreSamePointApprox( ptEnd1, ptStart2) && AreSamePointApprox( ptEnd2, ptStart0)) { + swap( vIndClosedSides[0], vIndClosedSides[1]) ; + swap( vIndClosedSides[1], vIndClosedSides[2]) ; } - } - // creo il bordo del trapezio esteso - PtrOwner pCrvTrapBorder( CreateCurveComposite()) ; - if ( IsNull( pCrvTrapBorder)) - return false ; - pCrvTrapBorder->AddPoint( ptS0) ; - pCrvTrapBorder->AddCurve( Release( pEdge0)) ; - pCrvTrapBorder->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; - pCrvTrapBorder->AddCurve( Release( pEdge2)) ; - pCrvTrapBorder->Close() ; - // ---------------------------------------------------------------------------------------------------------- + else if ( AreSamePointApprox( ptEnd2, ptStart0) && AreSamePointApprox( ptEnd0, ptStart1)) { + swap( vIndClosedSides[0], vIndClosedSides[2]) ; + swap( vIndClosedSides[2], vIndClosedSides[1]) ; + } + else // se non consecutivi + return true ; - // verifico dimensione x della svuotatura - double dLen0 = 0, dLen2 = 0 ; - pCrvTrapBorder->GetCurve( 0)->GetLength( dLen0) ; - pCrvTrapBorder->GetCurve( 2)->GetLength( dLen2) ; - if ( dLen0 < dDiam - EPS_SMALL || dLen2 < dDiam - EPS_SMALL) - return true ; + // se sono consecuti, ma la base non è il lato centrale, esco ( la ritroverò successivamente) + if ( vIndClosedSides[1] != nCrvInd) + return true ; - // creo un piccolo Offset e controllo che il trapezio non intersechi la curva Compo - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCrvTrapBorder, TOLL_TRAPEZOID, ICurve::OFF_EXTEND)) { - m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; - return false ; + // parametri lavorazione + double dDiam = m_TParams.m_dDiam ; + + // -------------- creo il bordo del trapezio estendendo i lati obliqui se possibile ------------------------ + // estendo + PtrOwner pEdge0( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + PtrOwner pEdge2( pCrvCompo->GetCurve( vIndClosedSides[2])->Clone()) ; + Point3d ptS0 ; pEdge0->GetStartPoint( ptS0) ; + Point3d ptE2 ; pEdge2->GetEndPoint( ptE2) ; + if ( abs( ptS0.y - dDimBoxY) > TOLL_TRAPEZOID) { + Vector3d vtDir ; pEdge0->GetStartDir( vtDir) ; + double dSinT = sqrt( 1 - vtDir.x * vtDir.x) ; + if ( dSinT > TOLL_TRAPEZOID) { + pEdge0->ExtendStartByLen(( dDimBoxY - ptS0.y) / dSinT) ; + pEdge0->GetStartPoint( ptS0) ; + } + } + if ( abs( ptE2.y - dDimBoxY) > TOLL_TRAPEZOID) { + Vector3d vtDir ; pEdge2->GetStartDir( vtDir) ; + double dSinT = sqrt( 1 - vtDir.x * vtDir.x) ; + if ( dSinT > TOLL_TRAPEZOID) { + pEdge2->ExtendEndByLen(( dDimBoxY - ptE2.y) / dSinT) ; + pEdge2->GetEndPoint( ptE2) ; + } + } + // creo il bordo del trapezio esteso + PtrOwner pCrvTrapBorder( CreateCurveComposite()) ; + if ( IsNull( pCrvTrapBorder)) + return false ; + pCrvTrapBorder->AddPoint( ptS0) ; + pCrvTrapBorder->AddCurve( Release( pEdge0)) ; + pCrvTrapBorder->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrapBorder->AddCurve( Release( pEdge2)) ; + pCrvTrapBorder->Close() ; + // ---------------------------------------------------------------------------------------------------------- + + // verifico dimensione x della svuotatura + double dLen0 = 0, dLen2 = 0 ; + pCrvTrapBorder->GetCurve( 0)->GetLength( dLen0) ; + pCrvTrapBorder->GetCurve( 2)->GetLength( dLen2) ; + if ( dLen0 < dDiam - EPS_SMALL || dLen2 < dDiam - EPS_SMALL) + return true ; + + // creo un piccolo Offset e controllo che il trapezio non intersechi la curva Compo + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pCrvTrapBorder, TOLL_TRAPEZOID, ICurve::OFF_EXTEND)) { + m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; + return false ; + } + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOffs)) + return false ; + IntersCurveCurve IntCC( *pCrvOffs, *pCrvCompo) ; + CRVCVECTOR ccClass ; + // se c'è intersezione, esco + if ( IntCC.GetRegionCurveClassification() != CCREGC_IN2) + return true ; + // costruisco il trapezio + pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartPoint( ptS0) ; + pCrvTrap->AddPoint( ptS0) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; + pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[2])->Clone()) ; + pCrvTrap->Close() ; + pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, 1, 0) ; + pCrvTrap->ChangeStartPoint( 1.) ; // la base è sempre la curva 0 + bOk = true ; } - PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; - if ( IsNull( pCrvOffs)) - return false ; - IntersCurveCurve IntCC( *pCrvOffs, *pCrvCompo) ; - CRVCVECTOR ccClass ; - // se c'è intersezione, esco - if ( IntCC.GetRegionCurveClassification() != CCREGC_IN2) - return true ; - // costruisco il trapezio - pCrvCompo->GetCurve( vIndClosedSides[0])->GetStartPoint( ptS0) ; - pCrvTrap->AddPoint( ptS0) ; - pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[0])->Clone()) ; - pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[1])->Clone()) ; - pCrvTrap->AddCurve( pCrvCompo->GetCurve( vIndClosedSides[2])->Clone()) ; - pCrvTrap->Close() ; - pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, 1, 0) ; - pCrvTrap->ChangeStartPoint( 1.) ; // la base è sempre la curva 0 - bOk = true ; return true ; } @@ -12254,8 +12761,8 @@ Pocketing::CheckSecondBaseTrapezoid( const ICurveComposite* pCrvCompo, const int //---------------------------------------------------------------------------- bool -Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d BBox, const int nBase, int& nSecondBase, - bool& bOk, ICurveComposite* pCrvTrap) +Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam, const int nType, int& nBase, + int& nSecondBase, bool& bOk, ICurveComposite* pCrvTrap) { // controllo parametri if ( pCrvCompo == nullptr) @@ -12264,11 +12771,13 @@ Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d // le parti tra le due basi devono essere tutte omogenee ( o tutte aperte o tutte chiuse) // pCrvTest0 sarà la parte destra, pCrvTest1 la parte sinistra - Point3d ptSB0, ptSB1 ; + Point3d ptSB0, ptSB1 ,ptEB0, ptEB1 ; PtrOwner pCrvTest0( CloneCurveComposite( pCrvCompo)) ; PtrOwner pCrvTest1( CloneCurveComposite( pCrvCompo)) ; pCrvCompo->GetCurve( nBase)->GetStartPoint( ptSB0) ; + pCrvCompo->GetCurve( nBase)->GetEndPoint( ptEB0) ; pCrvCompo->GetCurve( nSecondBase)->GetStartPoint( ptSB1) ; + pCrvCompo->GetCurve( nSecondBase)->GetEndPoint( ptEB1) ; pCrvTest0->ChangeStartPoint( nBase) ; pCrvTest1->ChangeStartPoint( nSecondBase) ; double dUTrim0, dUTrim1 ; @@ -12293,25 +12802,18 @@ Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d return true ; // se TmpProp diverse => non è un caso ottimizzato } - // parametri lavorazione - double dDiam = m_TParams.m_dDiam ; - - // creo la base principale e secondaria - PtrOwner pCrvBase0( pCrvCompo->GetCurve( nBase)->Clone()) ; - PtrOwner pCrvBase1( pCrvCompo->GetCurve( nSecondBase)->Clone()) ; - // ricavo i nuovi estremi - Point3d ptEB0, ptEB1 ; - pCrvBase0->GetStartPoint( ptSB0) ; - pCrvBase0->GetEndPoint( ptEB0) ; - pCrvBase1->GetStartPoint( ptSB1) ; - pCrvBase1->GetEndPoint( ptEB1) ; - // se lato destro aperto ( estendo il punto finale della base principale e il punto iniziale // della base secondaria fino al lato destro del box) bool bCopyRight = false ; if ( pCrvTest0->GetCurve( 0)->GetTempProp( 0) == 1) { - ptEB0 = BBox.GetMin() + X_AX * BBox.GetDimX() ; - ptSB1 = ptEB0 + dDiam * Y_AX ; + if ( nType == 0) { + pCrvTrap->GetCurve( 0)->GetStartPoint( ptEB0) ; + pCrvTrap->GetCurve( 1)->GetStartPoint( ptSB1) ; + } + else { + pCrvTrap->GetCurve( 0)->GetEndPoint( ptEB0) ; + pCrvTrap->GetCurve( 1)->GetEndPoint( ptSB1) ; + } } // se lato destro chiuso else @@ -12320,16 +12822,24 @@ Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d // della base primaria dino al lato sinistro del box) bool bCopyLeft = false ; if ( pCrvTest1->GetCurve( 0)->GetTempProp( 0) == 1) { - ptSB0 = BBox.GetMin() ; - ptEB1 = BBox.GetMin() + dDiam * Y_AX ; + if ( nType == 0) { + pCrvTrap->GetCurve( 2)->GetEndPoint( ptEB1) ; + pCrvTrap->GetCurve( 0)->GetStartPoint( ptSB0) ; + } + else { + pCrvTrap->GetCurve( 1)->GetEndPoint( ptEB1) ; + pCrvTrap->GetCurve( 2)->GetEndPoint( ptSB0) ; + } } // se lato sinistro chiuso else bCopyLeft = true ; // creo la curva da restituire + pCrvTrap->Clear() ; pCrvTrap->AddPoint( ptSB0) ; pCrvTrap->AddLine( ptEB0) ; + nBase = 0 ; if ( bCopyRight) pCrvTrap->AddCurve( Release( pCrvTest0)) ; else { @@ -12347,10 +12857,10 @@ Pocketing::PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d // verifico dimensione x della svuotatura nel caso tutto chiuso if ( bCopyLeft && bCopyRight) { - double dLen0 = 0, dLen1 = 0 ; - pCrvBase0->GetLength( dLen0) ; - pCrvBase1->GetLength( dLen1) ; - if ( dLen0 < dDiam - EPS_SMALL || dLen1 < dDiam - EPS_SMALL) { + double dLen0 = 0, dLen2 = 0 ; + pCrvTrap->GetCurve( nBase)->GetLength( dLen0) ; + pCrvTrap->GetCurve( nSecondBase)->GetLength( dLen2) ; + if ( dLen0 < dDiam - EPS_SMALL || dLen2 < dDiam - EPS_SMALL) { pCrvTrap->Clear() ; return true ; } diff --git a/Pocketing.h b/Pocketing.h index bdeeaa1..3d91488 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -85,8 +85,8 @@ class Pocketing : public Machining bool CreateStmForIntersection( ISurfTriMesh* pStm, ICRVCOMPOPOVECTOR& vCrvCompo, const Vector3d& vtN) ; bool CalcOffsExtensionsForCurves( const ICurveComposite* pCrvCompo, const Vector3d& vtN, double& dExt) ; bool GetExtendedLoopToFitStmVolume( ICurveComposite* pCrvLoop, const double& dExt, const Vector3d& vtN) ; - bool GetCurrentPart( const Point3d& ptInside, ISurfTriMesh* pStmPart) ; - bool SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm) ; + bool GetCurrentPart( const PNTVECTOR& vPtInside, ISurfTriMesh* pStmPart) ; + bool SetPocketingVolume( const PNTVECTOR& vPtInside, ISurfTriMesh* pStm) ; bool AdjustPocketingSideForVolumePart( ISurfTriMesh* pStmVolPart, const Vector3d& vtTool) ; bool SewingMissingFacesOnPlanes( ISurfTriMesh* pStm, const Plane3d& plPlane) ; bool ChainBisectors( ICURVEPOVECTOR& vpCrvs, ICRVCOMPOPOVECTOR& vCrvCompo) ; @@ -135,24 +135,27 @@ class Pocketing : public Machining bool ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, bool bAsParam) ; bool OrderCurvesByLastPntOfPath( ICRVCOMPOPOVECTOR& vCrv, Point3d ptEnd, PNTVECTOR& vPtStart, VCT3DVECTOR& vVtOut, BOOLVECTOR& vbMidOut) ; - bool SetBetterPtStartForSubChunks( ICurveComposite* pCrv0, const ISurfFlatRegion* pSrfToWork, Point3d& ptStart, - Vector3d& vtMidOut, bool& bMidOut) ; + bool SetBetterPtStartForSubChunks( ICurveComposite* pCrv0, const ISurfFlatRegion* pSrfToWork, const Point3d& ptEndPrec, + const Frame3d& frPocket, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) ; bool GetOptCrvIndex( const std::vector& vCrvOEWithFlags, int nStep, ISurfFlatRegion* pSrfChunkFinal, int& nIndex) ; bool GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTrap, Frame3d& frTrap, double& dPocketSize, int& nBase, int& nSecondBase) ; + bool GetBoxCrvOptTrap( const int nCrv, const ICurveComposite* pCrvCompo, const double dDiam, int& nType, ICurveComposite* pCrvBox) ; bool CheckTrapezoidClosedEdgePosition( const ICurveComposite* pCrvCompo, const int nCrvInd, const double dDimBoxY, INTVECTOR& vIndClosedSides, bool& bOk, ICurveComposite* pCrvTrap) ; bool CheckSecondBaseTrapezoid( const ICurveComposite* pCrvCompo, const int nCrvInd, int& nSecondBase) ; - bool PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, BBox3d BBox, const int nBase, int& nSecondBase, - bool& bOk, ICurveComposite* pCrvTrap) ; + bool PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam, const int nType, int& nBase, + int& nSecondBase, bool& bOk, ICurveComposite* pCrvTrap) ; bool GetSfrByStm( const ISurfTriMesh* pStm, ISurfFlatRegion* pSfr, const Plane3d plPock, const Vector3d& vtExtr, const double dThick, double dToll = 5 * EPS_SMALL) ; bool ProjectStmOnPlane( const ISurfTriMesh* pStmAbove, const Plane3d plPock, ISurfFlatRegion* pSfrProj) ; bool GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) ; - bool GetParamOnOpenSide( const ICurveComposite* pCompo,const ICRVCOMPOPOVECTOR& vCrvIsl, Point3d& ptMid, Vector3d& vtMidOut) ; - bool AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, bool bOrder = false) ; + bool GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, + const Frame3d& frPocket, Point3d& ptMid, Vector3d& vtMidOut) ; + bool AdjustContourStart( ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, bool bOrder = false, + Point3d ptRef = P_INVALID) ; bool GetParamForPtStartOnEdge( const ICurve* pCrv, const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vCrvIsl, double& dPar) ; bool CheckForRemovingIsland( const ICurveComposite* pCrvIslandBorder, double dOffs, bool bRemove) ; @@ -186,7 +189,7 @@ class Pocketing : public Machining VCT3DVECTOR& vVtTrasl, ISURFFRPOVECTOR& vSrfLimit, const Vector3d& vtTool, const Vector3d& vtExtr, double dDepth, double dElev, double dMaxElev, double dOkStep, bool bSplitArcs, const double dExtraLenInOut) ; - bool CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptStart, Vector3d& vtMidOut , bool& bMidOut, + bool CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptStart, const Point3d& ptEndPrec, Vector3d& vtMidOut , bool& bMidOut, bool bSplitArcs,ICurveComposite* pMCrv, ICurveComposite* pRCrv, ICurveComposite* pCrvOEWithFlags, bool vbChangedPrec, bool& bOptimizedTrap) ; bool CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nIter, @@ -266,8 +269,9 @@ class Pocketing : public Machining double dElev, double dAppr) ; bool CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, const ICurveComposite* pRCrv, Point3d& ptP1) const ; - bool AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, - ISurfFlatRegion* pSrfChunk, const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, + bool AddLeadIn( const ICurveComposite* pCrvCompo, const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, + const Vector3d& vtEnd, const Vector3d& vtN, ISurfFlatRegion* pSrfChunk, + const ICurveComposite* pRCrv, bool bAtLeft, bool bSplitArcs, bool bNoneForced = false, bool bSkipControl = false) ; bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, Point3d& ptP1, @@ -275,6 +279,8 @@ class Pocketing : public Machining bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, Point3d& ptP1, double& dElev, bool& bOppositeHome, bool bRecalcElev = true) ; + bool SetLeadInPointStart( const Point3d& ptCurr, const Vector3d vtN, + const bool& bAtLeft, Vector3d& vtStart, Point3d& ptDest) ; bool CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrLimit, ICurveComposite* pCrvStepLink) ; double GetRadiusForStartEndElevation( void) const ; @@ -341,5 +347,4 @@ class Pocketing : public Machining double m_dLen_Prec = 0.0 ; // Lunghezza del tool precedente bool m_bOrderStepZ = true ; // parametro per ordinare gli step Extra per Z decrescente o meno bool m_bPocketPlane = false ; // flag per svuotare solo la rimanenza sullo Step Extra - } ; \ No newline at end of file