diff --git a/SurfFinishing.cpp b/SurfFinishing.cpp index 4d49594..489be00 100644 --- a/SurfFinishing.cpp +++ b/SurfFinishing.cpp @@ -2537,7 +2537,7 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons bool SurfFinishing::GetZConstQuotesInsideSfrParallelToTool( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, const Vector3d& vtTool, - set& setZAmbiguos) + set& setZAmbiguos) const { // controllo dei parametri setZAmbiguos.clear() ; @@ -2660,7 +2660,7 @@ SurfFinishing::GetSfrSilhouette( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& //---------------------------------------------------------------------------- bool SurfFinishing::CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, - const ISurfFlatRegion* pSfrClass, const Vector3d& vtTool, double dDepth, vector& vCrvCompo) + const ISurfFlatRegion* pSfrClass, const Vector3d& vtTool, double dDepth, vector& vCrvCompo) const { /* funzione per calcolare le curve singole di finitura mediante Silhouette e le regioni da non rovinare */ @@ -2818,7 +2818,7 @@ SurfFinishing::CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SU bool SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, vector& vCrvCompo, const Vector3d& vtTool, const ISurfFlatRegion* pSfr, - double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) + double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) const { /* funzione per collegare le curve trovate creando quindi i percorsi di lavoro */ // NB. La prima tempProp della curva è il piano in cui iniziale e la seconda tempProp è @@ -3106,7 +3106,7 @@ bool SurfFinishing::CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket, const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, const Point3d ptStart_forced, const Point3d ptEnd_forced, - ICurveComposite* pCrv) + ICurveComposite* pCrv) const { // funzione per proiettare una curva su una supericie trimesh passando per la silhouette // controllo dei parametri @@ -4037,21 +4037,21 @@ SurfFinishing::ProcessSquare( int nFlag, double dLevel, double dQPt0, double dQp // C0 - E0 - C1 static int LineTable[16][4] = { { 0, -1, -1, -1}, // ( 0) - { 2, 0, 5, 3}, // ( 1) - { 2, 1, 4, 0}, // ( 2) - { 1, 1, 3, -1}, // ( 3) - { 2, 2, 5, 1}, // ( 4) - { -1, -1, -1, -1}, // ( 5) -> ambiguo - { 1, 2, 0, -1}, // ( 6) - { 2, 2, 4, 3}, // ( 7) - { 2, 3, 4, 2}, // ( 8) - { 1, 0, 2, -1}, // ( 9) - { -1, -1, -1, -1}, // ( 10) -> ambiguo - { 2, 1, 5, 2}, // ( 11) - { 1, 3, 1, -1}, // ( 12) - { 2, 0, 4, 1}, // ( 13) - { 2, 3, 5, 0}, // ( 14) - { 0, -1, -1, -1} } ; // ( 15) + { 2, 0, 5, 3}, // ( 1) + { 2, 1, 4, 0}, // ( 2) + { 1, 1, 3, -1}, // ( 3) + { 2, 2, 5, 1}, // ( 4) + { -1, -1, -1, -1}, // ( 5) -> ambiguo + { 1, 2, 0, -1}, // ( 6) + { 2, 2, 4, 3}, // ( 7) + { 2, 3, 4, 2}, // ( 8) + { 1, 0, 2, -1}, // ( 9) + { -1, -1, -1, -1}, // ( 10) -> ambiguo + { 2, 1, 5, 2}, // ( 11) + { 1, 3, 1, -1}, // ( 12) + { 2, 0, 4, 1}, // ( 13) + { 2, 3, 5, 0}, // ( 14) + { 0, -1, -1, -1} } ; // ( 15) static int LineTableAmbiguos[4][5] = { { 2, 2, 1, 0, 3}, // ( 5-split) { 2, 2, 3, 0, 1}, // ( 5-stick) { 2, 1, 0, 3, 2}, // ( 10-split) @@ -4124,7 +4124,7 @@ SurfFinishing::TestSubEdges( unordered_map& umEdgePnt, const INTVE vtAxL, vtMoveL, dCosSplitAng, pCAvTlStm, _nInd_debug) ; if ( ! ptQ.IsValid()) return false ; - umEdgePnt[ nKey] = ptQ ; + umEdgePnt[nKey] = ptQ ; } return true ; } @@ -4182,28 +4182,28 @@ SurfFinishing::MarchingSquares( const VECTORCOLLISIONSFR& vPntM, bool bSpiral, d if ( bUp0 != bUp1) { int nKey = 4 * nInd0 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } if ( bUp3 != bUp2) { int nKey = 4 * nInd3 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } if ( bUp0 != bUp3) { int nKey = 4 * nInd0 + 1 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } if ( bUp1 != bUp2) { int nKey = 4 * nInd1 + 1 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } @@ -4216,14 +4216,14 @@ SurfFinishing::MarchingSquares( const VECTORCOLLISIONSFR& vPntM, bool bSpiral, d if ( bUp1 != bUp3) { int nKey = 4 * nInd0 + 2 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } if ( bUp0 != bUp2) { int nKey = 4 * nInd0 + 3 ; if ( umEdgePnt.find( nKey) == umEdgePnt.end()) { - umEdgePnt[ nKey] = P_INVALID ; + umEdgePnt[nKey] = P_INVALID ; vEdgeInd.emplace_back( nKey) ; } } @@ -4351,14 +4351,23 @@ SurfFinishing::MarchingSquares( const VECTORCOLLISIONSFR& vPntM, bool bSpiral, d const double SILH_ARC_TOL = 0.1 ; const double SILH_ARC_FEA_MAX = 100. ; for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + #if ENABLE_OPTIMAL_DEBUG + int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, _nInd_debug, vCrvCompo[i]->Clone()) ; + m_pGeomDB->SetMaterial( a, WHITE) ; + #endif PolyArc PA ; if ( vCrvCompo[i]->ApproxWithArcsEx( SILH_ARC_TOL, ANG_TOL_STD_DEG, SILH_ARC_FEA_MAX, PA)) { PtrOwner pTempCrv( CreateCurveComposite()) ; if ( ! IsNull( pTempCrv) && pTempCrv->FromPolyArc( PA) && pTempCrv->RemoveSmallDefects( SILH_ARC_TOL / 2, ANG_TOL_STD_DEG) && - pTempCrv->MergeCurves( SILH_ARC_TOL / 2, ANG_TOL_STD_DEG)) + pTempCrv->MergeCurves( SILH_ARC_TOL / 2, ANG_TOL_STD_DEG)) { vCrvCompo[i].Set( pTempCrv) ; + #if ENABLE_OPTIMAL_DEBUG + int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, _nInd_debug, vCrvCompo[i]->Clone()) ; + m_pGeomDB->SetMaterial( a, PURPLE) ; + #endif + } } } @@ -4392,8 +4401,25 @@ SurfFinishing::GetOptimalSfr( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& double dCosClipping = cos( dSplitAngle * DEGTORAD) ; // costanti - const double TOL_SAMPLE = 2. ; // Tolleranza di campionamento per collisioni - const double EXTRA_XY = 2.5 * TOL_SAMPLE ; // Espansione del Box in X e Y per griglia di campionamento + const double TOL_SAMPLE = 2. ; + double dExtraXY = 0. ; + if ( m_TParams.m_dSideAng < EPS_ANG_SMALL) + dExtraXY += m_TParams.m_dDiam / 2. ; + else { + double dDeltaRad ; + double dSideAngRad = m_TParams.m_dSideAng * DEGTORAD ; + if ( m_TParams.m_dSideAng > 0) { + if ( m_TParams.m_dCornRad < EPS_SMALL) + dDeltaRad = m_TParams.m_dMaxMat * tan( dSideAngRad) ; + else + dDeltaRad = ( m_TParams.m_dCornRad * cos( dSideAngRad) + + ( m_TParams.m_dMaxMat + m_TParams.m_dCornRad * ( sin( dSideAngRad) - 1)) * tan( dSideAngRad)) ; + } + else + dDeltaRad = tan( dSideAngRad) * m_TParams.m_dMaxMat ; + dExtraXY += m_TParams.m_dDiam / 2. + dDeltaRad ; + } + const double EXTRA_XY = dExtraXY + 2.5 * TOL_SAMPLE ; // frame pianoXY Frame3d frXY ; @@ -4468,6 +4494,7 @@ SurfFinishing::GetOptimalSfr( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& } get<2>( vCollision[nInd].CollisionInfo).push_back( get<2>( vPntM[nInd])[nV]) ; } + #if ENABLE_OPTIMAL_DEBUG PtrOwner pt( CreateGeoPoint3d()) ; pt->Set( get<0>( vCollision[nInd].CollisionInfo)) ; @@ -4573,7 +4600,7 @@ SurfFinishing::OrderAndConnectPencilCurves( ICRVCOMPOPOVECTOR& vCrvCompo, double } } // se ho meno di 2 curve da ordinare, non faccio nulla - if ( int( vCrvCompo.size() < 2)) + if ( int( vCrvCompo.size()) < 2) return true ; // vettore dei quadrati delle distanze @@ -5356,6 +5383,192 @@ SurfFinishing::AddPencil( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrf return true ; } +//---------------------------------------------------------------------------- +bool +SurfFinishing::CalcOptimalSpiralCurves( const ISurfFlatRegion* pSfrSpiral, const ISurfFlatRegion* pSfrCnt, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, + ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const +{ + // se la superficie non è valida, non restituisco nulla + if ( pSfrSpiral == nullptr || ! pSfrSpiral->IsValid()) + return true ; + + // le curve di finitura spiral devono stare sul bordo della regione trovata + PtrOwner pMySfrSpiral( pSfrSpiral->CreateOffsetSurf( m_Params.m_dSideStep, ICurve::OFF_FILLET)) ; + if ( IsNull( pMySfrSpiral)) + return false ; + + // mi assicuro di non uscire dalla superficie originale + double dOffs = - m_TParams.m_dDiam / 2. - GetOffsR() + m_Params.m_dOverlap + 5 * EPS_SMALL ; + PtrOwner pSfrClass( pSfrCnt->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrClass)) + return false ; + if ( pSfrClass->IsValid()) { + pSfrClass->ToLoc( frSurf) ; + pMySfrSpiral->Intersect( *pSfrClass) ; + } + else + pMySfrSpiral->Clear() ; + + // se regione risultante non valida, non faccio nulla + if ( ! pMySfrSpiral->IsValid()) + return true ; + + // imposto i lati chiusi + for ( int nC = 0 ; nC < pMySfrSpiral->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pMySfrSpiral->GetLoopCount( nC) ; ++ nL) { + for ( int nU = 0 ; nU < pMySfrSpiral->GetLoopCurveCount( nC, nL) ; ++ nU) + pMySfrSpiral->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ; + } + } + + // eseguo calcolo delle lavorazioni come SpiralIN + ICRVCOMPOPOVECTOR vpCrvs ; + if ( ! CalcPocketing( pMySfrSpiral, 0., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5., + POCKET_SPIRALIN, false, false, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep, + m_Params.m_dLiTang, GetLeadInType(), vpCrvs)) { + m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ; + return false ; + } + + // ciclo sui percorsi ricavati risultanti + double dProgCoeff = 1. / max( int( vpCrvs.size()), 1) ; + for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) { + // definisco un nuovo percorso (in locale) + vPaths.resize( vPaths.size() + 1) ; + vPaths.back().pCrvPath.Set( Release( vpCrvs[k])) ; + vPaths.back().nType = SURFFIN_SUB_SPIRALIN ; + // li correggo per non interferire con le superfici + if ( pCAvTlStm != nullptr) { + // approssimo la curva con una polilinea + PolyLine PL ; + if ( ! vPaths.back().pCrvPath->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + return false ; + // eventuale aggiunta di punti per garantire max distanza + const double MIN_DIST = 1. ; + const double MAX_DIST = 50. ; + double dDist = Clamp( m_TParams.m_dDiam / 2, MIN_DIST, MAX_DIST) ; + if ( ! PL.AdjustForMaxSegmentLen( dDist)) + return false ; + // porto i dati geometrici in locale alle superfici + Vector3d vtAxL = vtTool ; + vtAxL.ToLoc( frSurf) ; + Vector3d vtMoveL = vtAxL ; + // traslo della lunghezza utensile diminuita dell'affondamento + PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ; + // eseguo CAv + if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox, ( k + 1) * dProgCoeff)) + return false ; + // contro-traslo della lunghezza utensile + PL.Translate( - vtAxL * m_TParams.m_dLen) ; + // elimino i punti allineati + PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ; + // creo una curva composita a partire dalla polilinea + PtrOwner< ICurveComposite> pCompo( CreateCurveComposite()) ; + if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) + return false ; + // sostituisco la vecchia curva con la nuova + vPaths.back().pCrvPath.Set( pCompo) ; + } + } + + // porto tutti i percorsi nel frame globale + for ( int i = 0 ; i < int( vPaths.size()) ; ++ i) + vPaths[i].pCrvPath->ToGlob( frSurf) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrZConst, const ISurfFlatRegion* pSfrCnt, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, + const SURFLOCALVECTOR& vSrfLoc, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const +{ + // se la superficie non è valida, non restituisco nulla + if ( pSfrZConst == nullptr || ! pSfrZConst->IsValid()) + return true ; + + // mi assicuro di non uscire dalla superficie originale + PtrOwner pMySfrZConst( pSfrZConst->CreateOffsetSurf( m_Params.m_dSideStep, ICurve::OFF_FILLET)) ; + if ( IsNull( pMySfrZConst)) + return false ; + double dOffs = - m_TParams.m_dDiam / 2. - GetOffsR() + m_Params.m_dOverlap + 5 * EPS_SMALL ; + PtrOwner pSfrClass( pSfrCnt->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrClass)) + return false ; + if ( pSfrClass->IsValid()) { + pSfrClass->ToLoc( frSurf) ; + pMySfrZConst->Intersect( *pSfrClass) ; + } + else + pMySfrZConst->Clear() ; + + // se regione risultante non valida, non faccio nulla + if ( ! pMySfrZConst->IsValid()) + return true ; + + // imposto i lati chiusi + for ( int nC = 0 ; nC < pMySfrZConst->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pMySfrZConst->GetLoopCount( nC) ; ++ nL) { + for ( int nU = 0 ; nU < pMySfrZConst->GetLoopCurveCount( nC, nL) ; ++ nU) + pMySfrZConst->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ; + } + } + + // inizializzo la classe di calcolo delle silhouette + CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ; + // scorro le superfici + for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) { + // recupero la superficie TriMesh e se valida la memorizzo + const ISurfTriMesh* pStm = GetSurfTriMesh( vSrfLoc[i].Get()) ; + if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) + vpStm.emplace_back( pStm) ; + } + + // definisco il frame della regione piana + Frame3d frSfr ; + Point3d ptC ; pSfrZConst->GetCentroid( ptC) ; + if ( ! frSfr.Set( ptC, pSfrZConst->GetNormVersor())) + return false ; + + // inizializzo classe di calcolo per le curve a ZConst + PtrOwner pCavParSilh( CreateCAvParSilhouettesSurfTm()) ; + if ( IsNull( pCavParSilh) || + ! pCavParSilh->SetData( vpStm, frSfr, SILH_SAMPLING, m_TParams.m_dSideAng, m_TParams.m_dDiam, + m_TParams.m_dCornRad, m_TParams.m_dMaxMat, GetOffsR(), dDepth)) + return false ; + + // recupero le curve singole definite dal bordo della Silhouette + vector vCrvCompo ; + if ( ! CalcZConstSilCrv( pCavParSilh, vSrfLoc, frSurf, pMySfrZConst, vtTool, dDepth, vCrvCompo)) { + m_pMchMgr->SetLastError( 3126, "Error in SurfFinishing : Computing ZConst Curves failed") ; + return false ; + } + + // se non ho ricato curve, non faccio nulla + if ( vCrvCompo.empty()) + return true ; + + // collego tra loro le curve trovate + ICRVCOMPOPOVECTOR vCrv ; + if ( ! CreateZConstPaths( pCAvTlStm, frSurf, vCrvCompo, vtTool, pMySfrZConst, dDepth, vCrv)) { + m_pMchMgr->SetLastError( 3127, "Error in SurfFinishing : Computing ZConst Paths failed") ; + return false ; + } + + // aggiungo i percorsi trovati + for ( int i = 0 ; i < int( vCrv.size()) ; ++ i) { + vPaths.resize( vPaths.size() + 1) ; + vPaths.back().pCrvPath.Set( Release( vCrv[i])) ; + vPaths.back().nType = SURFFIN_SUB_Z_CONST ; + // in globale + vPaths.back().pCrvPath->ToGlob( frSurf) ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, @@ -5389,204 +5602,29 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr return false ; } - // ----------------------- Lavorazione Spiral ------------------------------- - if ( ! IsNull( pSfrSpiral) && pSfrSpiral->IsValid()) { - // se richiesto parametro SkipMaxDown, devo limitare questa superficie alla vera Silhouette - bool bSkipMaxDown = true ; - GetValInNotes( m_Params.m_sUserNotes, "SkipMaxDown", bSkipMaxDown) ; - PtrOwner pSfrSil_real( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrSil_real)) - return false ; - if ( bSkipMaxDown) { - Frame3d frSfr ; - Point3d ptCenter ; pSfr->GetCentroid( ptCenter) ; - if ( ! frSfr.Set( ptCenter, pSfr->GetNormVersor())) - return false ; - Frame3d frLvl0 = GetToLoc( frSfr, frSurf) ; - // riduco la regione sulla Silhouette corretta - pSfrSil_real.Set( GetSfrSilhouette( vSrfLoc, frLvl0, - dDepth)) ; - if ( IsNull( pSfrSil_real) || ! pSfrSil_real->IsValid()) { - m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; - return false ; - } - // intersezione - pSfrSil_real->Offset( - m_Params.m_dSideStep + 10 * EPS_SMALL, ICurve::OFF_FILLET) ; - if ( ! IsNull( pSfrSil_real) && pSfrSil_real->IsValid()) { - pSfrSil_real->Translate( dDepth * frLvl0.VersZ()) ; - if ( ! pSfrSpiral->Intersect( *pSfrSil_real)) - return false ; - } - } - // le curve di finitura spiral devono stare sul bordo della regione trovata - pSfrSpiral->Offset( m_Params.m_dSideStep, ICurve::OFF_FILLET) ; - // mi assicuro di non uscire dalla superficie originale - PtrOwner pSfrOverlap( pSfr->CreateOffsetSurf( m_Params.m_dOverlap, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrOverlap)) - return false ; - if ( ! IsNull( pSfrOverlap) && pSfrOverlap->IsValid()) { - pSfrOverlap->ToLoc( frSurf) ; - pSfrSpiral->Intersect( *pSfrOverlap) ; - } - else - pSfrSpiral->Clear() ; - if ( ! IsNull( pSfrSpiral) && pSfrSpiral->IsValid()) { - // imposto i lati chiusi - for ( int nCC = 0 ; nCC < pSfrSpiral->GetChunkCount() ; ++ nCC) { - for ( int nL = 0 ; nL < pSfrSpiral->GetLoopCount( nCC) ; ++ nL) { - for ( int nU = 0 ; nU < pSfrSpiral->GetLoopCurveCount( nCC, nL) ; ++ nU) - pSfrSpiral->SetCurveTempProp( nCC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ; - } - } - // lavorazione Spiral - ICRVCOMPOPOVECTOR vpCrvs ; - if ( ! CalcPocketing( pSfrSpiral, m_Params.m_dSideStep, 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5., - POCKET_SPIRALIN, false, false, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep, - m_Params.m_dLiTang, GetLeadInType(), vpCrvs)) { - m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ; - return false ; - } - // ciclo sui percorsi ricavati risultanti - double dProgCoeff = 1. / max( int( vpCrvs.size()), 1) ; - for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) { - // definisco un nuovo percorso (in locale) - vPaths.resize( vPaths.size() + 1) ; - vPaths.back().pCrvPath.Set( Release( vpCrvs[k])) ; - vPaths.back().nType = SURFFIN_SUB_SPIRALIN ; - // li correggo per non interferire con le superfici - if ( pCAvTlStm != nullptr) { - // approssimo la curva con una polilinea - PolyLine PL ; - if ( ! vPaths.back().pCrvPath->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) - return false ; - // eventuale aggiunta di punti per garantire max distanza - const double MIN_DIST = 1. ; - const double MAX_DIST = 50. ; - double dDist = Clamp( m_TParams.m_dDiam / 2, MIN_DIST, MAX_DIST) ; - if ( ! PL.AdjustForMaxSegmentLen( dDist)) - return false ; - // porto i dati geometrici in locale alle superfici - Vector3d vtAxL = vtTool ; - vtAxL.ToLoc( frSurf) ; - Vector3d vtMoveL = vtAxL ; - // traslo della lunghezza utensile diminuita dell'affondamento - PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ; - // eseguo CAv - if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox, ( k + 1) * dProgCoeff)) - return false ; - // contro-traslo della lunghezza utensile - PL.Translate( - vtAxL * m_TParams.m_dLen) ; - // elimino i punti allineati - PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ; - // creo una curva composita a partire dalla polilinea - PtrOwner< ICurveComposite> pCompo( CreateCurveComposite()) ; - if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) - return false ; - // sostituisco la vecchia curva con la nuova - vPaths.back().pCrvPath.Set( pCompo) ; - } - } - } - // porto tutti i percorsi nel frame globale - for ( int i = 0 ; i < int( vPaths.size()) ; ++ i) { - #if ENABLE_OPTIMAL_SOFT_DEBUG - int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPaths[i].pCrvPath->Clone()) ; - m_pGeomDB->SetMaterial( _n, RED) ; - #endif - vPaths[i].pCrvPath->ToGlob( frSurf) ; - } + // recupero le curve dalla regione Spiral + if ( ! CalcOptimalSpiralCurves( pSfrSpiral, pSfr, frSurf, vtTool, dDepth, pCAvTlStm, vPaths)) { + m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; + return false ; } // aggiorno la ProgressBar al 60% ExeProcessEvents( 60, 0) ; - #if ENABLE_OPTIMAL_SOFT_DEBUG - // disegno i percorsi per controllo - int ___a = int( vPaths.size()) ; - for ( int i = 0 ; i < int( vPaths.size()) ; ++ i) { - int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPaths[i].pCrvPath->Clone()) ; - m_pGeomDB->SetMaterial( _n, RED) ; - } - #endif - - // ----------------------- Lavorazione Zconst ------------------------------- - if ( ! IsNull( pSfrZConst) && pSfrZConst->IsValid()) { - // mi assicuro di non uscire dalla superficie originale - PtrOwner pSfrOverlap( pSfr->CreateOffsetSurf( m_Params.m_dOverlap + GetOffsR(), ICurve::OFF_FILLET)) ; - if ( ! IsNull( pSfrOverlap) && pSfrOverlap->IsValid()) { - if ( ! pSfrOverlap->ToLoc( frSurf) || ! pSfrZConst->Intersect( *pSfrOverlap)) - return false ; - // imposto i lati chiusi - for ( int nC = 0 ; nC < pSfrZConst->GetChunkCount() ; ++ nC) { - for ( int nL = 0 ; nL < pSfrZConst->GetLoopCount( nC) ; ++ nL) { - for ( int nU = 0 ; nU < pSfrZConst->GetLoopCurveCount( nC, nL) ; ++ nU) - pSfrZConst->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ; - } - } - // inizializzo la classe di calcolo delle silhouette - CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ; - // scorro le superfici - for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) { - // recupero la superficie TriMesh e se valida la memorizzo - const ISurfTriMesh* pStm = GetSurfTriMesh( vSrfLoc[i].Get()) ; - if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) - vpStm.emplace_back( pStm) ; - } - // definisco il frame della regione piana - Frame3d frSfr ; - Point3d ptC ; pSfrZConst->GetCentroid( ptC) ; - if ( ! frSfr.Set( ptC, pSfrZConst->GetNormVersor())) - return false ; - // inizializzo classe di calcolo per le curve a ZConst - PtrOwner pCavParSilh( CreateCAvParSilhouettesSurfTm()) ; - if ( IsNull( pCavParSilh) || - ! pCavParSilh->SetData( vpStm, frSfr, SILH_SAMPLING, m_TParams.m_dSideAng, m_TParams.m_dDiam, - m_TParams.m_dCornRad, m_TParams.m_dMaxMat, GetOffsR(), dDepth)) - return false ; - // recupero le curve singole definite dal bordo della Silhouette - vector vCrvCompo ; - if ( ! CalcZConstSilCrv( pCavParSilh, vSrfLoc, frSurf, pSfrZConst, vtTool, dDepth, vCrvCompo)) { - m_pMchMgr->SetLastError( 3126, "Error in SurfFinishing : Computing ZConst Curves failed") ; - return false ; - } - // se ho delle curve, allora unisco i percorsi trovati - if ( ! vCrvCompo.empty()) { - // collego tra loro le curve trovate - ICRVCOMPOPOVECTOR vCrv ; - if ( ! CreateZConstPaths( pCAvTlStm, frSurf, vCrvCompo, vtTool, pSfrZConst, dDepth, vCrv)) { - m_pMchMgr->SetLastError( 3127, "Error in SurfFinishing : Computing ZConst Paths failed") ; - return false ; - } - // aggiungo i percorsi trovati - for ( int i = 0 ; i < int( vCrv.size()) ; ++ i) { - #if ENABLE_OPTIMAL_SOFT_DEBUG - int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrv[i]->Clone()) ; - m_pGeomDB->SetMaterial( _n, GREEN) ; - #endif - vPaths.resize( vPaths.size() + 1) ; - vPaths.back().pCrvPath.Set( Release( vCrv[i])) ; - vPaths.back().nType = SURFFIN_SUB_ZIGZAG ; - // in globale - vPaths.back().pCrvPath->ToGlob( frSurf) ; - } - } - } + // recupero le curve dalla regione ZConst + if ( ! CalcOptimalZConstCurves( pSfrZConst, pSfr, frSurf, vtTool, dDepth, vSrfLoc, pCAvTlStm, vPaths)) { + m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; + return false ; } // aggiorno la ProgressBar all' 80% ExeProcessEvents( 80, 0) ; - #if ENABLE_OPTIMAL_SOFT_DEBUG - // disegno i percorsi per controllo - for ( int i = ___a ; i < int( vPaths.size()) ; ++ i) { - int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPaths[i].pCrvPath->Clone()) ; - m_pGeomDB->SetMaterial( _n, GREEN) ; - } - #endif - // ordino i percorsi in base alla Zlocale if ( ! OrderOptimalPathsByZLoc( pSfr, vPaths)) return false ; - // aggiorno la ProgressBar all' 80% + + // aggiorno la ProgressBar al 90% ExeProcessEvents( 90, 0) ; // aggiusto la regione a seconda dei parametri diff --git a/SurfFinishing.h b/SurfFinishing.h index 9bc5e32..91b697f 100644 --- a/SurfFinishing.h +++ b/SurfFinishing.h @@ -121,7 +121,7 @@ class SurfFinishing : public Machining bool CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket, const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, const Point3d ptStart_forced, const Point3d ptEnd_forced, - ICurveComposite* pCrv) ; + ICurveComposite* pCrv) const ; // lavorazioni per superfici bool AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs) ; @@ -160,18 +160,23 @@ class SurfFinishing : public Machining const Vector3d& vtTool, double dDepth, double dClippingAngle, double dTolerAngle, ISURFTMPOVECTOR& vpStm1, ISURFTMPOVECTOR& vpStm2, double& dMaxFrontTriaRad) const ; bool GetZConstQuotesInsideSfrParallelToTool( const SURFLOCALVECTOR&, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, - const Vector3d& vtTool, std::set& setZAmbiguos) ; + const Vector3d& vtTool, std::set& setZAmbiguos) const ; ISurfFlatRegion* GetSfrSilhouette( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frLvl0, double dDepth) const ; ISurfFlatRegion* GetSfrProjectedStmLoops( const ISURFTMPOVECTOR& vStm, const ISurfFlatRegion* pSfrContour, const DBLVECTOR& vdLinFeaTol, const DBLVECTOR& vdAngTol, const DBLVECTOR& vdMaxLinTol) const ; ISurfTriMesh* SplitStmTriaUnderClippingAngle( const SurfLocal SrfLoc, const Vector3d& vtTest, double dClippingAngle, double dFrontTriaTolerAng, double& dMaxFrontTriaRad) const ; + bool CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrZConst, const ISurfFlatRegion* pSfrCnt, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, + const SURFLOCALVECTOR& vSrfLoc, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const ; + bool CalcOptimalSpiralCurves( const ISurfFlatRegion* pSfrSpiral, const ISurfFlatRegion* pSfrCnt, const Frame3d& frSurf, + const Vector3d& vtTool, double dDepth, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const ; bool GetOptimalSfr( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfrLoc, const Vector3d& vtTool, double dDepth, double dElev, ISurfFlatRegion* pSfrSpiral, ISurfFlatRegion* pSfrZConst) const ; bool CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, - const ISurfFlatRegion* pSfrClass, const Vector3d& vtTool, double dDepth, std::vector& vCrvCompo) ; + const ISurfFlatRegion* pSfrClass, const Vector3d& vtTool, double dDepth, std::vector& vCrvCompo) const ; bool CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, std::vector& vCrvCompo, const Vector3d& vtTool, - const ISurfFlatRegion* pSfr, double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) ; + const ISurfFlatRegion* pSfr, double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) const ; bool AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; bool AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; bool AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; diff --git a/SurfRoughing.cpp b/SurfRoughing.cpp index de884be..167a226 100644 --- a/SurfRoughing.cpp +++ b/SurfRoughing.cpp @@ -2105,10 +2105,13 @@ SurfRoughing::GetStmOutSideSfr( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw == nullptr || ! pStmRaw->IsValid()) return nullptr ; + double dTol = 100 * EPS_SMALL ; + // creo una copia della pSfr mediante un piccolo offset correttivo (per problemi con archi) - PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( 100 * EPS_SMALL, ICurve::OFF_FILLET)) ; + PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( dTol, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) return nullptr ; + pSfrOffs->Translate( dTol * pSfr->GetNormVersor()) ; // definisco il vettore delle curve dei bordi della regione CICURVEPVECTOR vpCrv ; @@ -2126,13 +2129,31 @@ SurfRoughing::GetStmOutSideSfr( const ISurfFlatRegion* pSfr, const ISurfTriMesh* } } - // definisco la TrimMesh limite + // definisco la TrimMesh limite ( inizialmente come copia del grezzo) PtrOwner pStmLimit( CloneSurfTriMesh( pStmRaw)) ; bOk = bOk && ( ! IsNull( pStmLimit) && pStmLimit->IsValid()) ; + // tengo solo le parti di superficie che sono effettivamente vicine alla regione di sgrossatura + // box della superficie piana + BBox3d BBoxSfr ; + bOk = bOk && pSfrOffs->GetLocalBBox( BBoxSfr) ; + BBoxSfr.Expand( 0., 0., vtExtr.Len()) ; + // scorro le parts + for ( int nPart = 0 ; nPart < pStmLimit->GetPartCount() && bOk ; ++ nPart) { + // calcolo il box della part corrente + BBox3d BBoxPart ; + bOk = bOk && pStmLimit->GetPartLocalBBox( nPart, BBoxPart) ; + // se non c'è intersezione con i Box, elimino la parte corrente + BBox3d BBoxInt ; + if ( BBoxSfr.FindIntersection( BBoxPart, BBoxInt)) { + bOk = pStmLimit->RemovePart( nPart) ; + -- nPart ; + } + } + // definisco la superficie di estrusione if ( bOk) { - PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrv, vtExtr)) ; + PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrv, ( 1 + 2. * dTol) * vtExtr)) ; bOk = ( ! IsNull( pStmExtr) && pStmExtr->IsValid()) ; // la superficie deve definire un volume double dVol = 0. ;