diff --git a/OperUserNotesConst.h b/OperUserNotesConst.h index 2810d63..a23af35 100644 --- a/OperUserNotesConst.h +++ b/OperUserNotesConst.h @@ -56,6 +56,8 @@ static const std::string UN_MINFEED = "MinFeed" ; static const std::string UN_TOOL_COMPENSATION = "ToolCompensation" ; static const std::string UN_START_PNT = "StartPoint" ; static const std::string UN_LIMIT_PLANE_ID = "LimitPlaneId" ; +static const std::string UN_LIMIT_TAB_DIST = "LimitTab" ; +static const std::string UN_CLOSED_EDGES = "Closed" ; // Solo per Sawing static const std::string UN_DOWNSE = "DownSE" ; diff --git a/PocketingNT.cpp b/PocketingNT.cpp index f1b52d8..bf8ecfc 100644 --- a/PocketingNT.cpp +++ b/PocketingNT.cpp @@ -151,6 +151,9 @@ static double FEED_MAX_COEFF = 1000. ; int nGrpDebugFeed = GDB_ID_NULL, nLayDebugFeed = GDB_ID_NULL ; #endif +// Utility +#define USE_PROGRESS_BAR 0 + //---------------------------------------------------------------------------- // USEROBJ_REGISTER( GetOperationClass( OPER_POCKETING), PocketingNT) ; @@ -1244,8 +1247,8 @@ PocketingNT::VerifyGeometry( SelData Id, int& nSubs, int& nType) //---------------------------------------------------------------------------- bool -PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, - ICURVEPLIST& lstPC) +PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, int nFacet, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, + const INTVECTOR& vIndCloseEdgesByUS, ICURVEPLIST& lstPC) const { // controllo dei parametri if ( pSurf == nullptr || ! pSurf->IsValid()) @@ -1253,23 +1256,22 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d if ( lstPC.empty()) return true ; // le curve devono essere tutte valide - for ( auto& pCrv : lstPC) { + for ( ICurve*& pCrv : lstPC) { if ( pCrv == nullptr || ! pCrv->IsValid()) return false ; } // trasformo la lista di curve in curve composite ICRVCOMPOPOVECTOR vCrvCompo ; vCrvCompo.reserve( lstPC.size()) ; - for ( auto& pCrv : lstPC) { + for ( ICurve*& pCrv : lstPC) { PtrOwner pCrvCompo( ConvertCurveToComposite( pCrv->Clone())) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->IsValid() || ! vCrvCompo.emplace_back( Release( pCrvCompo))) return false ; } - // se non ho isole e non esistono lati aperti, non faccio nulla - // Le isole chiuse necessitano di essere estruse - if ( int( vCrvCompo.size()) == 1) { + // se non ho isole e non esistono lati aperti, non faccio nulla, le isole chiuse necessitano di essere estruse + if ( ssize( vCrvCompo) == 1) { bool bSomeOpen = false ; for ( int i = 0 ; i < vCrvCompo.back()->GetCurveCount() && ! bSomeOpen ; ++ i) { bSomeOpen = ( vCrvCompo.back()->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) ; @@ -1282,17 +1284,16 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d // controllo se esistono lati aperti interni alla superficie di Trim, in caso positivo, non faccio nulla const double TOL_PT_INSIDE_STM = 3. ; - for ( auto& pCrvCompo : vCrvCompo) { + for ( PtrOwner& pCrvCompo : vCrvCompo) { // recupero i tratti omogenei ICRVCOMPOPOVECTOR vpCrvs ; GetHomogeneousParts( pCrvCompo, vpCrvs) ; // scorro i tratti alla ricerca di lati aperti - for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i) { if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { // analizzo le sottocurve del tratto for ( int j = 0 ; j < vpCrvs[i]->GetCurveCount() ; ++ j) { - // per ogni sottocurva considero punto iniziale, finale e medio per campionarla - // ( si potrebbe in futuro campionare in maniera più fitta ) + // per ogni sottocurva considero punto iniziale, finale e medio per campionarla (si potrebbe campionare in maniera più fitta) PNTVECTOR vPt( 3, P_INVALID) ; vpCrvs[i]->GetCurve( j)->GetStartPoint( vPt[0]) ; vpCrvs[i]->GetCurve( j)->GetMidPoint( vPt[1]) ; @@ -1300,29 +1301,78 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d // classifico tali punti rispetto alla superficie bool bOpenEdgeInStm = false ; double dDist = 0. ; - for ( int nPt = 0 ; nPt < int( vPt.size()) && ! bOpenEdgeInStm ; ++ nPt) { + for ( int nPt = 0 ; nPt < ssize( vPt) && ! bOpenEdgeInStm ; ++ nPt) { DistPointSurfTm DistPtStm( vPt[nPt], *pStmTrim) ; bOpenEdgeInStm = ( DistPtStm.IsPointInside() && DistPtStm.GetDist( dDist) && dDist > TOL_PT_INSIDE_STM) ; } if ( bOpenEdgeInStm) - return true ; // !!! molto restrittivo, bisogna capire cosa fare... + return true ; // (molto restrittivo) } } } } // recupero il volume di svuotatura - PtrOwner pStmRawCl( CloneSurfTriMesh( pStmTrim)) ; - PtrOwner pStmVol( CloneSurfTriMesh( pStmTrim)) ; - PtrOwner pSurfGlob( CloneSurfTriMesh( pSurf)) ; + PtrOwner pStmRawCl( CloneSurfTriMesh( pStmTrim)), + pStmVol( CloneSurfTriMesh( pStmTrim)), + pSurfGlob( CloneSurfTriMesh( pSurf)) ; if ( IsNull( pStmRawCl) || ! pStmRawCl->IsValid() || IsNull( pStmVol) || ! pStmVol->IsValid() || IsNull( pSurfGlob) || ! pSurfGlob->IsValid() || ! pSurfGlob->ToGlob( frGlob) || ! pStmVol->Subtract( *pSurfGlob)) return false ; + // modifico il volume se la geometria presenta dei lati chiusi forzati + ISURFFRPOVECTOR vSfrForcedClosedEdges ; + if ( ! vIndCloseEdgesByUS.empty() && lstPC.front() != nullptr && lstPC.front()->IsValid()) { + // converto la curva singola (assunzione) in composita + PtrOwner pCompo( ConvertCurveToComposite( lstPC.front()->Clone())) ; + if ( ! IsNull( pCompo)) { + // recupero la normale della faccia (serve per estrusione della curva) + Vector3d vtFaceN ; + if ( ! pSurf->GetFacetNormal( nFacet, vtFaceN)) + return false ; + vtFaceN.ToGlob( frGlob) ; + const double MAX_EXTRUSION = 1e4 ; + // recupero i lati forzati chiusi + for ( int nInd : vIndCloseEdgesByUS) { + const ICurve* pCrvForcedClose = pCompo->GetCurve( nInd) ; // tratto lineare (deriva da trimesh) + if ( pCrvForcedClose != nullptr && pCrvForcedClose->IsValid()) { + PtrOwner pMyCrvForcedClose( pCrvForcedClose->Clone()) ; // tratto lineare (deriva da trimesh) + if ( IsNull( pMyCrvForcedClose)) + return false ; + pMyCrvForcedClose->SetExtrusion( vtFaceN) ; + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pMyCrvForcedClose, MAX_EXTRUSION / 2., ICurve::OFF_EXTEND)) + return false ; + PtrOwner pCrvOff( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOff)) + return false ; + // composizione del perimetro (4 lati) + pCrvOff->Invert() ; + Point3d ptLink ; pCrvOff->GetStartPoint( ptLink) ; + PtrOwner pCompoPerimeter( CreateCurveComposite()) ; + if ( IsNull( pCompoPerimeter)) + return false ; + pCompoPerimeter->AddCurve( Release( pMyCrvForcedClose)) ; + pCompoPerimeter->AddLine( ptLink) ; + pCompoPerimeter->AddCurve( Release( pCrvOff)) ; + pCompoPerimeter->Close() ; + // aggiornamento regione limite dei lati aperti orzati come chiusi + PtrOwner pSfr( CreateSurfFlatRegion()) ; + if ( pSfr->AddExtLoop( Release( pCompoPerimeter)) && pSfr->IsValid()) { + if ( AreOppositeVectorApprox( vtFaceN, pSfr->GetNormVersor())) + pSfr->Invert() ; + vSfrForcedClosedEdges.emplace_back( Release( pSfr)) ; + } + } + } + } + } + + #if DEBUG_STM_TOPOLOGY int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; m_pGeomDB->SetName( nGrp, "StmFaceTopology") ; @@ -1331,6 +1381,9 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d m_pGeomDB->SetName( nStmLay, "Stm") ; int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nStmLay, pSurfGlob->Clone()) ; m_pGeomDB->SetMaterial( nId, TEAL) ; + int nCLForcedCloseEdgesLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetMaterial( nCLForcedCloseEdgesLay, RED) ; + m_pGeomDB->SetName( nCLForcedCloseEdgesLay, "Forced US Closes") ; int nClISlLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; m_pGeomDB->SetName( nClISlLay, "Closed_Isl") ; int nRawLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; @@ -1343,12 +1396,12 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d m_pGeomDB->SetName( nCrvLay, "Result") ; #endif - // le isole sono considerate estese fino al grezzo; creo dei solidi di estrusione per le isole chiuse + // le isole sono considerate esruse fino al grezzo; creo dei solidi di estrusione per le isole chiuse if ( ssize( vCrvCompo) > 1) { - Vector3d vtN ; lstPC.back()->GetExtrusion( vtN) ; + Vector3d vtN ; vCrvCompo.front()->GetExtrusion( vtN) ; const double EXTR_LEN = 1000. ; SurfFlatRegionByContours SfrByC ; - for ( auto& pCrvCompo : vCrvCompo) { + for ( PtrOwner& pCrvCompo : vCrvCompo) { if ( ! SfrByC.AddCurve( CloneCurveComposite( pCrvCompo))) return false ; } @@ -1367,7 +1420,7 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d pCrvLoop->Translate( - EXTR_LEN / 2. * vtN) ; pCrvLoop->SetExtrusion( vtN) ; OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCrvLoop, 10 * EPS_SMALL, ICurve::OFF_FILLET) || + if ( ! OffsCrv.Make( pCrvLoop, 10. * EPS_SMALL, ICurve::OFF_FILLET) || ! pCrvLoop.Set( OffsCrv.GetLongerCurve())) return false ; PtrOwner pStmExtr( GetSurfTriMeshByExtrusion( pCrvLoop, EXTR_LEN * vtN, true)) ; @@ -1379,8 +1432,6 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d int nIslId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nClISlLay, CloneSurfTriMesh( pStmExtr)) ; m_pGeomDB->SetMaterial( nIslId, BLACK) ; #endif - if ( ! pStmVol->Subtract( *pStmExtr)) - return false ; } } } @@ -1391,6 +1442,10 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d #if DEBUG_STM_TOPOLOGY nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nVolLay, pStmVol->Clone()) ; m_pGeomDB->SetMaterial( nId, GREEN) ; + if ( ! vSfrForcedClosedEdges.empty()) { + for ( const ISurfFlatRegion* pSfrForcedClosedEdges : vSfrForcedClosedEdges) + m_pGeomDB->AddGeoObj( GDB_ID_NULL, nCLForcedCloseEdgesLay, pSfrForcedClosedEdges->Clone()) ; + } #endif // se volume non chiuso, errore @@ -1420,10 +1475,10 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d Plane3d plProj ; if ( ! plProj.Set( ptC, vtN)) return false ; - POLYLINEVECTOR vPLVol, vPLRaw ; - if ( ! pStmVol->GetSilhouette( plProj, 20 * EPS_SMALL, vPLVol, false, EPS_SMALL)) + POLYLINEVECTOR vPLVol, vPLRaw, vPLForcedClosedEdges ; + if ( ! pStmVol->GetSilhouette( plProj, 20. * EPS_SMALL, vPLVol, false, EPS_SMALL)) return false ; - if ( ! pStmRawCl->GetSilhouette( plProj, 20 * EPS_SMALL, vPLRaw, false, EPS_SMALL)) + if ( ! pStmRawCl->GetSilhouette( plProj, 20. * EPS_SMALL, vPLRaw, false, EPS_SMALL)) return false ; #if DEBUG_STM_TOPOLOGY @@ -1433,28 +1488,35 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d m_pGeomDB->SetMaterial( nId, LIME) ; #endif - // recupero le due superfici piane + // recupero le superfici piane SurfFlatRegionByContours SfrBCVol, SfrBCRaw ; - for ( PolyLine& PL : vPLVol) { + for ( const PolyLine& PL : vPLVol) { PtrOwner pCompo( CreateCurveComposite()) ; if ( ! IsNull( pCompo) && pCompo->FromPolyLine( PL)) SfrBCVol.AddCurve( Release( pCompo)) ; } - for ( PolyLine& PL : vPLRaw) { + for ( const PolyLine& PL : vPLRaw) { PtrOwner pCompo( CreateCurveComposite()) ; if ( ! IsNull( pCompo) && pCompo->FromPolyLine( PL)) SfrBCRaw.AddCurve( Release( pCompo)) ; } - PtrOwner pSfrVol( SfrBCVol.GetSurf()) ; - PtrOwner pSfrRaw( SfrBCRaw.GetSurf()) ; - if ( IsNull( pSfrVol) || IsNull( pSfrRaw) || - ! pSfrVol->IsValid() || ! pSfrRaw->IsValid()) + PtrOwner pSfrVol( SfrBCVol.GetSurf()), + pSfrRaw( SfrBCRaw.GetSurf()) ; + if ( IsNull( pSfrVol) || IsNull( pSfrRaw) || ! pSfrVol->IsValid() || ! pSfrRaw->IsValid()) return false ; if ( AreOppositeVectorApprox( vtN, pSfrVol->GetNormVersor())) pSfrVol->Invert() ; if ( AreOppositeVectorApprox( vtN, pSfrRaw->GetNormVersor())) pSfrRaw->Invert() ; + // --- se presenza di lati chiusi forzati, allora sottraggo la rispettiva regione limite + for ( const ISurfFlatRegion* pSfrForcedClosedEdges : vSfrForcedClosedEdges) { + if ( AreOppositeVectorApprox( vtN, pSfrForcedClosedEdges->GetNormVersor())) + pSfrRaw->Invert() ; + pSfrVol->Subtract( *pSfrForcedClosedEdges) ; + pSfrRaw->Subtract( *pSfrForcedClosedEdges) ; + } + #if DEBUG_STM_TOPOLOGY nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawLay, pSfrRaw->Clone()) ; m_pGeomDB->SetMaterial( nId, BLUE) ; @@ -1463,23 +1525,21 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d #endif // se la nuova superficie ricavata contiene un tratto chiuso, allora non faccio nulla - // ( Esempio di una tasca inclinata con gradini ) + // (Esempio di una tasca inclinata con gradini) const double OFFSET_FOR_CLOSE = 1. ; // euristico - PtrOwner pSfrVol_Clone( pSfrVol->CreateOffsetSurf( - OFFSET_FOR_CLOSE, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrVol_Clone)) + PtrOwner pSfrVolCL( pSfrVol->CreateOffsetSurf( - OFFSET_FOR_CLOSE, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrVolCL)) return false ; - for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCrvCompo) ; ++ i) { ICRVCOMPOPOVECTOR vpCrvs ; GetHomogeneousParts( vCrvCompo[i], vpCrvs) ; - for ( int j = 0 ; j < int( vpCrvs.size()) ; ++ j) { + for ( int j = 0 ; j < ssize( vpCrvs) ; ++ j) { if ( vpCrvs[j]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) { CRVCVECTOR ccClass ; - if ( pSfrVol_Clone->GetCurveClassification( *vpCrvs[j], EPS_SMALL, ccClass)) { - for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) { - if ( ccClass[k].nClass != CRVC_OUT) { - // non estendo la superficie in quanto rovina il grezzo adiacente ad un chiuso - return true ; - } + if ( pSfrVolCL->GetCurveClassification( *vpCrvs[j], EPS_SMALL, ccClass)) { + for ( int k = 0 ; k < ssize( ccClass) ; ++ k) { + if ( ccClass[k].nClass != CRVC_OUT) + return true ; // non estendo la superficie in quanto rovina il grezzo adiacente ad un chiuso } } else @@ -1488,12 +1548,39 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d } } - // definisco i lati aperti della nuova regione da svuotare - // --- i lati aperti sono quelli in comune con la proiezione del grezzo - for ( auto& pCrv : lstPC) + // definisco i lati aperti della nuova regione da svuotare (i lati aperti sono quelli in comune con la proiezione del grezzo) + for ( ICurve*& pCrv : lstPC) delete( pCrv) ; lstPC.clear() ; - pSfrRaw->Offset( - 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + + pSfrRaw->Offset( - 50. * EPS_SMALL, ICurve::OFF_FILLET) ; // per tolleranza + + PNTMATRIX matPtForcedClosed ; // punti di campionamento per le curve di lato chiuso forzato + for ( const ISurfFlatRegion* pSfrForcedClosedEdges : vSfrForcedClosedEdges) { + PtrOwner pCompoForcedClosedEdges( ConvertCurveToComposite( pSfrForcedClosedEdges->GetLoop( 0, 0))) ; + if ( IsNull( pCompoForcedClosedEdges)) + return false ; + matPtForcedClosed.emplace_back( PNTVECTOR{}) ; + for ( int i = 0 ; i < pCompoForcedClosedEdges->GetCurveCount() ; ++ i) { + const ICurve* pCrv = pCompoForcedClosedEdges->GetCurve( i) ; + if ( pCrv != nullptr && pCrv->IsValid()) { + Point3d ptStart ; pCrv->GetStartPoint( ptStart) ; + Point3d ptMid ; pCrv->GetMidPoint( ptMid) ; + #if DEBUG_STM_TOPOLOGY + PtrOwner ptGeo( CreateGeoPoint3d()) ; ptGeo->Set( ptStart) ; + int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nCLForcedCloseEdgesLay, ptGeo->Clone()) ; + m_pGeomDB->SetMaterial( nId, ORANGE) ; + ptGeo->Set( ptMid) ; + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nCLForcedCloseEdgesLay, ptGeo->Clone()) ; + m_pGeomDB->SetMaterial( nId, ORANGE) ; + #endif + matPtForcedClosed.back().push_back( ptStart) ; matPtForcedClosed.back().push_back( ptMid) ; + if ( i == pCompoForcedClosedEdges->GetCurveCount() - 1) + matPtForcedClosed.back().push_back( matPtForcedClosed.back().front()) ; + } + } + } + for ( int nC = 0 ; nC < pSfrVol->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfrVol->GetLoopCount( nC) ; ++ nL) { // recupero il Loop @@ -1505,15 +1592,36 @@ PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d pCompoLoop->GetCurve( nU)->GetStartPoint( vPt[0]) ; pCompoLoop->GetCurve( nU)->GetMidPoint( vPt[1]) ; pCompoLoop->GetCurve( nU)->GetEndPoint( vPt[2]) ; + bool bIsClosed = false ; pCompoLoop->SetCurveTempProp( nU, TEMP_PROP_OPEN_EDGE, 0) ; - for ( int nPt = 0 ; nPt < int( vPt.size()) ; ++ nPt) { + for ( int nPt = 0 ; nPt < ssize( vPt) ; ++ nPt) { bool bIsInside = true ; IsPointInsideSurfFr( vPt[nPt], pSfrRaw, EPS_SMALL, bIsInside) ; if ( bIsInside) { + bIsClosed = true ; pCompoLoop->SetCurveTempProp( nU, TEMP_PROP_CLOSE_EDGE, 0) ; break ; } } + // se il tratto è aperto, controllo anche le regioni di forzatura dei chiusi mediante user notes + if ( ! matPtForcedClosed.empty() && ! bIsClosed) { + const ICurve* pCrv = pCompoLoop->GetCurve( nU) ; + if ( pCrv == nullptr || ! pCrv->IsValid()) + return false ; + for ( int i = 0 ; i < ssize( matPtForcedClosed) ; ++ i) { + for ( int nPt = 0 ; nPt < ssize( matPtForcedClosed[i]) - 2 ; nPt += 2) { + const Point3d& ptStart = matPtForcedClosed[i][nPt] ; + const Point3d& ptMid = matPtForcedClosed[i][nPt + 1] ; + const Point3d& ptEnd = matPtForcedClosed[i][nPt + 2] ; + if ( pCrv->IsPointOn( ptStart, 40. * EPS_SMALL) && + pCrv->IsPointOn( ptMid, 40. * EPS_SMALL) && + pCrv->IsPointOn( ptEnd, 40. * EPS_SMALL)) { + pCompoLoop->SetCurveTempProp( nU, TEMP_PROP_CLOSE_EDGE, 0) ; + break ; + } + } + } + } } #if DEBUG_STM_TOPOLOGY @@ -1637,6 +1745,7 @@ PocketingNT::GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const IS return false ; // per ogni loop recupero le curve composite ICURVEPLIST lstCrvLoops ; + INTVECTOR vIndCloseEdgesByUS ; // indice lati chiusi forzati da note utente for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { PtrOwner pCrvCompo( CreateCurveComposite()) ; pCrvCompo->FromPolyLine( vPL[i]) ; @@ -1678,6 +1787,21 @@ PocketingNT::GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const IS pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; // la porto in globale pCrvCompo->ToGlob( frGlob) ; + // verifico se devo chiudere eventuali lati mediante note utente + if ( lstCrvLoops.empty()) { + if ( GetValInNotes( m_Params.m_sUserNotes, UN_CLOSED_EDGES, vIndCloseEdgesByUS) && ! vIndCloseEdgesByUS.empty()) { + INTVECTOR vInds ; vInds.reserve( vIndCloseEdgesByUS.size()) ; + for ( int nInd : vIndCloseEdgesByUS) { + // verifico che il lato sia effettivamente aperto + int nTmpProp = TEMP_PROP_INVALID ; pCrvCompo->GetCurveTempProp( nInd, nTmpProp, 0) ; + if ( nTmpProp == TEMP_PROP_OPEN_EDGE) { + pCrvCompo->SetCurveTempProp( nInd, TEMP_PROP_CLOSE_EDGE) ; + vInds.push_back( nInd) ; + } + } + swap( vInds, vIndCloseEdgesByUS) ; + } + } // sistemazioni varie AdjustCurveFromSurf( pCrvCompo, TOOL_ORTHO, FACE_CONT, V_NULL, {}, 0) ; // la restituisco @@ -1686,8 +1810,8 @@ PocketingNT::GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const IS lstCrvLoops.emplace_back( Release( pCrvCompo)) ; } // aggiusto la topologia della faccia - AdjustCurvesByStmTopology( pSurf, frGlob, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), lstCrvLoops) ; - for ( auto& pCrv : lstCrvLoops) + AdjustCurvesByStmTopology( pSurf, nFacet, frGlob, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), vIndCloseEdgesByUS, lstCrvLoops) ; + for ( ICurve*& pCrv : lstCrvLoops) lstPC.emplace_back( pCrv) ; return true ; } @@ -1870,6 +1994,7 @@ PocketingNT::Chain( int nGrpDestId) vInds.emplace_back( Id) ; } } + // preparo i dati per il concatenamento bool bFirst = true ; Point3d ptNear = ORIG ; @@ -2432,63 +2557,80 @@ PocketingNT::GetLimitPlane( const Vector3d& vtTool, const ISurfTriMesh* pStmRaw) return Plane3d() ; // recupero dalle note utenti il piano - int nGeoPlaneId = GDB_ID_NULL ; - if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_LIMIT_PLANE_ID, nGeoPlaneId) || nGeoPlaneId == GDB_ID_NULL) - return Plane3d() ; - - // recupero l'oggetto geometrico e il suo sistema di riferimento - const IGeoObj* pGeoObj = m_pGeomDB->GetGeoObj( nGeoPlaneId) ; - if ( pGeoObj == nullptr || ! pGeoObj->IsValid()) - return Plane3d() ; - Frame3d frGlob ; m_pGeomDB->GetGlobFrame( nGeoPlaneId, frGlob) ; - - // definisco il piano in base al tipo di oggetto Plane3d PlaneLimit ; - switch ( pGeoObj->GetType()) { - case CRV_ARC : - case CRV_BEZIER : - case CRV_COMPO : { - // recupero la curva e verifico che sia piana e chiusa (serve per definire l'orientamento del piano) - const ICurve* pCrv = ::GetCurve( pGeoObj) ; - if ( pCrv == nullptr || ! pCrv->IsClosed()) + int nGeoPlaneId = GDB_ID_NULL ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_LIMIT_PLANE_ID, nGeoPlaneId) && nGeoPlaneId != GDB_ID_NULL) { + + // recupero l'oggetto geometrico e il suo sistema di riferimento + const IGeoObj* pGeoObj = m_pGeomDB->GetGeoObj( nGeoPlaneId) ; + if ( pGeoObj == nullptr || ! pGeoObj->IsValid()) return Plane3d() ; - if ( ! pCrv->IsFlat( PlaneLimit, true) || ! PlaneLimit.IsValid()) - return Plane3d() ; - } - break ; - case SRF_FLATRGN : { - // recupero la regione piana - const ISurfFlatRegion* pSfr = ::GetSurfFlatRegion( pGeoObj) ; - if ( pSfr == nullptr) - return Plane3d() ; - // recupero il suo piano intrinseco - Point3d ptCentroid ; pSfr->GetCentroid( ptCentroid) ; - PlaneLimit.Set( ptCentroid, pSfr->GetNormVersor()) ; - } - break ; - case SRF_TRIMESH : { - // recupero la TriMesh - const ISurfTriMesh* pStm = ::GetSurfTriMesh( pGeoObj) ; - if ( pStm == nullptr) - return Plane3d() ; - // verifico che sia formata da una sola faccia - if ( pStm->GetFacetCount() != 1) - return Plane3d() ; - // dalla faccia recupero il piano intrinseco - Point3d ptCenter ; Vector3d vtN ; pStm->GetFacetCenter( 0, ptCenter, vtN) ; - PlaneLimit.Set( ptCenter, vtN) ; - } - break ; - default : + Frame3d frGlob ; m_pGeomDB->GetGlobFrame( nGeoPlaneId, frGlob) ; + + // definisco il piano in base al tipo di oggetto + + switch ( pGeoObj->GetType()) { + case CRV_ARC : + case CRV_BEZIER : + case CRV_COMPO : { + // recupero la curva e verifico che sia piana e chiusa (serve per definire l'orientamento del piano) + const ICurve* pCrv = ::GetCurve( pGeoObj) ; + if ( pCrv == nullptr || ! pCrv->IsClosed()) + return Plane3d() ; + if ( ! pCrv->IsFlat( PlaneLimit, true) || ! PlaneLimit.IsValid()) + return Plane3d() ; + } break ; + case SRF_FLATRGN : { + // recupero la regione piana + const ISurfFlatRegion* pSfr = ::GetSurfFlatRegion( pGeoObj) ; + if ( pSfr == nullptr) + return Plane3d() ; + // recupero il suo piano intrinseco + Point3d ptCentroid ; pSfr->GetCentroid( ptCentroid) ; + PlaneLimit.Set( ptCentroid, pSfr->GetNormVersor()) ; + } + break ; + case SRF_TRIMESH : { + // recupero la TriMesh + const ISurfTriMesh* pStm = ::GetSurfTriMesh( pGeoObj) ; + if ( pStm == nullptr) + return Plane3d() ; + // verifico che sia formata da una sola faccia + if ( pStm->GetFacetCount() != 1) + return Plane3d() ; + // dalla faccia recupero il piano intrinseco + Point3d ptCenter ; Vector3d vtN ; pStm->GetFacetCenter( 0, ptCenter, vtN) ; + PlaneLimit.Set( ptCenter, vtN) ; + } + break ; + default : + break ; + } + + // il piano limite deve essere valido + if ( ! PlaneLimit.IsValid()) + return Plane3d() ; + // porto il piano in globale + PlaneLimit.ToGlob( frGlob) ; } + double dTabDist = 0. ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_LIMIT_TAB_DIST, dTabDist)) { + PlaneLimit = Plane3d() ; - // piano limite valido - if ( ! PlaneLimit.IsValid()) - return Plane3d() ; + // recupero la tavola + Machine* pMch = m_pMchMgr->GetCurrMachine() ; + if ( pMch == nullptr) + return Plane3d() ; + Point3d ptRefTab1 ; + if ( ! pMch->GetCurrTableRef1( ptRefTab1)) + return Plane3d() ; + PlaneLimit.Set( ptRefTab1 + Z_AX * dTabDist, Z_AX) ; - // porto il piano in globale - PlaneLimit.ToGlob( frGlob) ; + // il piano limite deve essere valido + if ( ! PlaneLimit.IsValid()) + return Plane3d() ; + } // verifico la normale rispetto alla direzione utensile double dCos = PlaneLimit.GetVersN() * vtTool ; @@ -4084,7 +4226,9 @@ bool PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) { // aggiorno la ProgressBar del 5% per simulare l'inizio della funzione - ExeProcessEvents( 5, 0) ; + #if USE_PROGRESS_BAR + ExeProcessEvents( 5, 0) ; + #endif // recupero gruppo per geometria temporanea const string GRP_TEMP = "Temp" ; @@ -4250,7 +4394,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // calcolo l'elevazione al di sopra della geometria originale double dOrigElev = 0. ; - if ( ! CalcOrigRegionElevation( pSfr, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), vtTool, dDepth, m_TParams.m_dDiam / 2., m_TParams.m_dLen, dOrigElev)) { + if ( ! CalcOrigRegionElevation( pSfr, vtTool, dDepth, m_TParams.m_dDiam / 2., m_TParams.m_dLen, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), dOrigElev)) { m_pMchMgr->SetLastError( 2433, "Error in PocketingNT : Calc Region Elevation failed") ; return false ; } @@ -4565,8 +4709,9 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) vStepInfo.back().pSfrLimit.Set( pSfrLimit) ; } // aggiorno la progressBar - ExeProcessEvents( 5 + nProgressBarStep * 45 / nStep, 0) ; - + #if USE_PROGRESS_BAR + ExeProcessEvents( 5 + nProgressBarStep * 45 / nStep, 0) ; + #endif } // imposto dati comuni @@ -4727,8 +4872,8 @@ PocketingNT::CalcRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& v //---------------------------------------------------------------------------- bool -PocketingNT::CalcOrigRegionElevation( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw, const Vector3d& vtTool, double dDepth, - double dRad, double dLen, double& dElev) const +PocketingNT::CalcOrigRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& vtTool, double dDepth, + double dRad, double dLen, const ISurfTriMesh* pStmRaw, double& dElev) const { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || @@ -5330,7 +5475,9 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo, bool& bEmpty) } } // aggiorno la progressBar - ExeProcessEvents( 50 + i * 50 / ssize( vStepInfo), 0) ; + #if USE_PROGRESS_BAR + ExeProcessEvents( 50 + i * 50 / ssize( vStepInfo), 0) ; + #endif } // controllo se la svuotatura è riferita ad un foro chiuso @@ -5779,7 +5926,9 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou return false ; // se svuotatura vuota, aggiorno la ProgressBar ed esco if ( bEmpty) { - ExeProcessEvents( 100, 0) ; + #if USE_PROGRESS_BAR + ExeProcessEvents( 100, 0) ; + #endif return true ; } @@ -6121,7 +6270,9 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou } // aggiorno per sicurezza la ProgressBar - ExeProcessEvents( 100, 0) ; + #if USE_PROGRESS_BAR + ExeProcessEvents( 100, 0) ; + #endif return true ; } diff --git a/PocketingNT.h b/PocketingNT.h index 1094a58..cec823b 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -106,7 +106,8 @@ class PocketingNT : public Machining private : bool MyApply( bool bRecalc, bool bPostApply) ; bool VerifyGeometry( SelData Id, int& nSubs, int& nType) ; - bool AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, ICURVEPLIST& lstPC) ; + bool AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, int nFacet, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, const INTVECTOR& vIndCloseEdgesByUS, + ICURVEPLIST& lstPC) const ; bool GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const ISurfTriMesh* pStmTrim, ICURVEPLIST& lstPC) ; bool SetCurveAllTempProp( int nCrvId, bool bForcedClose, ICurve* pCurve, bool* pbSomeOpen = nullptr) ; bool SetSfrLoopsAllTempProp( int nSfrId, ISurfFlatRegion* pSfr) ; @@ -134,8 +135,8 @@ class PocketingNT : public Machining bool ProcessPath( int nPathId, int nPvId, int nClId) ; bool CalcRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& vtTool, double dDepth, double dRad, double dLen, const ISurfTriMesh* pStmRaw, double& dElev) const ; - bool CalcOrigRegionElevation( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw, const Vector3d& vtTool, double dDepth, - double dRad, double dLen, double& dElev) const ; + bool CalcOrigRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& vtTool, double dDepth, + double dRad, double dLen, const ISurfTriMesh* pStmRaw, double& dElev) const ; bool VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) ; bool GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) ; bool CalcGeoExtSurfFr( const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, const ISurfTriMesh* pStmRaw,