diff --git a/OperUserNotesConst.h b/OperUserNotesConst.h index 1369a31..2810d63 100644 --- a/OperUserNotesConst.h +++ b/OperUserNotesConst.h @@ -55,6 +55,7 @@ static const std::string UN_ADJUSTFEED = "AdjustFeed" ; 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" ; // Solo per Sawing static const std::string UN_DOWNSE = "DownSE" ; diff --git a/PocketingNT.cpp b/PocketingNT.cpp index 85623d7..f1b52d8 100644 --- a/PocketingNT.cpp +++ b/PocketingNT.cpp @@ -107,6 +107,7 @@ static double FEED_MAX_COEFF = 1000. ; // 2443 = "Error in PocketingNT : Calc Limit Region failed" // 2444 = "Error in PocketingNT : Slicing Raw failed" // 2445 = "Error in PocketingNT : Error in Connecting Start Point" +// 2446 = "Error in PocketingNT : Limit Plane cut failed" // 2451 = "Warning in PocketingNT : Skipped entity (xx)" // 2452 = "Warning in PocketingNT : No pocket" // 2453 = "Warning in PocketingNT : Tool name changed (xx)" @@ -117,13 +118,14 @@ static double FEED_MAX_COEFF = 1000. ; // 2458 = "Warning in PocketingNT : machining depth (xxx) bigger than MaxMaterial (yyy)" // 2459 = "Warning in PocketingNT : No compensation in tool, so no compensation in machine" // 2460 = "Warning in PocketingNT : Machining toolpath empty" +// 2461 = "Warning in PocketingNT : Limit Plane ignored" //---------------------------------------------------------------------------- // 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) +#define DEBUG_SFR_STEPS 0 // Debug Sfr (Pock e Limit) nei vari step (risultato finale per CalcPocketing) #define DEBUG_SFR_RAW 0 // Debug intersezioni tra SurfFlatRegion e SurfTriMesh #define DEBUG_STM_EXTRUSION 0 // Debug superficie TriMesh di estrusione dei lati chiusi #define DEBUG_SFR_GEO_EXT 0 // Debug FlatRegion per geometrie dei lati chiusi (in Processpath) @@ -138,6 +140,7 @@ static double FEED_MAX_COEFF = 1000. ; #define DEBUG_TOOL_COMPENSATION 0 // Debug per Tool Compensation #define DEBUG_SILHOUETTE 0 // Debug Silhouette #define DEBUG_USER_PTSTART 0 // Debug punto iniziale stabilito dall'utente +#define DEBUG_LIMIT_PLANE 0 // Debug per piano limite #define DEBUG 0 // Debug #if DEBUG_STM_TOPOLOGY || DEBUG_OPEN_EDGE_EXTENSION || DEBUG_OPEN_EDGE_IN_RAW || DEBUG_SFR_STEPS || DEBUG_SFR_RAW || DEBUG_SFR_GEO_EXT || \ DEBUG_GLIDE || DEBUG_SAFETY_LINK || DEBUG_FEED || DEBUG_START_POINT || DEBUG_PATH_CL || DEBUG_ZIGZAG_LEADIN || DEBUG_DOUBLE_PARALLEL || \ @@ -2339,7 +2342,7 @@ PocketingNT::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, doubl //---------------------------------------------------------------------------- ISurfFlatRegion* PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, - const Vector3d& vtTool, const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil) + const Vector3d& vtTool, const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil) const { // controllo dei parametri if ( pStmRaw == nullptr || ! pStmRaw->IsValid() || pSfr == nullptr || ! pSfr->IsValid()) @@ -2420,6 +2423,128 @@ PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRe return Release( pSfrRaw) ; } +//---------------------------------------------------------------------------- +Plane3d +PocketingNT::GetLimitPlane( const Vector3d& vtTool, const ISurfTriMesh* pStmRaw) const +{ + // verifico la validità del grezzo + if ( pStmRaw == nullptr || ! pStmRaw->IsValid()) + 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()) + 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 ; + } + + // piano limite valido + if ( ! PlaneLimit.IsValid()) + return Plane3d() ; + + // porto il piano in globale + PlaneLimit.ToGlob( frGlob) ; + + // verifico la normale rispetto alla direzione utensile + double dCos = PlaneLimit.GetVersN() * vtTool ; + if ( dCos > - EPS_SMALL) { + return PlaneLimit ; + #if DEBUG_LIMIT_PLANE + PtrOwner pPlane( CreateCurveArc()) ; pPlane->Set( PlaneLimit.GetPoint(), PlaneLimit.GetVersN(), 1e5) ; + PtrOwner pSfrPlane( CreateSurfFlatRegion()) ; pSfrPlane->AddExtLoop( ::Release( pPlane)) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrPlane->Clone()) ; + #endif + } + else if ( cos( -135. * DEGTORAD) < dCos && dCos < 0.) { + // recupero il bordo che si ottiene dall'intersezione di tale piano con il grezzo + PtrOwner pStmRawCut( CloneSurfTriMesh( pStmRaw)) ; + if ( IsNull( pStmRawCut) || ! pStmRawCut->IsValid() || ! pStmRawCut->Cut( PlaneLimit, false)) + return Plane3d() ; + POLYLINEVECTOR vPL ; + if ( ! pStmRawCut->GetLoops( vPL) || vPL.empty()) { + m_pMchMgr->SetWarning( 2461, "Warning in PocketingNT : Limit Plane ignored") ; + return Plane3d() ; + } + // recupero la nuova normale del piano (perpendicolare a vtTool) + Vector3d vNewPlaneN = OrthoCompo( PlaneLimit.GetVersN(), vtTool) ; vNewPlaneN.Normalize() ; + // Rispetto a questa normale cerco il punto a Zlocale maggiore, questo diventerà il nuovo punto del piano + Frame3d frPlaneDir ; frPlaneDir.Set( ORIG, vNewPlaneN) ; + vPL[0].ToLoc( frPlaneDir) ; + PNTULIST& pointUList = vPL[0].GetUPointList() ; + Point3d ptZMax = P_INVALID ; + double dMaxZ = - INFINITO ; + for ( PNTULIST::iterator Iter = pointUList.begin() ; Iter != pointUList.end() ; ++ Iter) { + if ( Iter->first.z > dMaxZ) { + dMaxZ = Iter->first.z ; + ptZMax = Iter->first ; + } + } + if ( ! ptZMax.IsValid()) { + m_pMchMgr->SetWarning( 2461, "Warning in PocketingNT : Limit Plane ignored") ; + return Plane3d() ; + } + // definisco il nuovo piano limite + PlaneLimit.Set( GetToGlob( ptZMax, frPlaneDir), vNewPlaneN) ; + #if DEBUG_LIMIT_PLANE + PtrOwner pPlane( CreateCurveArc()) ; pPlane->Set( PlaneLimit.GetPoint(), PlaneLimit.GetVersN(), 1e5) ; + PtrOwner pSfrPlane( CreateSurfFlatRegion()) ; pSfrPlane->AddExtLoop( ::Release( pPlane)) ; + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrPlane->Clone()) ; + #endif + return PlaneLimit ; + } + else { + m_pMchMgr->SetWarning( 2461, "Warning in PocketingNT : Limit Plane ignored") ; + return Plane3d() ; + } + + return Plane3d() ; +} + //---------------------------------------------------------------------------- Point3d PocketingNT::GetStartPointByUser( const ISurfFlatRegion* pSfr) const @@ -3003,14 +3128,14 @@ PocketingNT::ExtendOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm) //---------------------------------------------------------------------------- bool -PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion) const +PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion, const Plane3d& PlaneLimit) const { // controllo parametri : if ( pSfr == nullptr || ! pSfr->IsValid() || pStmExtrusion == nullptr) return false ; - // se non ho una superificie di estrusione, allora è tutto aperto - if ( ! pStmExtrusion->IsValid() || pStmExtrusion->GetTriangleCount() == 0) { + // se non ho una superificie di estrusione e piani limite, allora è tutto aperto + if ( ( ! pStmExtrusion->IsValid() || pStmExtrusion->GetTriangleCount() == 0) && ! PlaneLimit.IsValid()) { for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { for ( int nU = 0 ; nU < pSfr->GetLoopCurveCount( nC, nL) ; ++ nU) @@ -3047,10 +3172,17 @@ PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* p if ( ! pCrv->GetPointD1D2( dPar, ICurve::FROM_PLUS, ptPar)) return false ; // scorro il vettore relativo alla regione di riferimento - DistPointSurfTm distCalculator( ptPar, *pStmExtrusion) ; - double dDist = 0. ; - distCalculator.GetDist( dDist) ; - bIsOnStm = ( dDist < DIST_TOL) ; + if ( pStmExtrusion->IsValid() && pStmExtrusion->GetTriangleCount() > 0) { + DistPointSurfTm distCalculator( ptPar, *pStmExtrusion) ; + double dDist = 0. ; + distCalculator.GetDist( dDist) ; + bIsOnStm = ( dDist < DIST_TOL) ; + } + // se esiste un piano di taglio, verifico la distanza da esso + if ( ! bIsOnStm && PlaneLimit.IsValid()) { + double dDist = abs( DistPointPlane( ptPar, PlaneLimit)) ; + bIsOnStm = ( dDist < DIST_TOL) ; + } } if ( bIsOnStm) pSfr->SetCurveTempProp( nC, nL, nU, TEMP_PROP_CLOSE_EDGE, 0) ; @@ -3058,22 +3190,24 @@ PocketingNT::ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* p } } - return true ; + return true ; } //---------------------------------------------------------------------------- bool -PocketingNT::CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, ISurfFlatRegion* pSfrLimit) +PocketingNT::CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, const Plane3d& PlaneLimit, + const Vector3d& vtTool, ISurfFlatRegion* pSfrLimit) const { // controllo dei parametri if ( pSfrPock == nullptr || ! pSfrPock->IsValid() || - pSfrRaw == nullptr || ! pSfrRaw->IsValid()) + pSfrRaw == nullptr || ! pSfrRaw->IsValid() || + pSfrLimit == nullptr) return false ; pSfrLimit->Clear() ; // la superficie limite è data dalla sottrazione tra il grezzo e la superficie da svuotare pSfrLimit->CopyFrom( pSfrRaw) ; - if ( pSfrLimit == nullptr || ! pSfrLimit->IsValid()) + if ( ! pSfrLimit->IsValid()) return false ; // piccolo Offset di correzione PtrOwner pSfrOffs( pSfrPock->CreateOffsetSurf( 10. * EPS_SMALL, ICurve::OFF_FILLET)) ; @@ -3122,6 +3256,27 @@ PocketingNT::CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRe } } + // se presente un piano limite + if ( PlaneLimit.IsValid()) { + // recupero la regione corrente + PtrOwner pSfrLimitPlane( CloneSurfFlatRegion( pSfrPock)) ; + if ( IsNull( pSfrLimitPlane) || ! pSfrLimitPlane->IsValid()) + return false ; + // effettuo un Offset di sicurezza per aggiungere eventuali regioni Limite al di sotto del Piano Limite + if ( ! pSfrLimitPlane->Offset( 4. * m_TParams.m_dDiam, ICurve::OFF_EXTEND)) + return false ; + // taglio la regione con il piano invertito + Plane3d PlaneLimitInv = PlaneLimit ; PlaneLimitInv.Invert() ; + if ( ! pSfrLimitPlane->Cut( PlaneLimitInv)) + return false ; + if ( ! IsNull( pSfrLimitPlane) && pSfrLimitPlane->IsValid()) { + if ( pSfrLimit->IsValid()) + pSfrLimit->Add( *pSfrLimitPlane) ; + else + pSfrLimit->CopyFrom( pSfrLimitPlane) ; + } + } + // se richiesto non controllo dei lati aperti if ( m_bOpenOutRaw && pSfrLimit->IsValid()) { double dExtension = 4. * m_TParams.m_dDiam + max( 0., m_dOpenMinSafe) + EPS_SMALL ; @@ -3704,7 +3859,8 @@ PocketingNT::CheckMaxDepth( const ISurfFlatRegion* pSfr, double dDepth, const Ve return true ; // ??? ( non deve capitare) // determino i lati aperti della regione ricavata - if ( ! ChooseCloseOrOpenEdge( pSfrAdj, pStmExtrusion)) { + Plane3d PlaneDummy ; PlaneDummy.Set( P_INVALID, V_NULL) ; + if ( ! ChooseCloseOrOpenEdge( pSfrAdj, pStmExtrusion, PlaneDummy)) { m_pMchMgr->SetLastError( 2441, "Error in PocketingNT : Detecting open edges failed") ; return false ; } @@ -4305,6 +4461,11 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) ISURFFRPOVECTOR vSfrGeoExt ; CalcGeoExtSurfFr( pSfr, vtTool, dDepth - dElev + vdSteps.back(), ( pStmTrim == nullptr ? pStmRaw : pStmTrim), vGeoSel, vSfrGeoExt) ; + // recupero, se presente il piano limite + Plane3d PlaneLimit = GetLimitPlane( vtTool, pStmRaw) ; + if ( PlaneLimit.IsValid()) + PlaneLimit.Invert() ; // user friendly + for ( int j = 0 ; j < ssize( vdSteps) ; ++ j) { // per i contatori non controllo se effettivamente svuoto una superficie o meno ++ nProgressBarStep ; // aggiorno step per progressBar @@ -4350,6 +4511,16 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // se regione risultante non vuota if ( pSfrPock->IsValid() && pSfrPock->GetChunkCount() > 0) { + // se presente un piano limite devo tagliare tale regione + if ( PlaneLimit.IsValid()) { + if ( ! pSfrPock->Cut( PlaneLimit)) { + m_pMchMgr->SetLastError( 2446, "Error in PocketingNT : Limit Plane cut failed") ; + return false ; + } + // se la regione risultante non è valida, mi fermo + if ( ! pSfrPock->IsValid() || pSfrPock->GetChunkCount() == 0) + continue ; + } // Verifico se bloccare gli step in base all'elevazione o meno if ( bBlockStepByElev) { @@ -4363,7 +4534,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) } // determino i lati aperti - if ( ! ChooseCloseOrOpenEdge( pSfrPock, pStmExtrusion)) { + if ( ! ChooseCloseOrOpenEdge( pSfrPock, pStmExtrusion, PlaneLimit)) { m_pMchMgr->SetLastError( 2441, "Error in PocketingNT : Detecting open edges failed") ; return false ; } @@ -4376,7 +4547,7 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) // determino la regione limite PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; if ( IsNull( pSfrLimit) || - ! CalcLimitRegion( pSfrPock, pSfrTrim, pSfrLimit)) { + ! CalcLimitRegion( pSfrPock, pSfrTrim, PlaneLimit, vtTool, pSfrLimit)) { m_pMchMgr->SetLastError( 2443, "Error in PocketingNT : Calc Limit Region failed") ; return false ; } diff --git a/PocketingNT.h b/PocketingNT.h index 62a707d..1094a58 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -118,7 +118,8 @@ class PocketingNT : public Machining ISurfTriMesh* GetStmRawSliced( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool) const ; ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) const ; ISurfFlatRegion* GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, - const Vector3d& vtTool, const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil = nullptr) ; + const Vector3d& vtTool, const Frame3d& frAtTop, ICAvParSilhouettesSurfTm** ppCavParSil = nullptr) const ; + Plane3d GetLimitPlane( const Vector3d& vtTool, const ISurfTriMesh* pStmRaw) const ; Point3d GetStartPointByUser( const ISurfFlatRegion* pSfr) const ; Point3d GetStartPointsByHead( const STEPINFOPOVECTOR& vStepInfo) const ; Point3d GetStartPointsBySteps( const STEPINFOPOVECTOR& vStepInfo, int nCrvType) const ; @@ -127,7 +128,7 @@ class PocketingNT : public Machining bool ManageOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmPart) ; bool GetHomogeneousParts( const ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCrvs) const ; bool ExtendOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm) ; - bool ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion) const ; + bool ChooseCloseOrOpenEdge( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmExtrusion, const Plane3d& PlaneLimit) const ; bool CheckMaxDepth( const ISurfFlatRegion* pSfr, double dDepth, const Vector3d& vtTool, const ISurfTriMesh* pStmRaw, const ISurfTriMesh* pStmExtrusion, const IntersParPlanesSurfTm& IPPStm, bool& bSkipMaxDepth) const ; bool ProcessPath( int nPathId, int nPvId, int nClId) ; @@ -139,7 +140,8 @@ class PocketingNT : public Machining bool GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) ; bool CalcGeoExtSurfFr( const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, const ISurfTriMesh* pStmRaw, const SELVECTOR& vGeoSel, ISURFFRPOVECTOR& vSfrGeoExt) ; - bool CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, ISurfFlatRegion* pSfrLimit) ; + bool CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, const Plane3d& PlaneLimit, + const Vector3d& vtTool, ISurfFlatRegion* pSfrLimit) const ; bool CalcPaths( STEPINFOPOVECTOR& vStepInfo, bool& bEmpty) ; bool CalcRetCurve( PathInfoPO& PathInfo, const StepInfoPO& StepInfo, const ICurveComposite* pCrvPath, const Vector3d& vtTool, bool bHolePocketing, const Point3d& ptHoleDest, bool bToolComp, bool bInVsOut, ICurveComposite* pCrvGlide) ;