diff --git a/SurfFinishing.cpp b/SurfFinishing.cpp index f067259..da45878 100644 --- a/SurfFinishing.cpp +++ b/SurfFinishing.cpp @@ -1670,6 +1670,15 @@ SurfFinishing::EraseMaxDownSurf( const SURFLOCALVECTOR& vSurfLoc, const Frame3d& pSfrSil->ToGlob( frSurf) ; double dPockRadOffs = SILH_ARC_TOL ; pSfrSil->Offset( dPockRadOffs, ICurve::OFF_CHAMFER) ; + pSfrSil->Offset( m_TParams.m_dDiam / 2., ICurve::OFF_FILLET) ; + #if DEBUG_SFR + int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; + m_pGeomDB->SetName( nGrp, "FlatRegions MaxDown") ; + int nLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetName( nLay, "SfrMaxDow") ; + int nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pSfrSil->Clone()) ; + m_pGeomDB->SetMaterial( nSfr, Color( 1., 0., 0., .5)) ; + #endif // intersezione tra contorno e regione if ( ! pSfrCnt->Intersect( *pSfrSil)) { // ricreo la regione originale @@ -1965,6 +1974,15 @@ SurfFinishing::ProcessSfr( int nPathId, int nPvId, int nClId) dDepth = dInvElev + dToolDepth ; } + // alla regione di contorno applico un Offset stabilito dal parametro di Overlap + if ( ! pSfrCnt->Offset( m_Params.m_dOverlap, ICurve::OFF_FILLET)) { + m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; + return false ; + } + // se non valida, non faccio nulla + if ( ! pSfrCnt->IsValid()) + return true ; + #if DEBUG_SFR int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; m_pGeomDB->SetName( nGrp, "FlatRegions") ; @@ -1987,15 +2005,6 @@ SurfFinishing::ProcessSfr( int nPathId, int nPvId, int nClId) return false ; } - // alla regione di contorno applico un Offset stabilito dal parametro di Overlap - if ( ! pSfrCnt->Offset( m_Params.m_dOverlap, ICurve::OFF_FILLET)) { - m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; - return false ; - } - // se non valida, non faccio nulla - if ( ! pSfrCnt->IsValid()) - return true ; - // tengo una copia della regione attuale, nel caso di finitura Optimal PtrOwner pSfrCntOrig( nullptr) ; if ( m_Params.m_nSubType == SURFFIN_SUB_OPTIMAL) { @@ -2623,7 +2632,7 @@ SurfFinishing::CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SU if ( IsNull( pCrvCompo)) return false ; // recupero le curve semplici e le inserisco nella curva composita - for ( size_t i = 0 ; i < vnInd.size() ; ++ i) { + for ( int i = 0 ; i < ssize( vnInd) ; ++ i) { int nId = abs( vnInd[i]) - 1 ; // la aggiungo alla curva composta if ( ! pCrvCompo->AddCurve( CloneCurveComposite( vCrvCompo.back()[nId]), true, dToler)) @@ -2648,8 +2657,8 @@ SurfFinishing::CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SU } // controllo la validità di tutte le curve trovate - for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { - for ( int j = 0 ; j < int( vCrvCompo[i].size()) ; ++ j) { + for ( int i = 0 ; i < ssize( vCrvCompo) ; ++ i) { + for ( int j = 0 ; j < ssize( vCrvCompo[i]) ; ++ j) { if ( vCrvCompo[i][j] == nullptr || ! vCrvCompo[i][j]->IsValid()) return false ; } @@ -5528,13 +5537,161 @@ SurfFinishing::CalcOptimalZigZagCurves( ISURFFRPOVECTOR& vSfrZigZagProj, const F return true ; } +//---------------------------------------------------------------------------- +bool +SurfFinishing::CalcOptimalZigZagSfrByZConstCrv( const ISurfFlatRegion* pSfrLoc, const CISURFTMPVECTOR& vpStm, const Vector3d& vtToolLoc, + double dExtraCollOffs, ICurveComposite* pCompoSil, ISurfFlatRegion* pSfrCollCompoSil) const +{ + // verifica dei parametri + if ( pSfrLoc == nullptr || ! pSfrLoc->IsValid() || + vpStm.empty() || + pCompoSil == nullptr || ! pCompoSil->IsValid() || + pSfrCollCompoSil == nullptr) + return false ; + + pSfrCollCompoSil->Clear() ; + + // definisco il frame della regione piana + Frame3d frSfr ; + Point3d ptC ; pSfrLoc->GetCentroid( ptC) ; + if ( ! frSfr.Set( ptC, pSfrLoc->GetNormVersor())) + return false ; + + // definisco il bordo della curva rappresentante la collisione + PtrOwner pCompoColl( CreateCurveComposite()) ; + if ( IsNull( pCompoColl)) + return false ; + bool bfirst = true ; + const double TOL_SAFE = Clamp( m_Params.m_dSideStep, 100. * EPS_SMALL, 1.0) ; // tolleranza per pareti verticali e per triangoli misti tra SplitAngle + double dRad = m_TParams.m_dDiam / 2. + TOL_SAFE ; + for ( int nCrv = 0 ; nCrv < pCompoSil->GetCurveCount() ; ++ nCrv) { + const ICurve* pCrv = pCompoSil->GetCurve( nCrv) ; + if ( pCrv == nullptr) + continue ; + // recupero il centro dell'utensile sferico sopra a tale curva + Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ; + Point3d ptSphereCenter = ptEnd + vtToolLoc * dRad ; + // recupero il punto a minima distanza ( quello che ha generato la collisione) + double dMinDist = INFINITO - 1 ; + Point3d ptMinDist = P_INVALID ; + Vector3d vtCollToCenter = V_INVALID ; + for ( int nSurf = 0 ; nSurf < ssize( vpStm) ; ++ nSurf) { + if ( vpStm[nSurf] != nullptr && vpStm[nSurf]->IsValid()) { + DistPointSurfTm distPtSurfTm( ptSphereCenter, *vpStm[nSurf]) ; + double dMyDist = INFINITO - 2 ; + if ( distPtSurfTm.GetDist( dMyDist) && dMyDist < dMinDist) { + dMinDist = dMyDist ; + distPtSurfTm.GetMinDistPoint( ptMinDist) ; + vtCollToCenter = ptSphereCenter - ptMinDist ; + vtCollToCenter.Normalize() ; + } + } + } + if ( ptMinDist.IsValid() && vtCollToCenter.IsValid()) { + Point3d ptColl = ptEnd - OrthoCompo( dRad * vtCollToCenter, vtToolLoc) ; + if ( bfirst) { + pCompoColl->AddPoint( ptColl) ; + bfirst = false ; + } + else + pCompoColl->AddLine( ptColl) ; + } + } + if ( pCompoSil->IsClosed()) + pCompoColl->Close() ; + + // abballisco le due curve smussandole + SimplifyCurve( pCompoSil, frSfr) ; + SimplifyCurve( pCompoColl, frSfr) ; + + #if 0 + int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoSil->Clone()) ; + m_pGeomDB->SetMaterial( a, FUCHSIA) ; + a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoColl->Clone()) ; + m_pGeomDB->SetMaterial( a, BLUE) ; + #endif + + // Se richiesto Offset Extra lo aggiungo alla curva di collisione + if ( abs( dExtraCollOffs) > 10. * EPS_SMALL) { + pCompoColl->SetExtrusion( vtToolLoc) ; + OffsetCurve OffsCrv ; + if ( OffsCrv.Make( pCompoColl, ( ! m_Params.m_bInvert ? dExtraCollOffs : - dExtraCollOffs), ICurve::OFF_FILLET)) { + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid()) { + pCompoColl->Clear() ; + pCompoColl->AddCurve( Release( pCrvOffs)) ; + } + } + } + + if ( pCompoSil->IsValid() && pCompoColl->IsValid()) { + if ( pCompoSil->IsClosed()) { + pSfrCollCompoSil->AddExtLoop( Release( pCompoColl)) ; + PtrOwner pCompoIsl( CloneCurveComposite( pCompoSil)) ; + if ( IsNull( pCompoIsl) || ! pCompoIsl->IsValid()) + return false ; + pCompoIsl->SetExtrusion( vtToolLoc) ; + double dOffset = ( ! m_Params.m_bInvert ? 1. : -1.) * dRad ; + OffsetCurve OffsCrv ; + OffsCrv.Make( pCompoIsl, dOffset, ICurve::OFF_FILLET) ; + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid()) + pSfrCollCompoSil->AddIntLoop( Release( pCrvOffs)) ; + else + pSfrCollCompoSil->AddIntLoop( Release( pCompoIsl)) ; + } + else { + PtrOwner pBorder( CloneCurveComposite( pCompoColl)) ; + if ( IsNull( pBorder) || ! pBorder->IsValid()) + return false ; + PtrOwner pNewCrvCompoInv( CloneCurveComposite( pCompoSil)) ; + if ( IsNull( pNewCrvCompoInv) || ! pNewCrvCompoInv->IsValid()) + return false ; + pNewCrvCompoInv->SetExtrusion( vtToolLoc) ; + double dOffset = ( ! m_Params.m_bInvert ? 1. : -1.) * dRad ; + OffsetCurve OffsCrv ; + OffsCrv.Make( pNewCrvCompoInv, dOffset, ICurve::OFF_FILLET) ; + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid()) + pNewCrvCompoInv.Set( Release( pCrvOffs)) ; + pNewCrvCompoInv->Invert() ; + Point3d ptCurr ; pBorder->GetEndPoint( ptCurr) ; + Vector3d vtCurr ; pBorder->GetEndDir( vtCurr) ; + Point3d ptEnd ; pNewCrvCompoInv->GetStartPoint( ptEnd) ; + PtrOwner pArc( CreateCurveArc()) ; pArc->Set2PVN( ptCurr, ptEnd, vtCurr, vtToolLoc) ; + pBorder->AddCurve( Release( pArc)) ; + pBorder->AddCurve( Release( pNewCrvCompoInv)) ; + pBorder->GetEndPoint( ptCurr) ; + pBorder->GetEndDir( vtCurr) ; + pBorder->GetStartPoint( ptEnd) ; + pArc.Set( CreateCurveArc()) ; pArc->Set2PVN( ptCurr, ptEnd, vtCurr, vtToolLoc) ; + pBorder->AddCurve( Release( pArc)) ; + pSfrCollCompoSil->AddExtLoop( Release( pBorder)) ; + } + } + + // per sicurezza oriento a prescindere la normale della superficie come vtToolLoc + if ( pSfrCollCompoSil->IsValid()) { + if ( AreOppositeVectorApprox( pSfrCollCompoSil->GetNormVersor(), vtToolLoc)) + pSfrCollCompoSil->Invert() ; + #if 0 + int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrCollCompoSil->Clone()) ; + m_pGeomDB->SetMaterial( a, Color( 255, 0, 0, 50)) ; + #endif + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const Vector3d& vtTool, double dAngDegSplit, double dAngDegTol, double dDepth, - ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const + ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths, ISurfFlatRegion* pSfrToolColl) const { // se la superficie non è valida, non restituisco nulla + if ( pSfrToolColl == nullptr) + return false ; if ( pSfrLoc == nullptr || ! pSfrLoc->IsValid()) return true ; @@ -5614,6 +5771,8 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU double dCosUpperBound = cos( ( dAngDegSplit - dAngDegTol) * DEGTORAD + EPS_ANG_SMALL) ; // --- classificazione punti e PolyLine corrispondenti enum { VALID = 0, AMBIGUOUS = 1, DISCARD = 2 } ; + // --- offset correttivo per regioni di collisione + const double dExtraOffs = m_TParams.m_dDiam / 2. ; #if ENABLE_OPTIMAL_DEBUG int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; @@ -5638,9 +5797,9 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU int nLayCrv = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; m_pGeomDB->SetName( nLayCrv, "Curves") ; m_pGeomDB->SetStatus( nLayCrv, GDB_ST_OFF) ; - int nLaySfrProj = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; - m_pGeomDB->SetName( nLaySfrProj, "SfrProj") ; - m_pGeomDB->SetStatus( nLaySfrProj, GDB_ST_OFF) ; + int nLaySfrColl = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetName( nLaySfrColl, "SfrColl") ; + m_pGeomDB->SetStatus( nLaySfrColl, GDB_ST_OFF) ; #endif // scorro i piani di ZConst ricavati... @@ -5829,16 +5988,24 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU // se vuota, non faccio nulla if ( PL.GetPointNbr() < 2) continue ; - // se PolyLine troppo corta, non la memorizzo ( < 1/4 circonferenza utensile) + // se PolyLine troppo corta, non la memorizzo double dLen = 0. ; PL.GetLength( dLen) ; - if ( dLen < ( PIGRECO / 2.) * ( m_TParams.m_dDiam / 2.)) + if ( dLen < MIN_DIST) continue ; - // definisco la curva e la abbellisco - PtrOwner pNewCrvCompo( CreateCurveComposite()) ; - if ( IsNull( pNewCrvCompo) || ! pNewCrvCompo->FromPolyLine( PL)) + // definisco la curva + PtrOwner pNewCompo( CreateCurveComposite()) ; + if ( IsNull( pNewCompo) || ! pNewCompo->FromPolyLine( PL)) continue ; - SimplifyCurve( pNewCrvCompo, frSfr) ; - vvCrvCompo[i].emplace_back( Release( pNewCrvCompo)) ; + // aggiorno la regione per il calcolo dello ZigZag ( la funzione abbellisce le curve) + PtrOwner pSfrColl( CreateSurfFlatRegion()) ; + CalcOptimalZigZagSfrByZConstCrv( pSfrLoc, vpStm, vtAxL, - dExtraOffs, pNewCompo, pSfrColl) ; + if ( ! IsNull( pSfrColl) && pSfrColl->IsValid()) { + if ( ! pSfrToolColl->IsValid()) + pSfrToolColl->CopyFrom( pSfrColl) ; + else + pSfrToolColl->Add( *pSfrColl) ; + } + vvCrvCompo[i].emplace_back( Release( pNewCompo)) ; // memorizzo come primo TempParam la distanza della superficie ( per coerenza) vvCrvCompo[i].back()->SetTempParam( dSfrDist, 0) ; #if ENABLE_OPTIMAL_DEBUG @@ -5848,6 +6015,17 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU } } + // la superficie complessiva di collisione viene limitata al bordo + if ( pSfrToolColl->IsValid()) { + pSfrToolColl->Offset( - dExtraOffs, ICurve::OFF_FILLET) ; + if ( pSfrToolColl->IsValid()) + pSfrToolColl->Intersect( *pSfrLoc) ; + #if ENABLE_OPTIMAL_DEBUG + int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySfrColl, pSfrToolColl->Clone()) ; + m_pGeomDB->SetMaterial( a, Color( 255, 0, 255, 50)) ; + #endif + } + // collego tra loro le curve trovate definendo quindi un percorso ICRVCOMPOPOVECTOR vCrv ; if ( ! CreateZConstPaths( pCAvTlStm, frSurf, vvCrvCompo, vtTool, pMySfrZConst, dDepth, vCrv)) { @@ -5947,156 +6125,37 @@ SurfFinishing::AreSameSfrChunkEpsilon( const ISurfFlatRegion* pSfrChunkA, const //---------------------------------------------------------------------------- bool -SurfFinishing::CalcOptimalZigZagRegion( const ISurfFlatRegion* pSfrCntLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, - const Vector3d& vtToolLoc, double dDepth, double dSplitAngDeg, ISURFFRPOVECTOR& vpSfrZigZagProj) const +SurfFinishing::CalcOptimalZigZagRegion( const ISurfFlatRegion* pSfrCntLoc, const ISurfFlatRegion* pSfrZLevelColl, + const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const Vector3d& vtToolLoc, double dDepth, + double dSplitAngDeg, ISURFFRPOVECTOR& vpSfrZigZagProj) const { // verifico validità dei parametri if ( pSfrCntLoc == nullptr || ! pSfrCntLoc->IsValid()) return false ; vpSfrZigZagProj.clear() ; - const double COS_SPLIT_ANG = cos( dSplitAngDeg * DEGTORAD) ; + // se non esiste una regione di ZLevelColl, quindi non esistono curve di Zlevel, tutta la superficie deve + // essere lavorata in ZigZag + if ( pSfrZLevelColl == nullptr || ! pSfrZLevelColl->IsValid()) + return ( vpSfrZigZagProj.emplace_back( CloneSurfFlatRegion( pSfrCntLoc))) ; - // scorro tutte le facce delle superfici presenti - CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ; - for ( const SurfLocal& SurfL : vSrfLoc) { - // recupero la superficie - const ISurf* pSurf = GetSurf( SurfL.Get()) ; - if ( pSurf == nullptr || ! pSurf->IsValid()) - continue ; - int nType = pSurf->GetType() ; - // se TriMesh - if ( nType == SRF_TRIMESH) { - const ISurfTriMesh* pStm = GetSurfTriMesh( pSurf) ; - if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) - vpStm.emplace_back( pStm) ; - } - // se Bezier - else if ( nType == SRF_BEZIER) { - const ISurfBezier* pSBz = GetSurfBezier( pSurf) ; - if ( pSBz != nullptr && pSBz->IsValid()) { - double dOldTol = GetSurfBezierAuxSurfRefinedTol() ; - SetSurfBezierAuxSurfRefinedTol( 5. * EPS_SMALL) ; - const ISurfTriMesh* pStm = pSBz->GetAuxSurfRefined() ; - SetSurfBezierAuxSurfRefinedTol( dOldTol) ; - if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) - vpStm.emplace_back( pStm) ; - } - } - } - - // Definisco una Zuppa di Triangoli per le facce entro la tolleranza - #if ENABLE_OPTIMAL_DEBUG - int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; - m_pGeomDB->SetName( nGrp, "SplitAngleSurf") ; - m_pGeomDB->SetStatus( nGrp, GDB_ST_OFF) ; - int nLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; - m_pGeomDB->SetName( nLay, "SplitAngleSurf") ; - #endif - StmFromTriangleSoup StmSoup ; - StmSoup.Start() ; - for ( const ISurfTriMesh* pStm : vpStm) { - if ( pStm == nullptr || ! pStm->IsValid()) - continue ; - // scorro le faccie della superficie e controllo l'angolo presente - for ( int nF = 0 ; nF < pStm->GetFacetCount() ; ++ nF) { - Vector3d vtFaceN ; pStm->GetFacetNormal( nF, vtFaceN) ; - #if ENABLE_OPTIMAL_DEBUG - int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, pStm->CloneFacet( nF)) ; - #endif - if ( vtFaceN * vtToolLoc > COS_SPLIT_ANG) { - #if ENABLE_OPTIMAL_DEBUG - m_pGeomDB->SetMaterial( nId, LIME) ; - #endif - INTVECTOR vnTria ; pStm->GetAllTriaInFacet( nF, vnTria) ; - for ( const int& nT : vnTria) { - Triangle3d Tria ; pStm->GetTriangle( nT, Tria) ; - StmSoup.AddTriangle( Tria) ; - } - } - else { - #if ENABLE_OPTIMAL_DEBUG - m_pGeomDB->SetMaterial( nId, BLACK) ; - #endif - } - } - } - StmSoup.End() ; - - // recupero i parametri per il calcolo delle regioni piane a ZigZag - Point3d ptTop ; pSfrCntLoc->GetCentroid( ptTop) ; - Frame3d frPlanes ; - if ( ! frPlanes.Set( ptTop, vtToolLoc)) + // separo ogni Chunk della regione a ZigZag (ognuno di essi verrà lavorato singolarmanete) + PtrOwner pSfrZigZag( CloneSurfFlatRegion( pSfrCntLoc)) ; + if ( IsNull( pSfrZigZag) || ! pSfrZigZag->IsValid()) return false ; - const double TOL_SIL = 1.0 ; - INTDBLVECTOR vSfrDistInd ; - - // Recupero le Superfici TriMesh - PtrOwner pStmZigZag( StmSoup.GetSurf()) ; - while ( ! IsNull( pStmZigZag)) { - if ( pStmZigZag->IsValid() && pStmZigZag->GetTriangleCount() > 0) { - // ogni Part della TriMesh a ZigZag diventa una FlatRegion - for ( int nP = 0 ; nP < pStmZigZag->GetPartCount() ; ++ nP) { - PtrOwner pStmZigZagPart( pStmZigZag->ClonePart( nP)) ; - if ( ! IsNull( pStmZigZagPart) && pStmZigZagPart->IsValid()) { - // recupero il Box della Parte corrente e determino la quota media ( controllo basilare, migliorabile) - BBox3d BBoxPart ; - pStmZigZagPart->GetLocalBBox( BBoxPart) ; - Point3d ptMid ; BBoxPart.GetCenter( ptMid) ; - // recupero le PolyLine di proiezione per la definizione del bordo - PtrOwner pCavParSilh( CreateCAvParSilhouettesSurfTm()) ; - if ( IsNull( pCavParSilh) || ! pCavParSilh->SetData( {pStmZigZagPart}, frPlanes, TOL_SIL)) - return false ; - POLYLINEVECTOR vPL ; - if ( ! pCavParSilh->GetSilhouette( - dDepth, vPL)) - return false ; - // inizializzo classe di calcolo per regione piana corrente mediante le PolyLine ricavate - SurfFlatRegionByContours SfrByC ; - for ( const PolyLine& PL : vPL) { - PtrOwner pCompoPL( CreateCurveComposite()) ; - if ( IsNull( pCompoPL) || ! pCompoPL->FromPolyLine( PL) || ! SfrByC.AddCurve( pCompoPL->Clone())) - return false ; - } - // Recupero le superfici piane e le memorizzo - PtrOwner pSfrProj( SfrByC.GetSurf()) ; - while ( ! IsNull( pSfrProj)) { - if ( pSfrProj->IsValid()) { - // porto la superficie in Globale - if ( AreOppositeVectorEpsilon( pSfrProj->GetNormVersor(), vtToolLoc, 20. * EPS_SMALL)) - pSfrProj->Invert() ; - // limito questa regione all'intersezione con la superficie di Contorno - if ( ! pSfrProj->Intersect( *pSfrCntLoc)) - return false ; - if ( pSfrProj->IsValid()) { - // verifico che non ci siano delle superfici duplicate - bool bDuplicate = false ; - for ( int i = 0 ; ! bDuplicate && i < ssize( vpSfrZigZagProj) ; ++ i) - bDuplicate = AreSameSfrChunkEpsilon( pSfrProj, vpSfrZigZagProj[i], m_TParams.m_dDiam / 4.) ; - if ( ! bDuplicate) { - vpSfrZigZagProj.emplace_back( Release( pSfrProj)) ; - vSfrDistInd.emplace_back( make_pair( ssize( vpSfrZigZagProj) - 1, abs( ( ptMid - ptTop) * vtToolLoc))) ; - } - } - } - pSfrProj.Set( SfrByC.GetSurf()) ; - } - } + if ( ! pSfrZigZag->Subtract( *pSfrZLevelColl)) + return false ; + if ( pSfrZigZag->IsValid()) { + for ( int nC = 0 ; nC < pSfrZigZag->GetChunkCount() ; ++ nC) { + PtrOwner pSfrZigZagChunk( pSfrZigZag->CloneChunk( nC)) ; + if ( ! IsNull( pSfrZigZagChunk) && pSfrZigZagChunk->IsValid()) { + // verifico che il Chunk non sia troppo "snello" + double dMaxOffs = 0. ; + pSfrZigZagChunk->GetMaxOffset( dMaxOffs) ; + if ( dMaxOffs > m_TParams.m_dDiam / 2. - 2. * EPS_SMALL) + vpSfrZigZagProj.emplace_back( Release( pSfrZigZagChunk)) ; } } - pStmZigZag.Set( StmSoup.GetSurf()) ; - } - if ( ssize( vpSfrZigZagProj) < 2) - return true ; - - // ordino le superfici ottenute in base alla distanza con la Superficie di contorno ( riferita alla Part di TriMesh) - ranges::sort( vSfrDistInd, {}, &pair::second) ; - for ( int i = 0 ; i < ssize( vSfrDistInd) ; ++ i) { - int nCurrI = i ; - while ( vSfrDistInd[nCurrI].first != nCurrI) { - int nNextI = vSfrDistInd[nCurrI].first ; - swap( vpSfrZigZagProj[nCurrI], vpSfrZigZagProj[nNextI]) ; - swap( vSfrDistInd[nCurrI], vSfrDistInd[nNextI]) ; - } } return true ; @@ -6108,9 +6167,6 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr const ISurfFlatRegion* pSfrCnt, const ISurfFlatRegion* pSfrCntExt, const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs) { - // vettore dei percorsi da calcolare - VECTORPATHS vPaths ; - // se entrambe le regioni non sono valide, non faccio nulla if ( ( pSfrCnt == nullptr || ! pSfrCnt->IsValid()) && ( pSfrCntExt == nullptr || ! pSfrCntExt->IsValid())) return false ; @@ -6125,18 +6181,21 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr return false ; // --- [1°] calcolo delle curve ZLevel e [2°] definizione della regione di proiezione per Zlevel --- - PtrOwner pSfrCntZLevel( pSfrCntLoc->CreateOffsetSurf( - m_TParams.m_dDiam / 2. + EPS_SMALL, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrCntZLevel)) + PtrOwner pSfrCntLimit( pSfrCntLoc->CreateOffsetSurf( - m_TParams.m_dDiam / 2. + EPS_SMALL, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrCntLimit)) return false ; // calcolo tutte le curve a ZLevel e determino la regione rimossa da queste curve - if ( ! CalcOptimalZConstCurves( pSfrCntZLevel, vSrfLoc, frSurf, vtTool, dAngDegSplit, dAngDegTol, dDepth, pCAvTlStm, vPaths)) { + VECTORPATHS vPaths ; + PtrOwner pSfrZLevelColl( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrZLevelColl) || + ! CalcOptimalZConstCurves( pSfrCntLimit, vSrfLoc, frSurf, vtTool, dAngDegSplit, dAngDegTol, dDepth, pCAvTlStm, vPaths, pSfrZLevelColl)) { m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; return false ; } // [3°] calcolo della regione di proiezione ZigZag --- ISURFFRPOVECTOR vSfrZigZagProj ; - if ( ! CalcOptimalZigZagRegion( pSfrCntZLevel, vSrfLoc, frSurf, GetToLoc( vtTool, frSurf), dDepth, dAngDegSplit, vSfrZigZagProj)) { + if ( ! CalcOptimalZigZagRegion( pSfrCntLimit, pSfrZLevelColl, vSrfLoc, frSurf, GetToLoc( vtTool, frSurf), dDepth, dAngDegSplit, vSfrZigZagProj)) { m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; return false ; } @@ -6148,8 +6207,6 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr return false ; } } - - // se non ho percorsi, non faccio nulla if ( vPaths.empty()) return true ; diff --git a/SurfFinishing.h b/SurfFinishing.h index 9ff555a..bd9a39f 100644 --- a/SurfFinishing.h +++ b/SurfFinishing.h @@ -178,7 +178,10 @@ class SurfFinishing : public Machining double dFrontTriaTolerAng, double& dMaxFrontTriaRad) const ; bool CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const Vector3d& vtTool, double dAngDegSplit, - double dAngDegTol, double dDepth, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const ; + double dAngDegTol, double dDepth, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths, + ISurfFlatRegion* pSfrToolColl) const ; + bool CalcOptimalZigZagSfrByZConstCrv( const ISurfFlatRegion* pSfrLoc, const CISURFTMPVECTOR& vpStm, const Vector3d& vtToolLoc, + double dExtraCollOffs, ICurveComposite* pCompoSil, ISurfFlatRegion* pSfrZigZag) const ; bool CalcOptimalZigZagCurves( ISURFFRPOVECTOR& vSfrZigZagProj, 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, @@ -215,8 +218,8 @@ class SurfFinishing : public Machining double dLimInfClippingAng, double dLimSupClippingAng, const Vector3d& vtAxL, const Vector3d& vtMoveL, ICAvToolSurfTm* pCAvTlStm, ICRVCOMPOPOVECTOR& vCrvCompo) const ; bool AreSameSfrChunkEpsilon( const ISurfFlatRegion* pSfrChunkA, const ISurfFlatRegion* pSfrChunkB, double dMaxDist) const ; - bool CalcOptimalZigZagRegion( const ISurfFlatRegion* pSfrCntLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, - const Vector3d& vtTool, double dDepth, double dSplitAngDeg, ISURFFRPOVECTOR& vpSfrZigZagProj) const ; + bool CalcOptimalZigZagRegion( const ISurfFlatRegion* pSfrCntLoc, const ISurfFlatRegion* pSfrZLevelColl, const SURFLOCALVECTOR& vSrfLoc, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, double dSplitAngDeg, ISURFFRPOVECTOR& vpSfrZigZagProj) const ; double GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) const ; double GetRadiusForStartEndElevation( void) const ;