diff --git a/PocketingNT.cpp b/PocketingNT.cpp index bdca492..39e9e7b 100644 --- a/PocketingNT.cpp +++ b/PocketingNT.cpp @@ -44,6 +44,7 @@ #include "/EgtDev/Include/EGkCalcPocketing.h" #include "/EgtDev/Include/EGkSurfLocal.h" #include "/EgtDev/Include/EGkDistPointSurfFr.h" +#include "/EgtDev/Include/EGkStmFromCurves.h" #include using namespace std ; @@ -59,9 +60,11 @@ static double TOOL_RAD_PTSTART = 20. ; // Parametri avanzati da UserNotes const string UN_MAXELEV = "MaxElev" ; const string UN_OPEN = "Open" ; +const string UN_TRIMSTM = "TrimExt" ; const string UN_OPENOUTRAW = "OpenOutRaw" ; const string UN_OPENMINSAFE = "OpenMinSafe" ; const string UN_MAXOPTSIZE = "MaxOptSize" ; +const string UN_PROJEXT = "ExtProj" ; const string UN_ADJUSTFEED = "AdjustFeed" ; //------------------------------ Errori/Warnings -------------------------------------- @@ -99,6 +102,9 @@ const string UN_ADJUSTFEED = "AdjustFeed" ; // 2433 = "Error in PocketingNT : Calc Region Elevation failed" // 2434 = "Error in PocketingNT : Managing Open Edges inside Raw failed" // 2435 = "Error in PocketingNT : Managing Open Edges on Raw failed" +// 2436 = "Error in PocketingNT : not valid Raw" +// 2437 = "Error in PocketingNT : not valid Trim Surf" +// 2438 = "Error in PocketingNT : not valid Pocketing Volume" // 2451 = "Warning in PocketingNT : Skipped entity (xx)" // 2452 = "Warning in PocketingNT : No pocket" // 2453 = "Warning in PocketingNT : Tool name changed (xx)" @@ -111,6 +117,7 @@ const string UN_ADJUSTFEED = "AdjustFeed" ; //---------------------------------------------------------------------------- // Debug +#define DEBUG_STM_TOPOLOGY 0 // Debug per topologia faccia selezionata per pStm #define DEBUG_OPEN_EDGE_EXTENSION 0 // Debug estensione dei lati aperti #define DEBUG_OPEN_EDGE_IN_RAW 0 // Debug gestione lati aperti interni al grezzo #define DEBUG_SFR_STEPS 0 // Debug Sfr ( Pock e Limit) nei vari step ( risultato finale per CalcPocketing) @@ -122,7 +129,7 @@ const string UN_ADJUSTFEED = "AdjustFeed" ; #define DEBUG_FEED 0 // Debug per Feed #define DEBUG_START_POINT 0 // Debug per scelta del punto iniziale #define DEBUG 0 // Debug -#if DEBUG_OPEN_EDGE_EXTENSION || DEBUG_OPEN_EDGE_IN_RAW || DEBUG_SFR_STEPS || DEBUG_SFR_RAW || DEBUG_GLIDE || DEBUG_SAFETY_LINK || DEBUG_FEED || DEBUG_START_POINT || DEBUG +#if DEBUG_STM_TOPOLOGY || DEBUG_OPEN_EDGE_EXTENSION || DEBUG_OPEN_EDGE_IN_RAW || DEBUG_SFR_STEPS || DEBUG_SFR_RAW || DEBUG_GLIDE || DEBUG_SAFETY_LINK || DEBUG_FEED || DEBUG_START_POINT || DEBUG #include "EgtDev/Include/EGkGeoPoint3d.h" #include "EgtDev/Include/EGkGeoVector3d.h" #include "EgtDev/Include/EGkFrame3d.h" @@ -1176,7 +1183,252 @@ PocketingNT::VerifyGeometry( SelData Id, int& nSubs, int& nType) //---------------------------------------------------------------------------- bool -PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) +PocketingNT::AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, + ICURVEPLIST& lstPC) +{ + // controllo dei parametri + if ( pSurf == nullptr || ! pSurf->IsValid()) + return false ; + if ( lstPC.empty()) + return true ; + // le curve devono essere tutte valide + for ( auto& 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) { + 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) { + bool bSomeOpen = false ; + for ( int i = 0 ; i < vCrvCompo.back()->GetCurveCount() && ! bSomeOpen ; ++ i) { + bSomeOpen = ( vCrvCompo.back()->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) ; + if ( bSomeOpen) + break ; + } + if ( ! bSomeOpen) + return true ; + } + + // 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) { + // recupero i tratti omogenei + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvCompo, vpCrvs) ; + // scorro i tratti alla ricerca di lati aperti + bool bOpenCrvInPart = false ; + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ 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 ) + PNTVECTOR vPt( 3, P_INVALID) ; + vpCrvs[i]->GetCurve( j)->GetStartPoint( vPt[0]) ; + vpCrvs[i]->GetCurve( j)->GetMidPoint( vPt[1]) ; + vpCrvs[i]->GetCurve( j)->GetEndPoint( vPt[2]) ; + // classifico tali punti rispetto alla superficie + bool bOpenEdgeInStm = false ; + double dDist = 0. ; + for ( int nPt = 0 ; nPt < int( vPt.size()) && ! 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... + } + } + } + } + + // recupero il volume di svuotatura + PtrOwner pStmRawCl( CloneSurfTriMesh( pStmTrim)) ; + PtrOwner pStmVol( CloneSurfTriMesh( pStmTrim)) ; + PtrOwner pSurfGlob( CloneSurfTriMesh( pSurf)) ; + if ( IsNull( pStmRawCl) || ! pStmRawCl->IsValid() || + IsNull( pStmVol) || ! pStmVol->IsValid() || + IsNull( pSurfGlob) || ! pSurfGlob->IsValid() || ! pSurfGlob->ToGlob( frGlob) || + ! pStmVol->Subtract( *pSurfGlob)) + return false ; + + #if DEBUG_STM_TOPOLOGY + int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; + m_pGeomDB->SetName( nGrp, "StmFaceTopology") ; + m_pGeomDB->SetStatus( nGrp, GDB_ST_OFF) ; + int nStmLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetName( nStmLay, "Stm") ; + int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nStmLay, pSurfGlob->Clone()) ; + m_pGeomDB->SetMaterial( nId, TEAL) ; + 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) ; + m_pGeomDB->SetName( nRawLay, "Raw") ; + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawLay, pStmRawCl->Clone()) ; + m_pGeomDB->SetMaterial( nId, PURPLE) ; + int nVolLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetName( nVolLay, "Vol") ; + int nCrvLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ; + m_pGeomDB->SetName( nCrvLay, "Result") ; + #endif + + // le isole sono considerate estese fino al grezzo; creo dei solidi di estrusione per le isole chiuse + if ( int( vCrvCompo.size() > 1)) { + Vector3d vtN ; lstPC.back()->GetExtrusion( vtN) ; + const double EXTR_LEN = 1000. ; + SurfFlatRegionByContours SfrByC ; + for ( auto& pCrvCompo : vCrvCompo) { + if ( ! SfrByC.AddCurve( CloneCurveComposite( pCrvCompo))) + return false ; + } + PtrOwner pSfr( SfrByC.GetSurf()) ; + if ( IsNull( pSfr) || ! pSfr->IsValid()) + return false ; + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + for ( int nL = 1 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + bool bClosedIsl = true ; + int nTmpProp = TEMP_PROP_INVALID ; + for ( int nU = 0 ; nU < pSfr->GetLoopCurveCount( nC, nL) && bClosedIsl ; ++ nU) + bClosedIsl = ( pSfr->GetCurveTempProp( nC, nL, nU, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + if ( bClosedIsl) { + PtrOwner pCrvLoop( pSfr->GetLoop( nC, nL)) ; + if ( ! IsNull( pCrvLoop) && pCrvLoop->IsValid()) { + pCrvLoop->Translate( - EXTR_LEN / 2. * vtN) ; + pCrvLoop->SetExtrusion( vtN) ; + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pCrvLoop, 10 * EPS_SMALL, ICurve::OFF_FILLET) || + ! pCrvLoop.Set( OffsCrv.GetLongerCurve())) + return false ; + PtrOwner pStmExtr( GetSurfTriMeshByExtrusion( pCrvLoop, EXTR_LEN * vtN, true)) ; + if ( ! IsNull( pStmExtr) && pStmExtr->IsValid() && pStmExtr->IsClosed()) { + double dVol = 0. ; + if ( pStmExtr->GetVolume( dVol) && dVol < 0.) + pStmExtr->Invert() ; + #if DEBUG_STM_TOPOLOGY + int nIslId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nClISlLay, CloneSurfTriMesh( pStmExtr)) ; + m_pGeomDB->SetMaterial( nIslId, BLACK) ; + #endif + if ( ! pStmVol->Subtract( *pStmExtr)) + return false ; + } + } + } + } + } + } + + #if DEBUG_STM_TOPOLOGY + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nVolLay, pStmVol->Clone()) ; + m_pGeomDB->SetMaterial( nId, GREEN) ; + #endif + + // se volume non chiuso, errore + if ( ! pStmVol->IsClosed()) + return false ; + + // proeitto la superficie ricavata e il grezzo sul piano intrinseco della regione piana + Vector3d vtN ; lstPC.back()->GetExtrusion( vtN) ; + Point3d ptC ; lstPC.back()->GetCentroid( ptC) ; + Plane3d plProj ; + if ( ! plProj.Set( ptC, vtN)) + return false ; + POLYLINEVECTOR vPLVol, vPLRaw ; + if ( ! pStmVol->GetSilhouette( plProj, 20 * EPS_SMALL, vPLVol)) + return false ; + if ( ! pStmRawCl->GetSilhouette( plProj, 20 * EPS_SMALL, vPLRaw)) + return false ; + + #if DEBUG_STM_TOPOLOGY + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawLay, pStmRawCl->Clone()) ; + m_pGeomDB->SetMaterial( nId, BLUE) ; + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nVolLay, pStmVol->Clone()) ; + m_pGeomDB->SetMaterial( nId, LIME) ; + #endif + + // recupero le due superfici piane + SurfFlatRegionByContours SfrBCVol, SfrBCRaw ; + for ( PolyLine& PL : vPLVol) { + PtrOwner pCompo( CreateCurveComposite()) ; + if ( ! IsNull( pCompo) && pCompo->FromPolyLine( PL)) + SfrBCVol.AddCurve( Release( pCompo)) ; + } + for ( 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()) + return false ; + if ( AreOppositeVectorApprox( vtN, pSfrVol->GetNormVersor())) + pSfrVol->Invert() ; + if ( AreOppositeVectorApprox( vtN, pSfrRaw->GetNormVersor())) + pSfrRaw->Invert() ; + + #if DEBUG_STM_TOPOLOGY + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawLay, pSfrRaw->Clone()) ; + m_pGeomDB->SetMaterial( nId, BLUE) ; + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nVolLay, pSfrVol->Clone()) ; + m_pGeomDB->SetMaterial( nId, LIME) ; + #endif + + // definisco i lati aperti della nuova regione da svuotare + // --- i lati aperti sono quelli in comune con la proiezione del grezzo + lstPC.clear() ; + pSfrRaw->Offset( - 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + for ( int nC = 0 ; nC < pSfrVol->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrVol->GetLoopCount( nC) ; ++ nL) { + // recupero il Loop + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfrVol->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return false ; + for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) { + PNTVECTOR vPt( 3, P_INVALID) ; + pCompoLoop->GetCurve( nU)->GetStartPoint( vPt[0]) ; + pCompoLoop->GetCurve( nU)->GetMidPoint( vPt[1]) ; + pCompoLoop->GetCurve( nU)->GetEndPoint( vPt[2]) ; + pCompoLoop->SetCurveTempProp( nU, TEMP_PROP_OPEN_EDGE, 0) ; + for ( int nPt = 0 ; nPt < int( vPt.size()) ; ++ nPt) { + bool bIsInside = true ; + IsPointInsideSurfFr( vPt[nPt], pSfrRaw, EPS_SMALL, bIsInside) ; + if ( bIsInside) { + pCompoLoop->SetCurveTempProp( nU, TEMP_PROP_CLOSE_EDGE, 0) ; + break ; + } + } + } + + #if DEBUG_STM_TOPOLOGY + for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) { + int nProp0 ; pCompoLoop->GetCurveTempProp( nU, nProp0, 0) ; + int nInd = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nCrvLay, pCompoLoop->GetCurve( nU)->Clone()) ; + m_pGeomDB->SetMaterial( nInd, ( nProp0 == 0 ? BLUE : RED)) ; + } + #endif + + lstPC.emplace_back( Release( pCompoLoop)) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::GetCurves( const SelData& Id, const ISurfTriMesh* pStmRaw, const ISurfTriMesh* pStmTrim, ICURVEPLIST& lstPC) { // ammessi : curve, testi, facce di trimesh o regioni const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; @@ -1186,7 +1438,8 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) Frame3d frGlob ; if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob)) return false ; - // se curva + + // --- se curva if ( ( pGObj->GetType() & GEO_CURVE) != 0) { PtrOwner pCurve ; Vector3d vtExtr ; @@ -1244,7 +1497,8 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) lstPC.emplace_back( Release( pCurve)) ; return true ; } - // se altrimenti testo + + // --- se testo else if ( pGObj->GetType() == EXT_TEXT) { // recupero il testo const IExtText* pText = ::GetExtText( pGObj) ; @@ -1262,7 +1516,8 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) // ritorno return true ; } - // se altrimenti superficie + + // --- se superficie else if ( pGObj->GetType() == SRF_TRIMESH) { // recupero la trimesh const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; @@ -1276,6 +1531,7 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) if ( vPL.empty()) return false ; // per ogni loop recupero le curve composite + ICURVEPLIST lstCrvLoops ; for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { PtrOwner pCrvCompo( CreateCurveComposite()) ; pCrvCompo->FromPolyLine( vPL[i]) ; @@ -1322,11 +1578,16 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) // la restituisco if ( m_bAllClose) ResetCurveAllTempProp( pCrvCompo) ; - lstPC.emplace_back( Release( pCrvCompo)) ; + lstCrvLoops.emplace_back( Release( pCrvCompo)) ; } + // aggiusto la topologia della faccia + AdjustCurvesByStmTopology( pSurf, frGlob, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), lstCrvLoops) ; + for ( auto& pCrv : lstCrvLoops) + lstPC.emplace_back( pCrv) ; return true ; } - // se altrimenti regione + + // --- se regione piana else if ( pGObj->GetType() == SRF_FLATRGN) { // recupero la regione const ISurfFlatRegion* pReg = ::GetSurfFlatRegion( pGObj) ; @@ -1366,9 +1627,11 @@ PocketingNT::GetCurves( SelData Id, ICURVEPLIST& lstPC) } return true ; } - // altrimenti errore + // -- altrimenti errore else return false ; + + return true ; } //---------------------------------------------------------------------------- @@ -1464,11 +1727,22 @@ PocketingNT::Chain( int nGrpDestId) SELVECTOR vInds ; // flag per imposizione lati chiusi m_bAllClose = GetForcedClosed() ; + + // recupero il grezzo in globale + PtrOwner pStmRaw( GetRaw()) ; + if ( IsNull( pStmRaw) || ! pStmRaw->IsValid() || pStmRaw->GetTriangleCount() == 0) { + m_pMchMgr->SetLastError( 2436, "Error in PocketingNT : not valid Raw") ; + return false ; + } + + // recupero la superficie di Trim in globale [nullptr se non presente] + PtrOwner pStmTrim( GetStmTrim()) ; + // recupero tutte le curve e le porto in globale for ( const auto& Id : m_vId) { // prendo le curve ICURVEPLIST lstPC ; - if ( ! GetCurves( Id, lstPC)) { + if ( ! GetCurves( Id, pStmRaw, pStmTrim, lstPC)) { string sInfo = "Warning in PocketingNT : Skipped entity " + ToString( Id) ; m_pMchMgr->SetWarning( 2451, sInfo) ; } @@ -1587,14 +1861,6 @@ PocketingNT::Chain( int nGrpDestId) SfrByC.AddCurve( Release( vCrvCompo[i])) ; } - // recupero il pezzo corrente - PtrOwner pStmRaw( GetRaw()) ; - if ( IsNull( pStmRaw) || ! pStmRaw->IsValid() || pStmRaw->GetTriangleCount() == 0) { - m_pMchMgr->SetLastError( 3025, "Error in PocketingNT : RawPart not computable") ; - return false ; - } - - // scorro le regioni piane ricavate dalle curve int nGroupName = -1 ; PtrOwner pSfrCurr( SfrByC.GetSurf()) ; @@ -1619,12 +1885,12 @@ PocketingNT::Chain( int nGrpDestId) Vector3d vtExtr ; pCrvInfo->GetExtrusion( vtExtr) ; // -------------- Controllo esistenza di lati aperti interni al grezzo -------------- // Questi lati vengono Offsettati, raccordati e considerati poi come chiusi - if ( ! ManageOpenEdges( pSfrChunk, pStmRaw)) { + if ( ! ManageOpenEdges( pSfrChunk, ( pStmTrim == nullptr ? pStmRaw : pStmTrim))) { m_pMchMgr->SetLastError( 2434, "Error in PocketingNT : Managing Open Edges inside Part failed") ; return false ; } // ------------- Estendo i lati aperti sul bordo per possibili proiezioni ------------- - if ( ! ExtendOpenEdges( pSfrChunk, pStmRaw)) { + if ( ! ExtendOpenEdges( pSfrChunk, ( pStmTrim == nullptr ? pStmRaw : pStmTrim))) { m_pMchMgr->SetLastError( 2435, "Error in PocketingNT : Managing Open Edges on Raw failed") ; return false ; } @@ -1705,6 +1971,41 @@ PocketingNT::GetRaw( void) return ( ( pStmRaw->IsValid() && pStmRaw->GetTriangleCount() > 0) ? Release( pStmRaw) : nullptr) ; } +//---------------------------------------------------------------------------- +ISurfTriMesh* +PocketingNT::GetStmTrim( void) +{ + // controllo se è presente una superficie di Trim + int nStmTrimId = GDB_ID_NULL ; + if ( ! GetValInNotes( m_Params.m_sUserNotes, UN_TRIMSTM, nStmTrimId)) + return nullptr ; + + // creo Stm della superficie di Trim + PtrOwner pStmTrim( CreateSurfTriMesh()) ; + if ( IsNull( pStmTrim)) + return nullptr ; + pStmTrim->AdjustTopology() ; + + // recupero l'oggetto geometrico + const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( nStmTrimId) ; + if ( pGObj == nullptr) + return nullptr ; + + // controllo che sia una superficie TriMesh + if ( pGObj->GetType() != SRF_TRIMESH) + return nullptr ; + + // ne recupero il riferimento globale + Frame3d frGlob ; + if ( ! m_pGeomDB->GetGlobFrame( nStmTrimId, frGlob)) + return nullptr ; + + // recupero la TriMesh di Trim + SurfLocal StmRawPart( GetSurfTriMesh( pGObj), frGlob, GLOB_FRM) ; + pStmTrim->Add( *GetSurfTriMesh( StmRawPart)) ; + return ( ( pStmTrim->IsValid() && pStmTrim->GetTriangleCount() > 0) ? Release( pStmTrim) : nullptr) ; +} + //---------------------------------------------------------------------------- ISurfTriMesh* PocketingNT::GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExtr) @@ -2141,7 +2442,11 @@ PocketingNT::ExtendOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm) if ( IsNull( pCrvNewBorder)) return false ; // definisco offset di estensione per tratti aperti - double dOffs = max( BBoxRawCut.GetDimX(), BBoxRawCut.GetDimY()) + m_TParams.m_dDiam ; + double dMaxDimBox = max( BBoxRawCut.GetDimX(), BBoxRawCut.GetDimY()) ; + double dOffs = min( 3. * m_TParams.m_dDiam, dMaxDimBox) + m_TParams.m_dDiam ; + double dOffsUser = 0. ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_PROJEXT, dOffsUser) && dOffsUser > EPS_SMALL) + dOffs = dOffsUser ; // sostiuisco ogni tratto aperto con il suo Offset for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { if ( vpCrvs[i]->GetTempProp() == TEMP_PROP_OPEN_EDGE) { @@ -2937,18 +3242,23 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) m_pMchMgr->SetWarning( 2457, sInfo) ; } - // recupero il grezzo + // recupero il grezzo e la superficie di Trim [nullptr se non presente] PtrOwner pStmRaw( GetRaw()) ; if ( IsNull( pStmRaw)) { m_pMchMgr->SetLastError( 3025, "Error in PocketingNT : RawPart not computable") ; return false ; } + PtrOwner pStmTrim( GetStmTrim()) ; #if DEBUG_SFR_RAW int nGrpSR = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ; int nLaySR = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpSR, GLOB_FRM) ; m_pGeomDB->SetName( nLaySR, "Sfr_Raw_Position") ; int _nRaw = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pStmRaw->Clone()) ; m_pGeomDB->SetMaterial( _nRaw, Color( .35, .46, .78, .1)) ; + if ( ! IsNull( pStmTrim)) { + int _nTrim = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pStmTrim->Clone()) ; + m_pGeomDB->SetMaterial( _nTrim, Color( .65, .26, .58, .1)) ; + } #endif // definisco una trimesh derivante dalla regione piana mediante estrusione dei lati chiusi @@ -3100,18 +3410,18 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) return false ; // adatto la regione piana alla geometria del grezzo - PtrOwner pSfrRaw( GetSfrRawProjection( pStmRaw, pSfrPock, vtTool)) ; - if ( IsNull( pSfrRaw)) { + PtrOwner pSfrTrim( GetSfrRawProjection( ( pStmTrim == nullptr ? pStmRaw : pStmTrim), pSfrPock, vtTool)) ; + if ( IsNull( pSfrTrim)) { m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Slicing Raw failed") ; return false ; } - if ( pSfrRaw->IsValid() && pSfrRaw->GetChunkCount() > 0) { + if ( pSfrTrim->IsValid() && pSfrTrim->GetChunkCount() > 0) { // se valida, limito la superficie di svuotatura alla proiezione del grezzo #if DEBUG_SFR_RAW - int _nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pSfrRaw->Clone()) ; + int _nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pSfrTrim->Clone()) ; m_pGeomDB->SetMaterial( _nSfr, Color( 0., 1., 0., .75)) ; #endif - pSfrPock->Intersect( *pSfrRaw) ; + pSfrPock->Intersect( *pSfrTrim) ; } else continue ; // svuotatura fuori dalla proiezione del grezzo, passo al prossimo step @@ -3132,7 +3442,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // determino la regione limite PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; if ( IsNull( pSfrLimit) || - ! CalcLimitRegion( pSfrPock, pSfrRaw, pSfrLimit)) { + ! CalcLimitRegion( pSfrPock, pSfrTrim, pSfrLimit)) { m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Calc limit region failed") ; return false ; } @@ -3616,9 +3926,9 @@ PocketingNT::CalcRetCurve( PathInfoPO& PathInfo, const StepInfoPO& StepInfo, con bool PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) { - /* - funzione per calcolo dei percorsi di Pockets e delle loro proprietà - */ + // se non ho Step, non faccio nulla + if ( vStepInfo.empty()) + return true ; // punto finale di riferimento per il percorso attuale ( serve per trovare il punto iniziale // del percorso successivo) @@ -3628,7 +3938,7 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) if ( ! ptStartRef.IsValid()) ptStartRef = GetStartPointsFromSteps( vStepInfo, TEMP_PROP_CLOSE_EDGE) ; } - // controllo parametri per casi ottimizzati + // recupero flag per casi ottimizzati double dMaxOptSize = m_Params.m_dSideStep ; GetValInNotes( m_Params.m_sUserNotes, UN_MAXOPTSIZE, dMaxOptSize) ; @@ -3663,6 +3973,21 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; return false ; } + if ( vStepInfo[i].vPaths[j].bOutStart && ! m_bOpenOutRaw) { + // se richiesto, controllo di essere davvero fuori dal grezzo [controllo basilare, migliorabile] + Point3d ptStart ; vCrvPaths[j]->GetStartPoint( ptStart) ; + double dElev ; + PtrOwner pCrvArc( CreateCurveArc()) ; + pCrvArc->Set( ptStart, m_vtTool, 50. * EPS_SMALL) ; + PtrOwner pSfrCheck( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrCheck) || ! pSfrCheck->AddExtLoop( Release( pCrvArc))) + return false ; + if ( CalcRegionElevation( pSfrCheck, m_vtTool, 0., m_TParams.m_dDiam / 2., m_TParams.m_dLen, dElev) && + dElev > EPS_SMALL) { + vStepInfo[i].vPaths[j].bOutStart = false ; + delete( vCrvPaths[j]->RemoveFirstOrLastCurve( false)) ; + } + } // controllo se il percorso ha un'uscita presso un lato aperto vStepInfo[i].vPaths[j].bOutEnd = ( vCrvPaths[j]->GetCurveCount() > 0 && vCrvPaths[j]->GetLastCurve()->GetTempProp( 0) == TEMP_PROP_OUT_START) ; diff --git a/PocketingNT.h b/PocketingNT.h index 83fab07..c5900a2 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -103,12 +103,14 @@ class PocketingNT : public Machining private : bool MyApply( bool bRecalc, bool bPostApply) ; bool VerifyGeometry( SelData Id, int& nSubs, int& nType) ; - bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ; + bool AdjustCurvesByStmTopology( const ISurfTriMesh* pSurf, const Frame3d& frGlob, const ISurfTriMesh* pStmTrim, ICURVEPLIST& lstPC) ; + 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) ; bool ResetCurveAllTempProp( ICurve* pCurve) ; bool Chain( int nGrpDestId) ; ISurfTriMesh* GetRaw( void) ; + ISurfTriMesh* GetStmTrim( void) ; ISurfTriMesh* GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExtr) ; ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) ; ISurfFlatRegion* GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool) ;