From 87666ea59c0dc3ecd043d940ec32072a38cd4365 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 12 Dec 2024 11:49:50 +0100 Subject: [PATCH] EgtMachKernel : - migliorata gestione sgrossature - aggiunta lavorazione di finitura ZConst. --- SurfFinishing.cpp | 1077 +++++++++++++++++++++++++++++++++++++++++---- SurfFinishing.h | 18 + SurfRoughing.cpp | 277 ++++++++---- SurfRoughing.h | 4 +- 4 files changed, 1182 insertions(+), 194 deletions(-) diff --git a/SurfFinishing.cpp b/SurfFinishing.cpp index 9a6cbe1..2e59023 100644 --- a/SurfFinishing.cpp +++ b/SurfFinishing.cpp @@ -4,7 +4,7 @@ // File : SurfFinishing.cpp Data : 28.05.19 Versione : 2.1e5 // Contenuto : Implementazione gestione finitura superfici. // -// Note : Questa lavorazione è sempre espressa nel riferimento globale. +// Note : Questa lavorazione � sempre espressa nel riferimento globale. // // Modifiche : 28.05.19 DS Creazione modulo. // @@ -18,6 +18,7 @@ #include "SurfFinishing.h" #include "OperationConst.h" #include "GeoConst.h" +#include "set" #include "/EgtDev/Include/EXeCmdLogOff.h" #include "/EgtDev/Include/EXeConst.h" #include "/EgtDev/Include/EGkCurveLine.h" @@ -37,6 +38,9 @@ #include "/EgtDev/Include/EGkUserObjFactory.h" #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkCurveAux.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointSurfFr.h" // per far dimenticare macro di WinUser.h #undef GetClassName @@ -68,11 +72,19 @@ using namespace std ; // 3123 = "Error in SurfFinishing : missing surfaces" // 3124 = "Error in SurfFinishing : region not computable" // 3125 = "Error in SurfFinishing : CalcPocketing failed" +// 3126 = "Error in SurfFinishing : Computing ZConst Curves failed" +// 3127 = "Error in SurfFinishing : Computing ZConst Paths failed" // 3151 = "Warning in SurfFinishing : Skipped entity (xx)" // 3152 = "Warning in SurfFinishing : No machinable path" // 3153 = "Warning in SurfFinishing : Tool name changed (xx)" // 3154 = "Warning in SurfFinishing : Tool data changed (xx)" +//---------------------------------------------------------------------------- +static string KEY_THICK = "THICK" ; +const double SILH_SAMPLING = 1. ; + +#define ENABLE_ZCONST_DEBUG 0 + //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_SURFFINISHING), SurfFinishing) ; @@ -450,14 +462,14 @@ SurfFinishing::SetParam( int nType, const string& sVal) bool SurfFinishing::SetGeometry( const SELVECTOR& vIds) { - // verifico validità gestore DB geometrico + // verifico validit� gestore DB geometrico if ( m_pGeomDB == nullptr) return false ; // reset della geometria corrente m_vId.clear() ; - // verifico che gli identificativi rappresentino delle entità ammissibili + // verifico che gli identificativi rappresentino delle entit� ammissibili for ( const auto& Id : vIds) { - // test sull'entità + // test sull'entit� int nSubs ; if ( ! VerifyGeometry( Id, nSubs)) { string sInfo = "Warning in SurfFinishing : Skipped entity " + ToString( Id) ; @@ -489,7 +501,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) int nCurrPaths = m_nPaths ; m_nPaths = 0 ; - // verifico validità gestore DB geometrico e Id del gruppo + // verifico validit� gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -500,7 +512,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) return false ; } - // non è prevista finitura superficie con aggregato da sotto + // non � prevista finitura superficie con aggregato da sotto if ( IsAggrBottom( m_TParams.m_sHead)) { m_pMchMgr->SetLastError( 3122, "Error in SurfFinishing : aggregate from bottom not allowed") ; return false ; @@ -526,7 +538,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; - // se non c'è, lo aggiungo + // se non c'�, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) @@ -563,7 +575,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; - // se non c'è, lo aggiungo + // se non c'�, lo aggiungo if ( nClId == GDB_ID_NULL) { nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nClId == GDB_ID_NULL) @@ -574,7 +586,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) else m_pGeomDB->EmptyGroup( nClId) ; - // lavoro ogni singola catena + // lavoro ogni singola regione piana bool bOk = true ; int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; while ( nPathId != GDB_ID_NULL) { @@ -606,7 +618,7 @@ SurfFinishing::Apply( bool bRecalc, bool bPostApply) bool SurfFinishing::Update( bool bPostApply) { - // verifico validità gestore DB geometrico e Id del gruppo + // verifico validit� gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -616,7 +628,7 @@ SurfFinishing::Update( bool bPostApply) return true ; } - // elimino le entità CLIMB, RISE e HOME della lavorazione, potrebbero falsare i calcoli degli assi (in ogni casi vengono riaggiunte dopo) + // elimino le entit� CLIMB, RISE e HOME della lavorazione, potrebbero falsare i calcoli degli assi (in ogni casi vengono riaggiunte dopo) RemoveClimbRiseHome() ; // imposto eventuale asse bloccato da lavorazione @@ -857,7 +869,7 @@ SurfFinishing::UpdateToolData( bool* pbChanged) bool SurfFinishing::GetGeometry( SELVECTOR& vIds) const { - // restituisco l'elenco delle entità + // restituisco l'elenco delle entit� vIds = m_vId ; return true ; } @@ -902,7 +914,7 @@ SurfFinishing::VerifyGeometry( SelData Id, int& nSubs) } return ( pCurve != nullptr) ; } - // se altrimenti è superficie trimesh + // se altrimenti � superficie trimesh else if ( pGObj->GetType() == SRF_TRIMESH) { const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; return ( pSurf != nullptr && pSurf->GetFacetCount() >= 1) ; @@ -927,7 +939,7 @@ SurfFinishing::GetCurves( SelData Id, ICURVEPLIST& lstPC) // se curva if ( ( pGObj->GetType() & GEO_CURVE) != 0) { PtrOwner pCurve ; - // se direttamente curva + // se direttamente curva if ( Id.nSub == SEL_SUB_ALL) { // recupero la curva const ICurve* pOriCurve = ::GetCurve( pGObj) ; @@ -940,7 +952,7 @@ SurfFinishing::GetCurves( SelData Id, ICURVEPLIST& lstPC) if ( ! pCurve->GetExtrusion( vtExtr) || vtExtr.IsSmall()) pCurve->SetExtrusion( Z_AX) ; } - // altrimenti sottocurva di composita + // altrimenti sottocurva di composita else { // recupero la composita const ICurveComposite* pCompo = GetCurveComposite( pGObj) ; @@ -1024,8 +1036,8 @@ SurfFinishing::Chain( int nGrpDestId) bFirst = false ; } } - // recupero i percorsi concatenati - int nCount = 0 ; + // recupero i percorsi concatenati e definisco la regione piana di svuotatura + SurfFlatRegionByContours SfrByC ; INTVECTOR vnId2 ; while ( chainC.GetChainFromNear( ptNear, false, vnId2)) { // creo una curva composita @@ -1066,22 +1078,78 @@ SurfFinishing::Chain( int nGrpDestId) // imposto estrusione e spessore pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; + // verifico sia piana e se necessario la appiattisco + PtrOwner pFlatCrv( FlattenCurve( *pCrvCompo, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ; + if ( IsNull( pFlatCrv)) { + Plane3d plPlane ; + if ( ! pCrvCompo->IsFlat( plPlane, true, 50 * EPS_SMALL)) + m_pMchMgr->SetLastError( 2403, "Error in SurfFinishing : Contour Not Flat") ; + else + m_pMchMgr->SetLastError( 2404, "Error in SurfFinishing : Tool Not Perpendicular to Flat Area") ; + return false ; + } + pFlatCrv->GetExtrusion( vtExtr) ; + pCrvCompo->Clear() ; + pCrvCompo->AddCurve( Release( pFlatCrv)) ; + // salvo vettore estrusione + pCrvCompo->SetExtrusion( vtExtr) ; + // salvo la thickness come seconda temp prop ( la Sfr rimuove la thick delle curve) + pCrvCompo->SetTempParam( dThick, 1) ; // aggiorno il nuovo punto vicino - pCrvCompo->GetEndPoint( ptNear) ; + pCrvCompo->GetEndPoint( ptNear) ; // se utile, approssimo con archi if ( ! ApproxWithArcsIfUseful( pCrvCompo)) return false ; - // creo nuovo gruppo - int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; - if ( nPathId == GDB_ID_NULL) - return false ; - m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ; - m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ; - // inserisco la curva composita nel gruppo destinazione - int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ; - if ( nNewId == GDB_ID_NULL) - return false ; + // inserisco la curva nella regione piana + SfrByC.AddCurve( Release( pCrvCompo)) ; } + + // scorro le regioni piane ricavate dalle curve + int nGroupName = -1 ; + PtrOwner pSfrCurr( SfrByC.GetSurf()) ; + while ( ! IsNull( pSfrCurr) && pSfrCurr->IsValid()) { + // per ogni Chunk + for ( int nC = 0 ; nC < pSfrCurr->GetChunkCount() ; ++ nC) { + // creo nuovo gruppo + int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; + if ( nPathId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nGroupName)) ; + m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( nGroupName)) ; + // recupero il Chunk corrente + PtrOwner pSfrChunk( pSfrCurr->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::CloneSurfFlatRegion( pSfrChunk)) ; + if ( nNewId == GDB_ID_NULL) + return false ; + // salvo eventuali lati aperti per il Chunk corrente + for ( int nL = 0 ; nL < pSfrChunk->GetLoopCount( 0) ; ++ nL) { + // recupero il Loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // memorizzo le propriet� di lato aperto nelle Info del gruppo + INTVECTOR vIndOpen ; + for ( int nU = 0 ; nU < pCrvLoop->GetCurveCount() ; ++ nU) { + int nTmpProp0 = TEMP_PROP_INVALID ; + if ( pCrvLoop->GetCurveTempProp( nU, nTmpProp0, 0) && nTmpProp0 == TEMP_PROP_OPEN_EDGE) + vIndOpen.emplace_back( nU) ; + } + // memorizzo la Thickness e l'Estrusione nelle Info del gruppo + if ( nL == 0) { + double dThick = pCrvLoop->GetTempParam( 1) ; + m_pGeomDB->SetInfo( nNewId, KEY_THICK, dThick) ; + Vector3d vtExtr ; + pCrvLoop->GetExtrusion( vtExtr) ; + m_pGeomDB->SetInfo( nNewId, KEY_EXTR, vtExtr) ; + } + } + } + // aggiorno la regione piana con la successiva calcolata + pSfrCurr.Set( SfrByC.GetSurf()) ; + } + return true ; } @@ -1092,7 +1160,7 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) // recupero gruppo per geometria temporanea const string GRP_TEMP = "Temp" ; int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; - // se non c'è, lo aggiungo + // se non c'�, lo aggiungo if ( nTempId == GDB_ID_NULL) { nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nTempId == GDB_ID_NULL) @@ -1106,51 +1174,26 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ; m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ; - // verifico sia una curva chiusa (deve delimitare l'area da svuotare) - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; - if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO) + // recupero la regione piana dal database geometrico + int nSfrId = m_pGeomDB->GetFirstInGroup( nPathId) ; + if ( m_pGeomDB->GetGeoType( nSfrId) != SRF_FLATRGN) return false ; - ICurve* pCrv = ::GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ; - if ( pCrv == nullptr || ! pCrv->IsClosed()) { - m_pMchMgr->SetLastError( 3104, "Error in SurfFinishing : Open Contour") ; - return false ; - } - // copio la curva composita da elaborare - int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; + // copio la regione piana da elaborare + int nCopyId = m_pGeomDB->CopyGlob( nSfrId, GDB_ID_NULL, nTempId) ; if ( nCopyId == GDB_ID_NULL) return false ; - ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; - - // recupero estrusione (vettore fresa) e spessore - Vector3d vtTool = Z_AX ; - pCompo->GetExtrusion( vtTool) ; - double dThick ; - pCompo->GetThickness( dThick) ; - - // verifico sia piana e sistemo senso antiorario visto dalla direzione di estrusione - Plane3d plPlane ; double dArea ; - if ( ! pCompo->GetArea( plPlane, dArea)) { - m_pMchMgr->SetLastError( 3105, "Error in SurfFinishing : Contour Not Flat") ; - return false ; - } - if ( abs( plPlane.GetVersN() * vtTool) < cos( 10 * EPS_ANG_SMALL)) { - m_pMchMgr->SetLastError( 3106, "Error in SurfFinishing : Tool Dir not perpendicular to Flat Area") ; - return false ; - } - if ( plPlane.GetVersN() * vtTool * dArea < 0) - pCompo->Invert() ; - - // unisco le parti allineate - if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true)) + PtrOwner pSfrGDB( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nCopyId))) ; + if ( IsNull( pSfrGDB) || ! pSfrGDB->IsValid()) return false ; - // recupero il box del grezzo in globale - BBox3d b3Raw ; - if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) { - m_pMchMgr->SetLastError( 3107, "Error in SurfFinishing : Empty RawBox") ; - return false ; - } + // recupero estrusione e spessore + Vector3d vtExtr = Z_AX ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_EXTR)) + m_pGeomDB->GetInfo( nSfrId, KEY_EXTR, vtExtr) ; + double dThick = 0. ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_THICK)) + m_pGeomDB->GetInfo( nSfrId, KEY_THICK, dThick) ; // valuto l'espressione dell'affondamento ExeLuaSetGlobNumVar( "TH", abs( dThick)) ; @@ -1160,6 +1203,36 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) m_pMchMgr->SetLastError( 3108, "Error in SurfFinishing : Depth not computable") ; return false ; } + // se spessore positivo, lo sottraggo al risuoltato + if ( dThick > 0) + dDepth -= dThick ; + + // recupero il box del grezzo in globale + BBox3d b3Raw ; + if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) { + m_pMchMgr->SetLastError( 3107, "Error in SurfFinishing : Empty RawBox") ; + return false ; + } + + // recupero il Loop esterno della regione da svuotatare + PtrOwner pCompo( ConvertCurveToComposite( pSfrGDB->GetLoop( 0, 0))) ; + if ( IsNull( pCompo) || ! pCompo->IsValid()) + return false ; + + // verifico sia piana e sistemo senso antiorario visto dalla direzione di estrusione + Plane3d plPlane ; double dArea ; + if ( ! pCompo->GetArea( plPlane, dArea)) { + m_pMchMgr->SetLastError( 3005, "Error in SurfFinishing : Contour Not Flat") ; + return false ; + } + if ( abs( plPlane.GetVersN() * vtExtr) < cos( 10 * EPS_ANG_SMALL)) { + m_pMchMgr->SetLastError( 3006, "Error in SurfFinishing : Tool Dir not perpendicular to Flat Area") ; + return false ; + } + if ( plPlane.GetVersN() * vtExtr * dArea < 0) + pCompo->Invert() ; + if ( plPlane.GetVersN() * vtExtr < 0) + plPlane.Invert() ; // recupero flag per saltare parti a massimo affondamento bool bSkipMaxDown = true ; @@ -1169,6 +1242,9 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) string sPathName ; m_pGeomDB->GetName( nPathId, sPathName) ; + // assegno il versore fresa + Vector3d vtTool = vtExtr ; + // se richiesta lavorazione if ( nClId != GDB_ID_NULL) { // creo gruppo per geometria di lavorazione del percorso @@ -1238,8 +1314,16 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ; return false ; } + for ( int nL = 1 ; nL < pSfrGDB->GetLoopCount( 0) ; ++ nL) { + // recupero l'isola + PtrOwner pCrvIsl( pSfrGDB->GetLoop( 0, nL)) ; + if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid() || + ! pSfrCnt->AddIntLoop( *pCrvIsl)) + return false ; + } + // se richiesto, elimino le parti al massimo affondamento - if ( bSkipMaxDown) { + if ( bSkipMaxDown && ( m_Params.m_nSubType != SURFFIN_SUB_Z_CONST)) { // calcolo silhouette dell'insieme di superfici CISURFTMPVECTOR vpStm ; vpStm.reserve( vSurfId.size()) ; for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) @@ -1294,7 +1378,7 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) pSfrCnt->Clear() ; pSfrCnt->AddExtLoop( *pCompo) ; } - // azzero le proprietà delle curve semplici dei contorni delle regioni ( se 1 lato aperto) + // azzero le propriet� delle curve semplici dei contorni delle regioni ( se 1 lato aperto) for ( int nC = 0 ; nC < pSfrCnt->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfrCnt->GetLoopCount( nC) ; ++ nL) { for ( int nCrv = 0 ; ; ++ nCrv) { @@ -1320,6 +1404,7 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) // Eseguo la lavorazione a seconda del tipo double dElev = dDepth ; + switch ( m_Params.m_nSubType) { case SURFFIN_SUB_ZIGZAG : if ( ! AddZigZag( pCAvTlStm, frSurf, pSfrCnt, vtTool, dDepth, dElev, bSplitArcs)) @@ -1337,6 +1422,11 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) if ( ! AddSpiral( pCAvTlStm, frSurf, pSfrCnt, vtTool, dDepth, dElev, bSplitArcs, false)) return false ; break ; + case SURFFIN_SUB_Z_CONST : + case SURFFIN_SUB_OPTIMAL : + if ( ! AddZConst( pCAvTlStm, vSrfLoc, frSurf, pSfrCnt, vtTool, dDepth, dElev, bSplitArcs)) + return false ; + break ; } } @@ -1346,6 +1436,47 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId) return true ; } +//---------------------------------------------------------------------------- +bool +SurfFinishing::SimplifyCurve( ICurveComposite* pCompo) const +{ + // controllo dei parametri + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + + // ricavo il punto iniziale e finale + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ; + + // eseguo le modifiche su una copia della curva originale + PtrOwner pCompoCL( CloneCurveComposite( pCompo)) ; + if ( IsNull( pCompoCL)) + return false ; + + // merge per uniformità + bool bOk = pCompoCL->MergeCurves( 200 * EPS_SMALL, 200 * EPS_ANG_SMALL, false) ; + // rimozione Spikes o Curve Z + bOk = bOk && pCompoCL->RemoveSmallDefects( 150 * EPS_SMALL, 2 * ANG_TOL_STD_DEG, true) ; + // interpolazione mediante linee ed archi + PolyArc PA ; + bOk = bOk && pCompoCL->ApproxWithArcsEx( 50 * EPS_SMALL, ANG_TOL_STD_DEG, LIN_FEA_STD, PA) && + pCompoCL->Clear() && pCompoCL->FromPolyArc( PA) ; + // controllo aggiuntivo sui punti iniziali e finali che siano gli stessi + Point3d ptNewStart, ptNewEnd ; + bOk = bOk && pCompoCL->GetStartPoint( ptNewStart) && pCompoCL->GetEndPoint( ptNewEnd) && + AreSamePointApprox( ptNewStart, ptStart) && AreSamePointApprox( ptNewEnd, ptEnd) ; + + // controllo che non si siano create auto-intersezioni + SelfIntersCurve SIC( *pCompoCL) ; + bOk = bOk && ( SIC.GetCrossIntersCount() == 0) ; + + // se tutto bene, sostiuisco la curva originale con la modificata + if ( bOk) + pCompo->CopyFrom( pCompoCL) ; + + return true ; +} + //---------------------------------------------------------------------------- bool SurfFinishing::GetActiveSurfaces( INTVECTOR& vSurfId) const @@ -1374,15 +1505,15 @@ SurfFinishing::GetActiveSurfaces( INTVECTOR& vSurfId) const // ciclo sui layer dei pezzi int nLayId = m_pGeomDB->GetFirstGroupInGroup( nPartId) ; while ( nLayId != GDB_ID_NULL) { - // ciclo sulle entità del layer + // ciclo sulle entit� del layer int nEntId = m_pGeomDB->GetFirstInGroup( nLayId) ; while ( nEntId != GDB_ID_NULL) { - // se entità superficie e visibile, la aggiungo + // se entit� superficie e visibile, la aggiungo int nStat ; if ( m_pGeomDB->GetGeoType( nEntId) == SRF_TRIMESH && m_pGeomDB->GetCalcStatus( nEntId, nStat) && nStat != GDB_ST_OFF) vSurfId.emplace_back( nEntId) ; - // passo alla entità successiva + // passo alla entit� successiva nEntId = m_pGeomDB->GetNext( nEntId) ; } nLayId =m_pGeomDB->GetNextGroup( nLayId) ; @@ -1472,9 +1603,9 @@ SurfFinishing::AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( IsNull( pCurve)) return false ; pCurve->ToGlob( frPocket) ; - // se prima entità + // se prima entit� if ( i == 0 ) { - // dati inizio entità + // dati inizio entit� Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -1536,9 +1667,9 @@ SurfFinishing::AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons SetFeed( GetRightFeed( vtMove, vtTool)) ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; - // se ultima entità + // se ultima entit� if ( i == nMaxInd) { - // dati fine entità + // dati fine entit� Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -1575,7 +1706,7 @@ SurfFinishing::AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( ! GetElevation( m_nPhase, ptEnd - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dEndElev)) dEndElev = dElev ; dEndElev -= ( ptP1 - ptEnd) * vtTool ; - // se non è ultimo tratto, aggiungo retrazione di collegamento + // se non � ultimo tratto, aggiungo retrazione di collegamento if ( k < int( vpCrvs.size()) - 1) { if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) { m_pMchMgr->SetLastError( 3112, "Error in SurfFinishing : Link not computable") ; @@ -1673,9 +1804,9 @@ SurfFinishing::AddOneWay( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( IsNull( pCurve)) return false ; pCurve->ToGlob( frPocket) ; - // se prima entità + // se prima entit� if ( i == 0 ) { - // dati inizio entità + // dati inizio entit� Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -1737,9 +1868,9 @@ SurfFinishing::AddOneWay( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons SetFeed( GetRightFeed( vtMove, vtTool)) ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; - // se ultima entità + // se ultima entit� if ( i == nMaxInd) { - // dati fine entità + // dati fine entit� Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -1776,7 +1907,7 @@ SurfFinishing::AddOneWay( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( ! GetElevation( m_nPhase, ptEnd - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dEndElev)) dEndElev = dElev ; dEndElev -= ( ptP1 - ptEnd) * vtTool ; - // se non è ultimo tratto, aggiungo retrazione di collegamento + // se non � ultimo tratto, aggiungo retrazione di collegamento if ( k < int( vpCrvs.size()) - 1) { if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) { m_pMchMgr->SetLastError( 3112, "Error in SurfFinishing : Link not computable") ; @@ -1874,9 +2005,9 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( IsNull( pCurve)) return false ; pCurve->ToGlob( frPocket) ; - // se prima entità + // se prima entit� if ( i == 0 ) { - // dati inizio entità + // dati inizio entit� Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -1938,9 +2069,9 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons SetFeed( GetRightFeed( vtMove, vtTool)) ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; - // se ultima entità + // se ultima entit� if ( i == nMaxInd) { - // dati fine entità + // dati fine entit� Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -1977,7 +2108,7 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons if ( ! GetElevation( m_nPhase, ptEnd - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dEndElev)) dEndElev = dElev ; dEndElev -= ( ptP1 - ptEnd) * vtTool ; - // se non è ultimo tratto, aggiungo retrazione di collegamento + // se non � ultimo tratto, aggiungo retrazione di collegamento if ( false) { if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) { m_pMchMgr->SetLastError( 3112, "Error in SurfFinishing : Link not computable") ; @@ -1998,12 +2129,768 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons return true ; } +//---------------------------------------------------------------------------- +bool +SurfFinishing::GetZConstFacesInsideSfr( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, set& setZAmbiguos) +{ + // controllo dei parametri + setZAmbiguos.clear() ; + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + + // creo un frame centrato sulla superficie + Frame3d frSfr ; + Point3d ptC ; pSfr->GetCentroid( ptC) ; + if ( ! frSfr.Set( ptC, pSfr->GetNormVersor()) || ! frSfr.IsValid()) + return false ; + // porto una copia della superficie in questo frame + PtrOwner pSfrLoc( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfrLoc) || ! pSfrLoc->IsValid() || ! pSfrLoc->ToLoc( frSfr)) + return false ; + + // scorro le superfici trimesh selezionate + for ( int nS = 0 ; nS < int( vSrfLoc.size()) ; ++ nS) { + // recupero la superficie + PtrOwner pStm( CloneSurfTriMesh( GetSurfTriMesh( vSrfLoc[nS].Get()))) ; + if ( IsNull( pStm) || ! pStm->IsValid()) + return false ; + // scorro le facce + for ( int nF = 0 ; nF < pStm->GetFacetCount() ; ++ nF) { + // recupero il centro e la normale della faccia + Point3d ptCenter ; + Vector3d vtNorm ; + if ( pStm->GetFacetCenter( nF, ptCenter, vtNorm)) { + vtNorm.ToGlob( frSurf) ; + if ( AreSameVectorEpsilon( vtNorm, vtTool, 10 * EPS_SMALL)) { + // recupero i contorni della faccia + POLYLINEVECTOR vPL ; + if ( pStm->GetFacetLoops( nF, vPL)) { + // recupero la superficie piana dalle curve + SurfFlatRegionByContours SfrByC ; + for ( int nPL = 0 ; nPL < int( vPL.size()) ; ++ nPL) { + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[nPL])) + return false ; + // porto la curva nel riferimento globale + pCrvCompo->ToGlob( frSurf) ; + // porto la curva nel riferimento della pSfr (per la classificazione) + pCrvCompo->ToLoc( frSfr) ; + // aggiungo la curva alla FlatRegion + SfrByC.AddCurve( Release( pCrvCompo)) ; + } + // recupero la superficie + PtrOwner pSfrFace( SfrByC.GetSurf()) ; + if ( IsNull( pSfrFace) || ! pSfrFace->IsValid()) + return false ; + // se esiste intersezione tra pSfrFace e pSfr allora salvo la Z locale + pSfrFace->Intersect( *pSfrLoc) ; + if ( ! IsNull( pSfrFace) && pSfrFace->IsValid()) { + // porto il punto nel riferimento della superficie + ptCenter.ToGlob( frSurf) ; + ptCenter.ToLoc( frSfr) ; + // inserisco la Z del piano locale nell'insieme + setZAmbiguos.insert( ptCenter.z) ; + } + } + } + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +ICAvParSilhouettesSurfTm* +SurfFinishing::GetParSilhouettesForZConst( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, + const ISurfFlatRegion* pSfr) const +{ + // controllo dei parametri + if ( vSrfLoc.empty() || ! frSurf.IsValid() || pSfr == nullptr || ! pSfr->IsValid()) + return nullptr ; + + // inizializzo la classe di calcolo delle silhouette nei piani come sopra + CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ; + for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) { + ISurfTriMesh* pStm = CloneSurfTriMesh( GetSurfTriMesh( vSrfLoc[i].Get())) ; + if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0) { + pStm->ToGlob( frSurf) ; + vpStm.emplace_back( pStm) ; + } + else { + delete( pStm) ; + pStm = nullptr ; + } + } + const double SILH_SHARPED_ANG_TOL = ( ANG_TOL_STD_DEG / 3.) ; + PtrOwner pCavParSilh( CreateCAvParSilhouettesSurfTm()) ; + if ( IsNull( pCavParSilh) || + ! pCavParSilh->SetDataForRegion( vpStm, pSfr, m_TParams.m_dSideAng, m_TParams.m_dDiam, + m_TParams.m_dCornRad, m_TParams.m_dMaxMat, GetOffsR(), SILH_SAMPLING, SILH_SHARPED_ANG_TOL)) + return nullptr ; + + return ( Release( pCavParSilh)) ; +} + +//---------------------------------------------------------------------------- +bool +SurfFinishing::CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, double dDepth, vector& vCrvCompo) +{ + /* funzione per calcolare le curve singole di finitura mediante Silhouette e le regioni da non rovinare */ + + // controllo che la regione piana sia definita correttamente + vCrvCompo.clear() ; + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + + // NB. Essendo una finitura a Z costante, devo controllare che i piani di finitura non facciano + // overlap con facce delle TriMesh selezionate con normale simile a vtTool + set setZAmbiguos ; + PtrOwner pSfrZAmb( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfrZAmb) || ! pSfrZAmb->IsValid() || + ! pSfrZAmb->Offset( m_TParams.m_dDiam / 2. + abs( m_Params.m_dOverlap), ICurve::OFF_FILLET)) + return false ; + if ( ! GetZConstFacesInsideSfr( vSrfLoc, frSurf, pSfrZAmb, vtTool, setZAmbiguos)) + return false ; + + // calcolo la silhouette sui diversi piani + for ( int nPlane = 1 ; nPlane * m_Params.m_dSideStep < dDepth + EPS_SMALL ; ++ nPlane) { + // riservo lo spazio nel vettore delle curve + vCrvCompo.resize( vCrvCompo.size() + 1) ; + // definisco la Zlocale per il calcolo della silhouette + double dZLoc = - nPlane * m_Params.m_dSideStep ; + for ( set::iterator it = setZAmbiguos.begin() ; it != setZAmbiguos.end() ; ++ it) { + if ( abs( *it - dZLoc) < 5 * EPS_SMALL) + dZLoc += ( nPlane == 1 ? - 10 * EPS_SMALL : + 10 * EPS_SMALL) ; + } + // calcolo vettore di PolyLine ottenute al piano corrente + POLYLINEVECTOR vPL ; + if ( ! pCavParSilh->GetSilhouetteInsideRegion( dZLoc, vPL)) + return false ; + for ( auto& PL : vPL) { + // recupero la curva dalla silhouette + PtrOwner pSilCrv( CreateCurveComposite()) ; + if ( IsNull( pSilCrv)) + return false ; + pSilCrv->FromPolyLine( PL) ; + // approssimo con archi + const double SILH_ARC_TOL = 0.1 * SILH_SAMPLING ; + const double SILH_ARC_FEA_MAX = 100. ; + PolyArc PA ; + if ( pSilCrv->ApproxWithArcsEx( SILH_ARC_TOL, ANG_TOL_STD_DEG, SILH_ARC_FEA_MAX, PA)) { + PtrOwner pTempCrv( CreateCurveComposite()) ; + if ( ! IsNull( pTempCrv) && + pTempCrv->FromPolyArc( PA) && + pTempCrv->RemoveSmallDefects( SILH_ARC_TOL / 2., ANG_TOL_STD_DEG) && + pTempCrv->MergeCurves( SILH_ARC_TOL / 2., ANG_TOL_STD_DEG)) + pSilCrv.Set( pTempCrv) ; + } + SimplifyCurve( pSilCrv) ; + vCrvCompo.back().emplace_back( Release( pSilCrv)) ; + } + // controllo validità delle curve + for ( int i = 0 ; i < int( vCrvCompo.back().size()) ; ++ i) + if ( vCrvCompo.back()[i] == nullptr || ! vCrvCompo.back()[i]->IsValid()) + return false ; + // preparo i dati per il concatenamento + bool bFirst = true ; + Point3d ptNear = ORIG ; + double dToler = 500 * EPS_SMALL ; + ChainCurves chainC ; + chainC.Init( false, dToler, int( vCrvCompo.back().size())) ; + for ( int i = 0 ; i < int( vCrvCompo.back().size()) ; ++ i) { + // recupero i dati della curva necessari al concatenamento e li assegno + Point3d ptStart, ptEnd ; + Vector3d vtStart, vtEnd ; + if ( ! vCrvCompo.back()[i]->GetStartPoint( ptStart) || ! vCrvCompo.back()[i]->GetStartDir( vtStart) || + ! vCrvCompo.back()[i]->GetEndPoint( ptEnd) || ! vCrvCompo.back()[i]->GetEndDir( vtEnd)) + return false ; + if ( ! chainC.AddCurve( int( i + 1), ptStart, vtStart, ptEnd, vtEnd)) + return false ; + // se prima curva, assegno inizio della ricerca + if ( bFirst) { + ptNear = ptStart + 10 * EPS_SMALL * vtStart ; + bFirst = false ; + } + } + // vettore delle curve composite risultante + ICRVCOMPOPOVECTOR vCrvCompoChained ; + // recupero i percorsi concatenati + INTVECTOR vnInd ; + while ( chainC.GetChainFromNear( ptNear, true, vnInd)) { + // creo una curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + // recupero le curve semplici e le inserisco nella curva composita + for ( size_t i = 0 ; i < vnInd.size() ; ++ i) { + int nId = abs( vnInd[i]) - 1 ; + // la aggiungo alla curva composta + if ( ! pCrvCompo->AddCurve( CloneCurveComposite( vCrvCompo.back()[nId]), true, dToler)) + return false ; + } + // aggiorno il nuovo punto vicino + if ( pCrvCompo->GetCurveCount() > 0) { + pCrvCompo->GetEndPoint( ptNear) ; + vCrvCompoChained.emplace_back( Release( pCrvCompo)) ; + } + } + swap( vCrvCompoChained, vCrvCompo.back()) ; + // salvo lo Step come primo temp param della curva e inverto se necessario + for ( int i = 0 ; i < int( vCrvCompo.back().size()) ; ++ i) { + vCrvCompo.back()[i]->SetTempParam( - nPlane * m_Params.m_dSideStep, 0) ; + if ( m_Params.m_bInvert) + vCrvCompo.back()[i]->Invert() ; + } + } + + // 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) { + if ( vCrvCompo[i][j] == nullptr || ! vCrvCompo[i][j]->IsValid()) + return false ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, + vector& vCrvCompo, const Vector3d& vtTool, const ISurfFlatRegion* pSfr, + double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) +{ + /* funzione per collegare le curve trovate creando quindi i percorsi di lavoro */ + // NB. La prima tempProp della curva è il piano in cui iniziale e la seconda tempProp è + // il piano a cui finisce + + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + PtrOwner pSfrClass( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfrClass) || ! pSfrClass->IsValid()) + return false ; + + // porto tutte le curve nel piano XY locale alla pSfr + Frame3d frXY ; + Point3d ptCenter ; pSfr->GetCentroid( ptCenter) ; + if ( ! frXY.Set( ptCenter, vtTool)) + return false ; + for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + for ( int j = 0 ; j < int( vCrvCompo[i].size()) ; ++ j) { + vCrvCompo[i][j]->ToLoc( frXY) ; + #if ENABLE_ZCONST_DEBUG + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvCompo[i][j]->Clone()) ; + m_pGeomDB->SetMaterial( _a, WHITE) ; + #endif + } + } + // tengo una copia dei bordi della regione + pSfrClass->ToLoc( frXY) ; + #if ENABLE_ZCONST_DEBUG + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrClass->Clone()) ; + m_pGeomDB->SetMaterial( _a, Color( 0., 1., 0., .15)) ; + #endif + ICRVCOMPOPOVECTOR vCrvSfrLoops ; + for ( int nC = 0 ; nC < pSfrClass->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrClass->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrClass->GetLoop( nC, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // tutti i loop sono orientati come il loop esterno ( aiuta per la classificazione della curve) + if ( nL > 0) + pCrvLoop->Invert() ; + vCrvSfrLoops.emplace_back( Release( pCrvLoop)) ; + #if ENABLE_ZCONST_DEBUG + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvSfrLoops.back()->Clone()) ; + m_pGeomDB->SetMaterial( _a, PURPLE) ; + #endif + + } + } + // definisco il piano locale della regione piana + Plane3d plProjection ; + if ( ! plProjection.Set( ORIG, Z_AX)) + return false ; + + int nCurrRow = 0 ; + // scorro le righe + for ( ; nCurrRow < int( vCrvCompo.size()) - 1 ; ++ nCurrRow) { + // scorro sulle colonne + for ( int nCurrCol = 0 ; nCurrCol < int( vCrvCompo[nCurrRow].size()) ; ++ nCurrCol) { + // se la curva attuale � nulla, passo alla successiva + if ( vCrvCompo[nCurrRow][nCurrCol] == nullptr) + continue ; + // recupero il punto finale della curva corrente + Point3d ptCurrEnd ; vCrvCompo[nCurrRow][nCurrCol]->GetEndPoint( ptCurrEnd) ; + // recupero la distanza con la Sfr + double dSfrDistCurr = vCrvCompo[nCurrRow][nCurrCol]->GetTempParam( 0) ; + // inizializzo spazio per un nuovo percorso ( inserisco la curva corrente) + vCrvPath.resize( vCrvPath.size() + 1) ; + vCrvPath.back().Set( vCrvCompo[nCurrRow][nCurrCol]) ; + // salvo come prima temp prop il numero del piano a cui sono + vCrvPath.back()->SetTempProp( nCurrRow + 1, 0) ; + // scorro sulle righe successive + for ( int nNextRow = nCurrRow + 1 ; nNextRow < int( vCrvCompo.size()) ; ++ nNextRow) { + // cerco le curve valide tra le colonne + double dMinSqDist = INFINITO ; // euristico + int nNextCol_path = -1 ; + for ( int nNextCol = 0 ; nNextCol < int( vCrvCompo[nNextRow].size()) ; ++ nNextCol) { + // se curva già in un Path, cerco la successiva + if ( vCrvCompo[nNextRow][nNextCol] == nullptr) + continue ; + // se la curva successiva è aperta + if ( ! vCrvCompo[nNextRow][nNextCol]->IsClosed()) { + // controllo la distanza con il punto iniziale della curva + Point3d ptS ; vCrvCompo[nNextRow][nNextCol]->GetStartPoint( ptS) ; + double dNextSqDist = SqDist( ptS, ptCurrEnd) ; + if ( dNextSqDist < dMinSqDist) { + dMinSqDist = dNextSqDist ; + nNextCol_path = nNextCol ; + } + // controllo la distanza con il punto finale della curva + Point3d ptE ; vCrvCompo[nNextRow][nNextCol]->GetEndPoint( ptE) ; + dNextSqDist = SqDist( ptE, ptCurrEnd) ; + if ( dNextSqDist < dMinSqDist) { + dMinSqDist = dNextSqDist ; + nNextCol_path = nNextCol ; + vCrvCompo[nNextRow][nNextCol]->Invert() ; // inverto + } + } + // se la curva successiva è chiusa + else { + // cerco il punto a minima distanza + DistPointCurve DistPtCrv( ptCurrEnd, *vCrvCompo[nNextRow][nNextCol]) ; + double dNextSqDist = 0. ; + if ( DistPtCrv.GetSqDist( dNextSqDist)) { + if ( dNextSqDist < dMinSqDist) { + dMinSqDist = dNextSqDist ; + nNextCol_path = nNextCol ; + double dMinPar = 0. ; + int nFlag = 0 ; + if ( DistPtCrv.GetParamAtMinDistPoint( 0., dMinPar, nFlag)) + vCrvCompo[nNextRow][nNextCol]->ChangeStartPoint( dMinPar) ; + } + } + } + } + // se la curva risulta troppo distante o non ho trovato nessuna colonna valida + if ( /*dMinSqDist > m_Params.m_dSideStep * m_Params.m_dSideStep * 1000 ||*/ nNextCol_path == -1) { + nCurrRow = 0 ; // azzero il contatore delle righe + break ; // interrompo ciclo sulle righe successive di ricerca + } + // altrimenti creo raccordo e aggiungo la curva al percorso + else { + // definisco un tratto lineare che collega gli estremi + Point3d ptStartLink = ptCurrEnd ; + Point3d ptEndLink ; vCrvCompo[nNextRow][nNextCol_path]->GetStartPoint( ptEndLink) ; + PtrOwner pLineLink( CreateCurveLine()) ; + if ( IsNull( pLineLink) || ! pLineLink->Set( ptStartLink, ptEndLink) || + ! pLineLink->IsValid()) + return false ; + + #if ENABLE_ZCONST_DEBUG + int _b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pLineLink->Clone()) ; + m_pGeomDB->SetMaterial( _b, ORANGE) ; + #endif + + // se la linea è parallela a vtTool, allora ho una parete verticale (localmente) + Vector3d vtLineLink ; pLineLink->GetStartDir( vtLineLink) ; + if ( AreSameOrOppositeVectorEpsilon( vtLineLink, vtTool, 25 * EPS_SMALL)) { + // in questo caso la proiezione del link � automaticamente sul bordo della pSrfClass + vCrvPath.back()->AddCurve( Release( pLineLink), true, 1500 * EPS_SMALL) ; + vCrvPath.back()->AddCurve( Release( vCrvCompo[nNextRow][nNextCol_path]), true, 1500 * EPS_SMALL) ; + } + // se il collegamento non è parallelo a vtTool + else { + // in questo caso proietto la curva nel piano locale della pSfrClass ( Z=0 ; Z_AX()) + PtrOwner pLineLinkProjected( ProjectCurveOnPlane( *pLineLink, plProjection)) ; + if ( IsNull( pLineLinkProjected) || ! pLineLinkProjected->IsValid()) + return false ; + + #if ENABLE_ZCONST_DEBUG + int _c = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pLineLinkProjected->Clone()) ; + m_pGeomDB->SetMaterial( _c, YELLOW) ; + #endif + + // classifico la curva proiettata in base alla superficie + CRVCVECTOR ccClass ; + if ( ! pSfrClass->GetCurveClassification( *pLineLinkProjected, EPS_SMALL, ccClass)) + return false ; + // inizializzo la nuova curva di Link + PtrOwner pCompoLink( CreateCurveComposite()) ; + if ( IsNull( pCompoLink)) + return false ; + // scorro sulle classificazioni ottenute + for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { + // recupero il tratto di curva corrente + PtrOwner pCrv( pLineLinkProjected->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ; + if ( IsNull( pCrv) || ! pCrv->IsValid()) // troppo piccolo... + continue ; // passo al tratto di classificazione successivo + // se la curva non è esterna alla regione, allora la conservo (non rivina le Stm) + if ( ccClass[i].nClass != CRVC_OUT) { + if ( ! pCompoLink->AddCurve( Release( pCrv), true, 25 * EPS_SMALL)) + return false ; + } + // se la curva è esterna, allora devo seguire il bordo della regione di classificazione + else { + // recupero gli estremi del segmento di classificazione esterno alla pSfrClass + Point3d ptS_sfr ; pLineLinkProjected->GetPointD1D2( ccClass[i].dParS, ICurve::FROM_MINUS, ptS_sfr) ; + Point3d ptE_sfr ; pLineLinkProjected->GetPointD1D2( ccClass[i].dParE, ICurve::FROM_MINUS, ptE_sfr) ; + // scorro tutti i loop della regione di classificazione + for ( int j = 0 ; j < int( vCrvSfrLoops.size()) ; ++ j) { + // se i punti trovati sono sul loop corrente + if ( vCrvSfrLoops[j]->IsPointOn( ptS_sfr, 25 * EPS_SMALL) && + vCrvSfrLoops[j]->IsPointOn( ptE_sfr, 25 * EPS_SMALL)) { + // devo capire quale delle due curve (pCrvA, pCrvB) devo seguire sul bordo + double dUS ; vCrvSfrLoops[j]->GetParamAtPoint( ptS_sfr, dUS, 25 * EPS_SMALL) ; + double dUE ; vCrvSfrLoops[j]->GetParamAtPoint( ptE_sfr, dUE, 25 * EPS_SMALL) ; + PtrOwner pCrvA( ConvertCurveToComposite( vCrvSfrLoops[j]->CopyParamRange( dUS, dUE))) ; + PtrOwner pCrvB( ConvertCurveToComposite( vCrvSfrLoops[j]->CopyParamRange( dUE, dUS))) ; + // tra le due curve (pCrvA, pCrvB) scelgo quella con lunghezza minore + double dLenA = INFINITO ; double dLenB = INFINITO ; + if ( ! IsNull( pCrvA) && pCrvA->IsValid()) + pCrvA->GetLength( dLenA) ; + if ( ! IsNull( pCrvB) && pCrvB->IsValid()) { + // la pCrvB è sempre percorsa in senso opposto + pCrvB->Invert() ; + pCrvB->GetLength( dLenB) ; + } + // aggiungo la curva + if ( ! pCompoLink->AddCurve( dLenA < dLenB ? Release( pCrvA) : Release( pCrvB), true, 25 * EPS_SMALL)) + return false ; + } + } + } + } + // se il link trovato non è valido, errore + if ( ! pCompoLink->IsValid()) + return false ; + + // porto il link sulla curva attuale di silhouette e lo proietto sulla pStm + pCompoLink->Translate( vtTool * dSfrDistCurr) ; + + #if ENABLE_ZCONST_DEBUG + int _d = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoLink->Clone()) ; + m_pGeomDB->SetMaterial( _d, LIME) ; + #endif + + if ( ! CalcZConstProjectedLink( pCAvTlStm, frXY, frSurf, vtTool, dDepth, ptStartLink, ptEndLink, pCompoLink)) + return false ; + + #if ENABLE_ZCONST_DEBUG + int _e = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoLink->Clone()) ; + m_pGeomDB->SetMaterial( _e, RED) ; + #endif + + // aggiungo le curve ritrovate al percorso attuale + if ( ! vCrvPath.back()->AddCurve( Release( pCompoLink), true, 1500 * EPS_SMALL) || + ! vCrvPath.back()->AddCurve( Release( vCrvCompo[nNextRow][nNextCol_path]), true, 1500 * EPS_SMALL)) + return false ; + } + vCrvPath.back()->GetEndPoint( ptCurrEnd) ; // aggiorno il punto finale del percorso + vCrvPath.back()->SetTempProp( nNextRow + 1, 1) ; // salvo come seconda temp prop il piano a cui sono + } + } + } + } + // se non ho percorsi, non faccio nulla + if ( vCrvPath.empty()) + return true ; + // se ho percorsi non validi, errore + for ( int i = 0 ; i < int( vCrvPath.size()) ; ++ i) { + if ( vCrvPath[i] == nullptr || ! vCrvPath[i]->IsValid()) + return false ; + } + + // preso come riferimento il primo percorso, ordino i successivi in base alla vicinanza + Point3d ptRef ; vCrvPath.front()->GetEndPoint( ptRef) ; + double dSqMaxDist = INFINITO ; + for ( int i = 1 ; i < int( vCrvPath.size()) ; ++ i) { + int nNextInd = i + 1 ; + for ( int j = nNextInd ; j < int( vCrvPath.size()) ; ++ j) { + Point3d ptS ; vCrvPath[j]->GetStartPoint( ptS) ; + double dCurrSqDist = SqDist( ptS, ptRef) ; + if ( dCurrSqDist < dSqMaxDist) { + dSqMaxDist = dCurrSqDist ; + nNextInd = j ; + } + } + if ( nNextInd != i + 1) + swap( vCrvPath[i], vCrvPath[nNextInd]) ; + dSqMaxDist = INFINITO ; + } + + // riporto i percorsi nel frame originale + for ( int i = 0 ; i < int( vCrvPath.size()) ; ++ i) + vCrvPath[i]->ToGlob( frXY) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfFinishing::CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, + const Point3d ptStart_forced, const Point3d ptEnd_forced, + ICurveComposite* pCrv) +{ + /* funzione per proiettare una curva su una supericie trimesh passando per la silhouette */ + // controllo dei parametri + if ( pCAvTlStm == nullptr || + pCrv == nullptr || ! pCrv->IsValid()) + return false ; + // approssimo la curva con una polilinea + PolyLine PL ; + if ( ! pCrv->ApproxWithLines( m_Params.m_dApprox, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) + return false ; + // eventuale aggiunta di punti per garantire max distanza + const double MIN_DIST = 1. ; + const double MAX_DIST = 50. ; + double dDist = Clamp( m_TParams.m_dDiam / 2, MIN_DIST, MAX_DIST) ; + if ( ! PL.AdjustForMaxSegmentLen( dDist)) + return false ; + // porto nel riferimento delle superfici + PL.LocToLoc( frPocket, frSurf) ; + // porto i dati geometrici in locale alle superfici + Vector3d vtAxL = vtTool ; + vtAxL.ToLoc( frSurf) ; + Vector3d vtMoveL = vtAxL ; + // traslo della lunghezza utensile diminuita dell'affondamento + PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ; + // eseguo il test del percorso + if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox)) + return false ; + // contro-traslo della lunghezza utensile + PL.Translate( - vtAxL * m_TParams.m_dLen) ; + // riporto la polilinea nel riferimento della curva + PL.LocToLoc( frSurf, frPocket) ; + // elimino i punti allineati + PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ; + // sostituisco primo ed ultimo punto con quelli forzati + PL.EraseFirstUPoint() ; + PL.EraseLastUPoint() ; + PL.AddUPoint( 0, ptStart_forced, false) ; + PL.AddUPoint( PL.GetPointNbr(), ptEnd_forced, true) ; + // creo una curva composita a partire dalla polilinea + PtrOwner< ICurveComposite> pCompo( CreateCurveComposite()) ; + if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) + return false ; + // sostituisco la vecchia curva con la nuova + pCrv->CopyFrom( pCompo) ; + return true ; +} + +//---------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------- +bool +SurfFinishing::AddZConst( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs) +{ + + // controllo che la regione sia definita correttamente + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + // aggiusto la regione a seconda dei parametri + PtrOwner pSfrClass( pSfr->CreateOffsetSurf( - m_TParams.m_dDiam / 2. + m_Params.m_dOverlap, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrClass) || ! pSfrClass->IsValid()) + return false ; + + // inizializzo la classe di calcolo delle silhouette nei piani come sopra + PtrOwner pCavParSilh( GetParSilhouettesForZConst( vSrfLoc, frSurf, pSfrClass)) ; + if ( IsNull( pCavParSilh)) + return false ; + + // recupero le curve singole definite dal bordo della Silhouette + vector vCrvCompo ; + if ( ! CalcZConstSilCrv( pCavParSilh, vSrfLoc, frSurf, pSfrClass, vtTool, dDepth, vCrvCompo)) { + m_pMchMgr->SetLastError( 3126, "Error in SurfFinishing : Computing ZConst Curves failed") ; + return false ; + } + // se non ho curve, esco + if ( vCrvCompo.empty()) + return true ; + + // collego tra loro le curve trovate + ICRVCOMPOPOVECTOR vCrvPath ; + if ( ! CreateZConstPaths( pCAvTlStm, vSrfLoc, frSurf, vCrvCompo, vtTool, pSfrClass, dDepth, vCrvPath)) { + m_pMchMgr->SetLastError( 3127, "Error in SurfFinishing : Computing ZConst Paths failed") ; + return false ; + } + // se non ho percorsi, errore + if ( vCrvPath.empty()) + return false ; + + // recupero distanze di sicurezza + double dSafeZ = GetSafeZ() ; + // lunghezza di approccio/retrazione + double dAppr = m_Params.m_dStartPos ; + + // ciclo sulle curve risultanti + bool bStart = true ; + for ( int k = 0 ; k < int( vCrvPath.size()) ; ++ k) { + // determino in che piano di partenza e il piano di arrivo + int nStartPlane = vCrvPath[k]->GetTempProp( 0) ; + int nEndPlane = vCrvPath[k]->GetTempProp( 1) ; + // ciclo sulle curve elementari + int nMaxInd = vCrvPath[k]->GetCurveCount() - 1 ; + for ( int i = 0 ; i <= nMaxInd ; ++ i) { + // curva corrente + const ICurve* pCrvC = vCrvPath[k]->GetCurve( i) ; + // copio la curva + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) + return false ; + // se prima entità + if ( i == 0) { + // dati inizio entità + Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; + Vector3d vtStart ; pCurve->GetStartDir( vtStart) ; + // vettore tangente iniziale non deve salire rispetto a estrusione (poi si prende opposto) + double dStartOnExtr = vtStart * vtTool ; + if ( dStartOnExtr > 0) { + vtStart -= dStartOnExtr * vtTool ; + vtStart.Normalize() ; + } + // determino normale della superficie sul punto iniziale + Vector3d vtNorm ; + if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptStart, vtTool, vtNorm)) { + Point3d ptEnd ; + pCurve->GetEndPoint( ptEnd) ; + if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptEnd, vtTool, vtNorm)) + vtNorm = V_NULL ; + } + // determino inizio attacco + Point3d ptP1 ; + if ( ! CalcLeadInStart( ptStart, vtStart, vtTool, vtNorm, ptP1)) + return false ; + // eventuale correzione inizio attacco per evitare interferenze + if ( ! GetLastGoodPoint( pCAvTlStm, frSurf, ptStart, ptP1, vtTool, ptP1)) + return false ; + // controllo che tale punto sia al di fuori della regione piana + bool bIsInside = false ; + if ( IsPointInsideSurfFr( ptP1 + vtTool * ( m_Params.m_dSideStep * nStartPlane), pSfrClass, EPS_SMALL, bIsInside)) + ptP1 = ptStart ; + // determino elevazione su inizio attacco + double dStElev ; + if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) + dStElev = dElev ; + dStElev -= ( ptP1 - ptStart) * vtTool ; + // se inizio, approccio globale al punto iniziale + if ( bStart) { + if ( ! AddApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) { + m_pMchMgr->SetLastError( 3111, "Error in SurfFinishing : Approach not computable") ; + return false ; + } + bStart = false ; + } + // altrimenti, approccio di collegamento + else { + if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) { + m_pMchMgr->SetLastError( 3112, "Error in SurfFinishing : Link not computable") ; + return false ; + } + } + // aggiungo attacco + SetFeed( GetStartFeed()) ; + if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtTool, bSplitArcs)) { + m_pMchMgr->SetLastError( 3113, "Error in SurfFinishing : LeadIn not computable") ; + return false ; + } + } + // elaborazioni sulla curva corrente (sempre un segmento di retta) + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + Vector3d vtMove ; pLine->GetStartDir( vtMove) ; + SetFeed( GetRightFeed( vtMove, vtTool)) ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) + return false ; + } + else if ( pCurve->GetType() == CRV_ARC) { + ICurveArc* pArc = GetCurveArc( pCurve) ; + Point3d ptCen = pArc->GetCenter() ; + double dAngCen = pArc->GetAngCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + Point3d ptP3 ; pArc->GetEndPoint( ptP3) ; + SetFeed( GetFeed()) ; + if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) + return false ; + } + // se ultima entità + if ( i == nMaxInd) { + // dati fine entità + Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; pCurve->GetEndDir( vtEnd) ; + // vettore tangente finale non deve scendere rispetto a estrusione + double dEndOnExtr = vtEnd * vtTool ; + if ( dEndOnExtr < 0) { + vtEnd -= dEndOnExtr * vtTool ; + vtEnd.Normalize() ; + } + // determino normale della superficie sul punto finale + Vector3d vtNorm ; + if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptEnd, vtTool, vtNorm)) { + Point3d ptStart ; + pCurve->GetStartPoint( ptStart) ; + if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptStart, vtTool, vtNorm)) + vtNorm = V_NULL ; + } + // determino fine uscita + Point3d ptP1 ; + if ( ! CalcLeadOutEnd( ptEnd, vtEnd, vtTool, vtNorm, ptP1)) + return false ; + // eventuale correzione fine uscita per evitare interferenze + if ( ! GetLastGoodPoint( pCAvTlStm, frSurf, ptEnd, ptP1, vtTool, ptP1)) + return false ; + // controllo che tale punto sia al di fuori della regione piana + bool bIsInside = false ; + if ( IsPointInsideSurfFr( ptP1 + vtTool * ( m_Params.m_dSideStep * nStartPlane), pSfrClass, EPS_SMALL, bIsInside)) + ptP1 = ptEnd ; + // se ultima uscita globale del percorso + if ( k == int( vCrvPath.size()) - 1) { + // aggiungo LeadOut + SetFeed( GetEndFeed()) ; + if ( ! AddLeadOut( ptEnd, vtEnd, ptP1, vtTool, bSplitArcs)) { + m_pMchMgr->SetLastError( 3114, "Error in SurfFinishing : LeadOut not computable") ; + return false ; + } + // aggiungo retroazione finale + if ( ! AddRetract( ptP1, vtTool, dSafeZ, nEndPlane * m_Params.m_dSideStep, dAppr)) { + m_pMchMgr->SetLastError( 3115, "Error in SurfFinishing : Retract not computable") ; + return false ; + } + } + // altrimenti + else { + // determino elevazione su fine uscita + double dEndElev ; + if ( ! GetElevation( m_nPhase, ptEnd - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dEndElev)) + dEndElev = dElev ; + dEndElev -= ( ptP1 - ptEnd) * vtTool ; + if ( ! AddRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) { + m_pMchMgr->SetLastError( 3115, "Error in SurfFinishing : Retract not computable") ; + return false ; + } + } + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfFinishing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) { SetFlag( 1) ; - // se sopra attacco c'è spazio per sicurezza o approccio + // se sopra attacco c'� spazio per sicurezza o approccio double dSafeDist = dSafeZ ; if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { // se distanza di sicurezza minore di distanza di inizio @@ -2045,7 +2932,7 @@ SurfFinishing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double d bool SurfFinishing::AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) { - // se sopra attacco c'è spazio per approccio + // se sopra attacco c'� spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 1b -> punto appena sopra inizio Point3d ptP1b = ptP + vtTool * ( dElev + dAppr) ; @@ -2073,7 +2960,7 @@ SurfFinishing::AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, doub bool SurfFinishing::AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) { - // se sopra uscita c'è spazio per approccio + // se sopra uscita c'� spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 4 -> movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; @@ -2088,7 +2975,7 @@ SurfFinishing::AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, doubl bool SurfFinishing::AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) { - // se sopra uscita c'è spazio per sicurezza o approccio + // se sopra uscita c'� spazio per sicurezza o approccio double dSafeDist = dSafeZ ; if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { if ( dSafeDist < dAppr + 10 * EPS_SMALL) { @@ -2158,7 +3045,7 @@ SurfFinishing::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, bool SurfFinishing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtTool, bool bSplitArcs) { - // Se inizio e fine coincidono, non devo fare alcunché + // Se inizio e fine coincidono, non devo fare alcunch� if ( AreSamePointApprox( ptP1, ptStart)) return true ; // Assegno il tipo @@ -2236,7 +3123,7 @@ SurfFinishing::CalcLeadOutEnd( const Point3d& ptEnd, const Vector3d& vtEnd, cons bool SurfFinishing::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Point3d& ptP1, const Vector3d& vtTool, bool bSplitArcs) { - // Se inizio e fine coincidono, non devo fare alcunché + // Se inizio e fine coincidono, non devo fare alcunch� if ( AreSamePointApprox( ptEnd, ptP1)) return true ; // Assegno tipo e parametri @@ -2336,7 +3223,7 @@ SurfFinishing::GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) con // Se l'utensile non ha movimento significativo di punta, si restituisce la feed standard if ( dCosMove > - COS_ORTO_ANG_SMALL) return GetFeed() ; - // Altrimenti non si deve superare la massima velocità di punta prevista + // Altrimenti non si deve superare la massima velocit� di punta prevista return min( GetFeed(), GetTipFeed() / abs( dCosMove)) ; } diff --git a/SurfFinishing.h b/SurfFinishing.h index 8814c98..7679d10 100644 --- a/SurfFinishing.h +++ b/SurfFinishing.h @@ -13,15 +13,18 @@ #pragma once +#include "set" #include "Machining.h" #include "SurfFinishingData.h" #include "ToolData.h" #include "MachiningConst.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkSurfLocal.h" class ICAvToolSurfTm ; class ISurfFlatRegion ; +class ICAvParSilhouettesSurfTm ; //---------------------------------------------------------------------------- class SurfFinishing : public Machining @@ -74,12 +77,27 @@ class SurfFinishing : public Machining bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ; bool Chain( int nGrpDestId) ; bool ProcessPath( int nPathId, int nPvId, int nClId) ; + bool SimplifyCurve( ICurveComposite* pCompo) const ; + bool CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket, + const Frame3d& frSurf, const Vector3d& vtTool, double dDepth, + const Point3d ptStart_forced, const Point3d ptEnd_forced, + ICurveComposite* pCrv) ; bool AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs) ; bool AddOneWay( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs) ; bool AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, const ISurfFlatRegion* pSfrPock, const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs, bool bInVsOut) ; + bool AddZConst( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, double dDepth, double dElev, bool bSliptArcs) ; + bool GetZConstFacesInsideSfr( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, std::set& setZAmbiguos) ; + ICAvParSilhouettesSurfTm* GetParSilhouettesForZConst( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, + const ISurfFlatRegion* pSfr) const ; + bool CalcZConstSilCrv( ICAvParSilhouettesSurfTm* pCavParSilh, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr, + const Vector3d& vtTool, double dDepth, std::vector& vCrvCompo) ; + bool CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, std::vector& vCrvCompo, const Vector3d& vtTool, + const ISurfFlatRegion* pSfr, double dDepth, ICRVCOMPOPOVECTOR& vCrvPath) ; bool AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; bool AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; bool AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ; diff --git a/SurfRoughing.cpp b/SurfRoughing.cpp index fa4c198..4cbb994 100644 --- a/SurfRoughing.cpp +++ b/SurfRoughing.cpp @@ -89,9 +89,17 @@ using namespace std ; //---------------------------------------------------------------------------- static string KEY_SURF_POCK = "SurfPock_" ; static string KEY_SURF_LIMIT = "SurfLimit_" ; +static string KEY_OPEN = "OPEN" ; +static string KEY_THICK = "THICK" ; #define ENABLE_DEBUG_SFR 0 #define ENABLE_DEBUG_FEEDS 0 +#define ENABLE_DEBUG_SFR_BOOLEANS 0 +#define ENABLE_DEBUG_ZPLANE 0 +#if ENABLE_DEBUG_SFR_BOOLEANS + #include "/EgtDev/Include/EGkGeoObjSave.h" + string sPathSrfBool = "C:\\Temp\\" ; +#endif const double STEP_TOL = 10. * EPS_SMALL ; const double SIL_DEPTH_TOL = 100. * EPS_SMALL ; @@ -590,12 +598,6 @@ SurfRoughing::Apply( bool bRecalc, bool bPostApply) m_dTHoldDiam = 0 ; m_pGeomDB->GetInfo( nToolId, TTH_DIAM, m_dTHoldDiam) ; - // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria - if ( bChain && ! Chain( nAuxId)) { - m_pMchMgr->SetLastError( 3003, "Error in SurfRoughing : Chaining failed") ; - return false ; - } - // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; // se non c'è, lo aggiungo @@ -609,28 +611,24 @@ SurfRoughing::Apply( bool bRecalc, bool bPostApply) else m_pGeomDB->EmptyGroup( nClId) ; - // recupero gruppo per geometria temporanea - const string GRP_TEMP = "Temp" ; - int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; - // se non c'è, lo aggiungo - if ( nTempId == GDB_ID_NULL) { - nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; - if ( nTempId == GDB_ID_NULL) - return false ; - m_pGeomDB->SetName( nTempId, GRP_TEMP) ; + // elimino eventuale gruppo geometria simmetrica per lavorazione in doppio + int nDblId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_DBL) ; + if ( nDblId != GDB_ID_NULL) { + m_pGeomDB->Erase( nDblId) ; + nDblId = GDB_ID_NULL ; } - // altrimenti lo svuoto - else - m_pGeomDB->EmptyGroup( nTempId) ; - // in ogni caso lo dichiaro temporaneo e non visibile - m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ; - m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ; - // lavoro ogni singola catena + // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria + if ( bChain && ! Chain( nAuxId)) { + m_pMchMgr->SetLastError( 3003, "Error in SurfRoughing : Chaining failed") ; + return false ; + } + + // lavoro ogni singola regione piana bool bOk = true ; int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; while ( nPathId != GDB_ID_NULL) { - if ( ! ProcessPath( nPathId, nTempId, GDB_ID_NULL, nClId)) + if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId)) bOk = false ; nPathId = m_pGeomDB->GetNextGroup( nPathId) ; } @@ -643,15 +641,14 @@ SurfRoughing::Apply( bool bRecalc, bool bPostApply) // eseguo aggiornamento assi macchina e collegamento con operazione precedente if ( ! Update( bPostApply)) return false ; - + // aggiorno stato della lavorazione m_nStatus = ( bPostApply ? MCH_ST_OK : MCH_ST_NO_POSTAPPL) ; // dichiaro successiva da aggiornare UpdateFollowingOperationsStatus( MCH_ST_OTH_MODIF) ; - LOG_DBG_INFO( GetEMkLogger(), "SurfRoughing apply done") ; - return true ; + } //---------------------------------------------------------------------------- @@ -1080,8 +1077,8 @@ SurfRoughing::Chain( int nGrpDestId) bFirst = false ; } } - // recupero i percorsi concatenati - int nCount = 0 ; + // recupero i percorsi concatenati e definisco la regione piana di sgrossatura + SurfFlatRegionByContours SfrByC ; INTVECTOR vnId2 ; while ( chainC.GetChainFromNear( ptNear, false, vnId2)) { // creo una curva composita @@ -1119,56 +1116,143 @@ SurfRoughing::Chain( int nGrpDestId) // se non sono state inserite curve, vado oltre if ( pCrvCompo->GetCurveCount() == 0) continue ; + // se la curva non è chiusa, errore + if ( ! pCrvCompo->IsClosed()) { + m_pMchMgr->SetLastError( 3004, "Error in SurfRoughing : Open Contour") ; + return false ; + } // imposto estrusione e spessore pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; + // verifico sia piana e se necessario la appiattisco + PtrOwner pFlatCrv( FlattenCurve( *pCrvCompo, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ; + if ( IsNull( pFlatCrv)) { + Plane3d plPlane ; + if ( ! pCrvCompo->IsFlat( plPlane, true, 50 * EPS_SMALL)) + m_pMchMgr->SetLastError( 3005, "Error in SurfRoughing : Contour Not Flat") ; + else + m_pMchMgr->SetLastError( 3006, "Error in SurfRoughing : Tool Dir not perpendicular to Flat Area") ; + return false ; + } + pFlatCrv->GetExtrusion( vtExtr) ; + pCrvCompo->Clear() ; + pCrvCompo->AddCurve( Release( pFlatCrv)) ; + // salvo vettore estrusione + pCrvCompo->SetExtrusion( vtExtr) ; + // salvo la thickness come seconda temp prop ( la Sfr rimuove la thick delle curve) + pCrvCompo->SetTempParam( dThick, 1) ; // aggiorno il nuovo punto vicino - pCrvCompo->GetEndPoint( ptNear) ; + pCrvCompo->GetEndPoint( ptNear) ; // se utile, approssimo con archi if ( ! ApproxWithArcsIfUseful( pCrvCompo)) return false ; - // creo nuovo gruppo - int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; - if ( nPathId == GDB_ID_NULL) - return false ; - m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ; - m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ; - // inserisco la curva composita nel gruppo destinazione - int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ; - if ( nNewId == GDB_ID_NULL) - return false ; + // inserisco la curva nella regione piana + SfrByC.AddCurve( Release( pCrvCompo)) ; } + + // scorro le regioni piane ricavate dalle curve + int nGroupName = -1 ; + PtrOwner pSfrCurr( SfrByC.GetSurf()) ; + while ( ! IsNull( pSfrCurr) && pSfrCurr->IsValid()) { + // per ogni Chunk + for ( int nC = 0 ; nC < pSfrCurr->GetChunkCount() ; ++ nC) { + // creo nuovo gruppo + int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; + if ( nPathId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nGroupName)) ; + m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( nGroupName)) ; + // recupero il Chunk corrente + PtrOwner pSfrChunk( pSfrCurr->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::CloneSurfFlatRegion( pSfrChunk)) ; + if ( nNewId == GDB_ID_NULL) + return false ; + // salvo eventuali lati aperti per il Chunk corrente + for ( int nL = 0 ; nL < pSfrChunk->GetLoopCount( 0) ; ++ nL) { + // recupero il Loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // memorizzo la Thickness e l'Estrusione nelle Info del gruppo + if ( nL == 0) { + double dThick = pCrvLoop->GetTempParam( 1) ; + m_pGeomDB->SetInfo( nNewId, KEY_THICK, dThick) ; + Vector3d vtExtr ; + pCrvLoop->GetExtrusion( vtExtr) ; + m_pGeomDB->SetInfo( nNewId, KEY_EXTR, vtExtr) ; + } + } + } + // aggiorno la regione piana con la successiva calcolata + pSfrCurr.Set( SfrByC.GetSurf()) ; + } + return true ; } //---------------------------------------------------------------------------- bool -SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) +SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId) { // aggiorno la ProgressBar del 5% per simulare l'inizio della funzione ExeProcessEvents( 5, 0) ; - // verifico sia una curva chiusa (deve delimitare l'area da svuotare) - int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; - if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO) - return false ; - ICurve* pCrv = ::GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ; - if ( pCrv == nullptr || ! pCrv->IsClosed()) { - m_pMchMgr->SetLastError( 3004, "Error in SurfRoughing : Open Contour") ; - return false ; + // recupero gruppo per geometria temporanea + const string GRP_TEMP = "Temp" ; + int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; + // se non c'è, lo aggiungo + if ( nTempId == GDB_ID_NULL) { + nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; + if ( nTempId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nTempId, GRP_TEMP) ; } + // altrimenti lo svuoto + else + m_pGeomDB->EmptyGroup( nTempId) ; + // in ogni caso lo dichiaro temporaneo e non visibile + m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ; + m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ; - // copio la curva composita da elaborare - int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; + // recupero la regione piana dal database geometrico + int nSfrId = m_pGeomDB->GetFirstInGroup( nPathId) ; + if ( m_pGeomDB->GetGeoType( nSfrId) != SRF_FLATRGN) + return false ; + + // copio la regione piana da elaborare + int nCopyId = m_pGeomDB->CopyGlob( nSfrId, GDB_ID_NULL, nTempId) ; if ( nCopyId == GDB_ID_NULL) return false ; - ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; + PtrOwner pSfrGDB( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nCopyId))) ; + if ( IsNull( pSfrGDB) || ! pSfrGDB->IsValid()) + return false ; // recupero estrusione e spessore Vector3d vtExtr = Z_AX ; - pCompo->GetExtrusion( vtExtr) ; - double dThick ; - pCompo->GetThickness( dThick) ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_EXTR)) + m_pGeomDB->GetInfo( nSfrId, KEY_EXTR, vtExtr) ; + double dThick = 0. ; + if ( m_pGeomDB->ExistsInfo( nSfrId, KEY_THICK)) + m_pGeomDB->GetInfo( nSfrId, KEY_THICK, dThick) ; + + // valuto l'espressione dell'affondamento + ExeLuaSetGlobNumVar( "TH", abs( dThick)) ; + double dDepth ; + string sMyDepth = m_Params.m_sDepth ; + if ( ! ExeLuaEvalNumExpr( ToUpper( sMyDepth), &dDepth)) { + m_pMchMgr->SetLastError( 3008, "Error in SurfRoughing : Depth not computable") ; + return false ; + } + // se spessore positivo, lo sottraggo dal risultato + if ( dThick > 0) + dDepth -= dThick ; + + // recupero il Loop esterno della regione da svuotatare + PtrOwner pCompo( ConvertCurveToComposite( pSfrGDB->GetLoop( 0, 0))) ; + if ( IsNull( pCompo) || ! pCompo->IsValid()) + return false ; // verifico sia piana e sistemo senso antiorario visto dalla direzione di estrusione Plane3d plPlane ; double dArea ; @@ -1201,15 +1285,6 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) return false ; } - // valuto l'espressione dell'affondamento - ExeLuaSetGlobNumVar( "TH", abs( dThick)) ; - double dDepth ; - string sMyDepth = m_Params.m_sDepth ; - if ( ! ExeLuaEvalNumExpr( ToUpper( sMyDepth), &dDepth)) { - m_pMchMgr->SetLastError( 3008, "Error in SurfRoughing : Depth not computable") ; - return false ; - } - // recupero nome del path string sPathName ; m_pGeomDB->GetName( nPathId, sPathName) ; @@ -1257,7 +1332,7 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) // costruisco una superficie di estrusione della curva (devo determinare parte della regione limite) Vector3d vtLimitExtr = - vtTool * 1.5 * max( b3Raw.GetDimX(), max( b3Raw.GetDimY(), b3Raw.GetDimZ())) ; - PtrOwner pStmLimit( GetStmOutSideCompo( pCompo, pStmRaw, vtLimitExtr)) ; + PtrOwner pStmLimit( GetStmOutSideSfr( pSfrGDB, pStmRaw, vtLimitExtr)) ; if ( IsNull( pStmLimit)) return false ; @@ -1306,6 +1381,12 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) if ( m_bDetectPlaneZ) { if ( ! DetectPlaneZ( vpStm, fr_pCompo, vtTool, vPlaneZ, - GetOffsL(), dDepth - GetOffsL())) return false ; + #if ENABLE_DEBUG_ZPLANE + for ( int nP = 0 ; nP < int( vPlaneZ.size()) ; ++ nP) { + int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPlaneZ[nP].first->Clone()) ; + m_pGeomDB->SetMaterial( _a, Color( 1., 0., 0., .25)) ; + } + #endif } // definisco una struttura per i parametri utili sugli step @@ -1394,6 +1475,13 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) m_pMchMgr->SetLastError( 3024, "Error in SurfRoughing : region not computable") ; return false ; } + for ( int nL = 1 ; nL < pSfrGDB->GetLoopCount( 0) ; ++ nL) { + // recupero l'isola + PtrOwner pCrvIsl( pSfrGDB->GetLoop( 0, nL)) ; + if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid() || + ! pSfr->AddIntLoop( *pCrvIsl)) + return false ; + } pSfr->Translate( ( it->dDepth + GetOffsL()) * vtTool) ; /* ******************** Regione adattata al grezzo ******************** */ @@ -1464,8 +1552,13 @@ SurfRoughing::ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) PtrOwner pSfrRef( CloneSurfFlatRegion( vStepInfo[nIndRef].pSfrRemoved)) ; if ( ! IsNull( pSfrRef) && pSfrRef->IsValid()) { // se valida pSfrRef->Offset( OFFS_CORR_OPEN_EDGES, ICurve::OFF_FILLET) ; // correzione - pSfr->Subtract( *pSfrRef) ; // sottraggo la regione svuotata in precedenza - // aggiorno Regione piana per gestione lati aperti + if ( ! pSfr->Subtract( *pSfrRef)) { // sottraggo la regione svuotata in precedenza + #if ENABLE_DEBUG_SFR_BOOLEANS + SaveSfrBooleans( pSfr, pSfrRef, sPathSrfBool + "Sub_" + to_string( it->dDepth) + ".nge") ; + #endif + // NB. In attesa di una versione più robusta per le booleane tra regioni piane, il substep viene scartato + continue ; + }// aggiorno Regione piana per gestione lati aperti pSfrOpenClose->Subtract( *pSfrRef) ; } } @@ -1750,42 +1843,32 @@ SurfRoughing::GetRaw( void) const //---------------------------------------------------------------------------- ISurfTriMesh* -SurfRoughing::GetStmOutSideCompo( ICurveComposite* pCompo, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const +SurfRoughing::GetStmOutSideSfr( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const { // controllo dei parametri - if ( pCompo == nullptr || ! pCompo->IsValid() || + if ( pSfr == nullptr || ! pSfr->IsValid() || pStmRaw == nullptr || ! pStmRaw->IsValid()) return nullptr ; - // recupero la PolyLine dalla curva - PolyLine PL ; - pCompo->ApproxWithLines( 10 * EPS_SMALL, 15, ICurve::APL_STD, PL) ; + // definisco il vettore delle curve dei i bordi della regione + CICURVEPVECTOR vpCrv ; - // determino la superficie di estrusione - PtrOwner pStmExtr( CreateSurfTriMesh()) ; - bool bOk = ( ! IsNull( pStmExtr)) ; - bOk = bOk && pStmExtr->AdjustTopology() ; - bOk = bOk && pStmExtr->CreateByExtrusion( PL, vtExtr) ; - bOk = bOk && ( pStmExtr->IsValid() && pStmExtr->GetTriangleCount() > 0) ; - if ( ! bOk) - return nullptr ; - // aggiungo i caps - PtrOwner pStmCap0( CreateSurfTriMesh()) ; - bOk = ( ! IsNull( pStmCap0)) ; - bOk = bOk && pStmCap0->CreateByFlatContour( PL) ; - bOk = bOk && ( pStmCap0->IsValid() && pStmCap0->GetTriangleCount() > 0) ; - if ( ! bOk) - return nullptr ; - Vector3d vtN ; pStmCap0->GetFacetNormal( 0, vtN) ; - Vector3d vtN_ref = vtExtr ; vtN_ref.Normalize() ; - if ( AreOppositeVectorApprox( vtN, vtN_ref)) - pStmCap0->Invert() ; - PtrOwner pStmCap1( CloneSurfTriMesh( pStmCap0)) ; - bOk = ( ! IsNull( pStmCap1) && pStmCap1->IsValid() && pStmCap1->GetTriangleCount() > 0) ; - bOk = bOk && ( pStmCap1->Translate( vtExtr) && pStmCap1->Invert()) ; - bOk = bOk && pStmExtr->DoSewing( *pStmCap0) ; - bOk = bOk && pStmExtr->DoSewing( *pStmCap1) ; - if ( ! bOk) + // per ogni Chunk + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + // per ogni Loop + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + // recupero il Loop come curva composita + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return nullptr ; + // recupero la PolyLine associata a tale Loop e la inserisco nel vettore + vpCrv.emplace_back( Release( pCompoLoop)) ; + } + } + + // definisco la superficie di estrusione + PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrv, vtExtr)) ; + if ( IsNull( pStmExtr) || ! pStmExtr->IsValid()) return nullptr ; // la superficie deeve definire un volume @@ -1795,7 +1878,7 @@ SurfRoughing::GetStmOutSideCompo( ICurveComposite* pCompo, const ISurfTriMesh* p // sottraggo al grezzo la regione di estrusione PtrOwner pStmLimit( CloneSurfTriMesh( pStmRaw)) ; - bOk = ! IsNull( pStmLimit) ; + bool bOk = ! IsNull( pStmLimit) ; bOk = bOk && pStmLimit->IsValid() ; bOk = bOk && pStmLimit->Subtract( *pStmExtr) ; if ( ! bOk) diff --git a/SurfRoughing.h b/SurfRoughing.h index 37b8eba..b51efcf 100644 --- a/SurfRoughing.h +++ b/SurfRoughing.h @@ -106,7 +106,7 @@ class SurfRoughing : public Machining bool VerifyGeometry( SelData Id, int& nSubs) ; bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ; bool Chain( int nGrpDestId) ; - bool ProcessPath( int nPathId, int nTempId, int nPvId, int nClId) ; + bool ProcessPath( int nPathId, int nPvId, int nClId) ; bool DetectPlaneZ( const CISURFTMPVECTOR& vpStm, const Frame3d& frCompo, const Vector3d& vtTool, PLANEZFACEVECTOR& vPlaneZ, double dMinDepth, double dMaxDepth) const ; bool CalcPaths( const INTINTVECTOR& vPocket, STEPINFOSRVECTOR& vStepInfo) const ; @@ -122,7 +122,7 @@ class SurfRoughing : public Machining bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, Point3d& ptP1) ; ISurfTriMesh* GetRaw( void) const ; - ISurfTriMesh* GetStmOutSideCompo( ICurveComposite* pCompo, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const ; + ISurfTriMesh* GetStmOutSideSfr( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const ; ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) const ; ISurfFlatRegion* GetSfrSilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dDepth, double Sil_tol, bool& bOk) const ; bool GetActiveSurfaces( INTVECTOR& vSurfId) const ;