EgtMachKernel :

- in Finiture di lama Along5A migliorata la collisione tra lama e sezione e aggiunto ricalcolo SideStep.
This commit is contained in:
Riccardo Elitropi
2026-09-01 12:08:04 +02:00
parent b63914f60b
commit 0bf76e8efb
2 changed files with 714 additions and 174 deletions
+688 -162
View File
@@ -39,10 +39,13 @@
#include "/EgtDev/Include/EgtPointerOwner.h"
#define DEBUG_SAW_FIN 0
#if DEBUG_SAW_FIN
#define BISECTION_ALONG5AX 0
#if DEBUG_SAW_FIN || BISECTION_ALONG5AX
#include "EgtDev/Include/EGkGeoPoint3d.h"
#include "EgtDev/Include/EGkGeoVector3d.h"
#include "EgtDev/Include/EGkGeoFrame3d.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
std::vector<IGeoObj*> VT ; std::vector<Color> VC ;
#endif
// per far dimenticare macro di WinUser.h
#undef GetClassName
@@ -84,7 +87,7 @@ enum nCrvClass {
CCL_FLAT = 2,
CCL_FALL = 3,
CCL_RISE = 4
};
} ;
//----------------------------------------------------------------------------
USEROBJ_REGISTER( GetOperationClass( OPER_SAWFINISHING), SawFinishing) ;
@@ -2641,6 +2644,8 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
}
// elimino eventuali sottosquadra e oriento ogni curva secondo X descrescente
// NB. -->! nonostante la finitura 5Ax non necessita della rimozione dei sottosquadra, qui vengono lo stesso effettuati in
// quanto non vi è ancora una sgrossatura per la loro rimozione !<--
ICRVCOMPOPOVECTOR vpNucCrvs ; vpNucCrvs.reserve( vpSects.size()) ;
for ( const auto& pSect : vpSects) {
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
@@ -2745,12 +2750,19 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
else
return m_Params.m_nHeadSide ;
} ;
// -----------------------------------------------------------------------------------------------
// estensione dei tratti di classificazione
enum nCrvClass5Ax {
CCL_VERT_RISE = 5,
CCL_VERT_FALL = 6
} ;
// per ogni sezione semplice
for ( int i = 0 ; i < ssize( vSections) ; ++ i) {
// riferimenti
SectionInfo& CurrSection = vSections[i] ;
SectionInfo5Ax& CurrSection = vSections[i] ;
SUBSECTIONVECTOR& vCurrSubSections = CurrSection.vSubSections ;
// spezzo eventuali archi sopra e sotto
@@ -2776,11 +2788,21 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
PtrOwner<ICurveComposite> pCompoSubSect( ConvertCurveToComposite( CurrSection.pSection->CopyParamRange( double( i - 1), double( i)))) ;
if ( ! AddSubSection( vCurrSubSections, pCompoSubSect, GetHeadSide( vnClass[0])))
return false ;
vCurrSubSections.back().vnClass.emplace_back( vnClass[0]) ;
if ( vnClass[0] == CCL_VERT) {
Point3d ptS ; vCurrSubSections.back().pSubSection->GetStartPoint( ptS) ;
Point3d ptE ; vCurrSubSections.back().pSubSection->GetEndPoint( ptE) ;
if ( ptS.y < ptE.y)
vCurrSubSections.back().vnClass.back() = CCL_VERT_RISE ;
else
vCurrSubSections.back().vnClass.back() = CCL_VERT_FALL ;
}
bCanSwapHead = ( vnClass[0] != CCL_RISE && vnClass[0] != CCL_FALL) ;
}
// classificazione corrente
const int& nCurrClass = vnClass[i] ;
// classificazione precedente
const int& nPrevClass = vnClass[i - 1] ;
const int& nPrevClass = vnClass[i-1] ;
// parametri per copia sotto-tratto corrente
double dUS = double( i) ;
double dUE = double( i + 1) ;
@@ -2793,10 +2815,43 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
case CCL_SMALL :
case CCL_VERT :
{
// a prescindere dai valori precedenti si aggiunge semplicemente il tratto di sezione
if ( ! vCurrSubSections.back().pSubSection->AddCurve( ::Release( pCompoSub)))
return false ;
bCanSwapHead = ( bCanSwapHead && ( nPrevClass != CCL_RISE && nPrevClass != CCL_FALL)) ;
// determino la vera classificazione corrente
int nMyClass = nCurrClass ;
if ( nCurrClass == CCL_VERT) {
Point3d ptS ; pCompoSub->GetStartPoint( ptS) ;
Point3d ptE ; pCompoSub->GetEndPoint( ptE) ;
if ( ptS.y < ptE.y)
nMyClass = CCL_VERT_RISE ;
else
nMyClass = CCL_VERT_FALL ;
}
// se posso invertire la testa
if ( bCanSwapHead || ( nMyClass == CCL_FLAT || nMyClass == CCL_SMALL)) {
// a prescindere dai valori precedenti si aggiunge semplicemente il tratto di sezione
if ( ! vCurrSubSections.back().pSubSection->AddCurve( ::Release( pCompoSub)))
return false ;
bCanSwapHead = ( bCanSwapHead && ( nPrevClass != CCL_RISE && nPrevClass != CCL_FALL)) ;
}
// se non posso invertire la testa, controllo se posso collegare il tratto corrente all SubSection corrente
else {
int nOtherClass = ( nMyClass == CCL_VERT_FALL ? CCL_VERT_RISE : CCL_VERT_FALL) ;
if ( find( vCurrSubSections.back().vnClass.begin(), vCurrSubSections.back().vnClass.end(), nOtherClass) != vCurrSubSections.back().vnClass.end()) {
// nuova sezione
PtrOwner<ICurveComposite> pCompoSubSect( ::Release( pCompoSub)) ;
if ( ! AddSubSection( vCurrSubSections, pCompoSubSect, m_Params.m_nHeadSide))
return false ;
bCanSwapHead = true ;
}
else {
// aggiungo alla sezione precedente
if ( ! vCurrSubSections.back().pSubSection->AddCurve( ::Release( pCompoSub)))
return false ;
bCanSwapHead = ( bCanSwapHead && ( nPrevClass != CCL_RISE && nPrevClass != CCL_FALL)) ;
}
}
vCurrSubSections.back().vnClass.emplace_back( nMyClass) ;
break ;
}
// --- classificazione corrente Fall (la testa deve essere a destra)
@@ -2837,6 +2892,7 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
if ( ! AddSubSection( vCurrSubSections, pCompoSubSect, SAWFIN_HS_RIGHT))
return false ;
}
vCurrSubSections.back().vnClass.emplace_back( CCL_FALL) ;
break ;
}
// --- classificazione corrente Rise (la testa deve essere a sinistra)
@@ -2877,6 +2933,7 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const
if ( ! vCurrSubSections.back().pSubSection->AddCurve( ::Release( pCompoSub)))
return false ;
}
vCurrSubSections.back().vnClass.emplace_back( CCL_RISE) ;
break ;
}
}
@@ -3466,41 +3523,47 @@ SawFinishing::CalcCAvSect5Ax( const ICurveComposite* pSubSect, const ICRVCOMPOPO
bOtherCollision = false ;
bAwayFromPoint = false ;
// definisco il numero di punti di campionamento progressivi
const int MAX_NUM = 3 ;
// definisco le costanti di collisione e i parametri di ricerca
const int MAX_NUM = 3 ; // -->! dispari, in modo da controllare sempre il centro della sezione della lama !<--
const double LINE_LEN = 1e4 ;
const double TOL = 50. * EPS_SMALL ;
double dSqMaxElev = EPS_ZERO ;
const double COLLISION_TOL = 10. * EPS_SMALL ;
const double AWAY_TOL = 2. ;
// NB -->! ptP è sulla metà della sezione della lama
PtrOwner<ICurveLine> pLineInters( CreateCurveLine()) ;
if ( IsNull( pLineInters) || ! pLineInters->Set( ptP, ptP + vtCorr * LINE_LEN))
if ( IsNull( pLineInters) || ! pLineInters->Set( ptP + vtCorr * COLLISION_TOL, ptP + vtCorr * LINE_LEN))
return false ;
DistPointCurve distPtCrv( ptP + vtTool * m_TParams.m_dThick / 2., *pSubSect) ;
DistPointCurve distPtCrv( ptP, *pSubSect) ;
Point3d ptMidSaw ; int nFlag ;
if ( ! distPtCrv.GetMinDistPoint( 0., ptMidSaw, nFlag))
return false ;
double dLenAtMiSaw ;
if ( ! pSubSect->GetLengthAtPoint( ptMidSaw, dLenAtMiSaw, TOL))
return false ;
double dLenSec ;
if ( ! pSubSect->GetLength( dLenSec))
double dLenAtMidSaw ; double dLenSec ;
if ( ! distPtCrv.GetMinDistPoint( 0., ptMidSaw, nFlag) ||
! pSubSect->GetLengthAtPoint( ptMidSaw, dLenAtMidSaw, COLLISION_TOL) ||
! pSubSect->GetLength( dLenSec))
return false ;
// porto la linea all'estremo della sezione della lama, in direzione opposta a vtTool
pLineInters->Translate( - ( m_TParams.m_dThick / 2.) * vtTool) ;
// per ogni punto di campionamento
double dSqMaxElev = EPS_ZERO ;
for ( int i = 0 ; i < MAX_NUM ; ++ i) {
// traslo la retta di intersezione
if ( i > 0)
pLineInters->Translate( ( m_TParams.m_dThick) / ( MAX_NUM - 1) * vtTool) ;
// calcolo l'intersezione tra la retta e la sezione
Point3d ptLineS ; pLineInters->GetStartPoint( ptLineS) ;
IntersCurveCurve ICC( *pLineInters, *pSubSect) ;
for ( int j = ICC.GetIntersCount() - 1 ; j >= 0 ; -- j) {
IntCrvCrvInfo aInfo ;
if ( ICC.GetIntCrvCrvInfo( j, aInfo)) {
Point3d ptColl = aInfo.bOverlap ? aInfo.IciA[1].ptI : aInfo.IciA[0].ptI ;
Point3d ptColl = ( aInfo.bOverlap ? aInfo.IciA[1].ptI : aInfo.IciA[0].ptI) ;
double dLenAtColl ;
if ( ! pSubSect->GetLengthAtPoint( ptColl, dLenAtColl, TOL))
if ( ! pSubSect->GetLengthAtPoint( ptColl, dLenAtColl, AWAY_TOL))
return false ;
if ( dLenAtColl < max( 0., dLenAtMiSaw - m_TParams.m_dThick / 2. - TOL) ||
min( dLenSec, dLenAtMiSaw + m_TParams.m_dThick / 2. + TOL) < dLenAtColl) {
if ( dLenAtColl < max( 0., dLenAtMidSaw - m_TParams.m_dThick / 2. - AWAY_TOL) ||
min( dLenSec, dLenAtMidSaw + m_TParams.m_dThick / 2. + AWAY_TOL) < dLenAtColl) {
bAwayFromPoint = true ;
return true ;
}
@@ -3529,7 +3592,449 @@ SawFinishing::CalcCAvSect5Ax( const ICurveComposite* pSubSect, const ICRVCOMPOPO
//----------------------------------------------------------------------------
bool
SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& frSect, bool bExtend,
SawFinishing::CalcStepsFor5AxSections( SECTIONVECTOR& vSections) const
{
// Struttura per pramatrizzazione di una curva in base ai suoi angoli interni ed esterni
enum AngleType5Ax { INTERNAL = -1, EXTERNAL = 1 } ;
vector<pair<double, int>> vAngleParams ; // <dU, AngleType5Ax>
// Funzioni per calcolo di Bisezione =============================================================================
// ---
auto CalcSideStep = [&] ( const ICurve* pCurve, int& nStep, double& dStep) {
dStep = max( m_Params.m_dSideStep, 10. * EPS_SMALL) ;
double dLen ;
if ( ! pCurve->GetLength( dLen))
return false ;
if ( dLen < 10. * EPS_SMALL)
return true ;
nStep = static_cast<int>( ceil( dLen / dStep)) ;
dStep = dLen / nStep ;
return true ;
} ;
// ---
auto CalcPointAndDirections = [&]( const ICurveComposite* pCompo, double dUCurr, ICurve::Side nSide, Point3d& ptCurr, Vector3d& vtTan, Vector3d& vtOut) {
// Recupero il punto e la direzione tangente normalizzata
if ( ! pCompo->GetPointD1D2( dUCurr, nSide, ptCurr, &vtTan) || ! vtTan.Normalize())
return false ;
// Calcolo la direzione perpendicolare di uscita
vtOut = GetRotate( vtTan, Z_AX, - ANG_RIGHT) ;
return true ;
} ;
// ---
auto CheckCollision = [&]( const ICurveComposite* pCompo, const ICurveComposite* pCompoCollision, const Point3d& ptP, const Vector3d& vtTan,
const Vector3d& vtOut, bool& bCollision) {
// Posiziono correttamente la lama (punti di campionamento) e vedo quando spostarmi lungo vtOut
const double ELEV_TOL = 10. * EPS_SMALL ;
const int POINT_NBR = 5 ; // (potrebbe essere maggiore, basta che sia dispari per passare nel centro lama)
double dElev = 0. ;
const Point3d ptLineS = ptP - vtTan * ( m_TParams.m_dThick / 2.) + ELEV_TOL * vtOut ;
const Point3d ptLineE = ptP - vtTan * ( m_TParams.m_dThick / 2.) + 1e4 * vtOut ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( IsNull( pLine) || ! pLine->Set( ptLineS, ptLineE))
return false ;
#if BISECTION_ALONG5AX
VT.clear() ; VC.clear() ;
VT.emplace_back( pCompo->Clone()) ; VC.emplace_back( BLUE) ;
#endif
// Calcolo di quanto traslare la lama lungo vtOut per evitare collisioni con il tratto corrente
Point3d ptInters ;
for ( int i = 0 ; i < POINT_NBR ; ++ i) {
if ( i > 0)
pLine->Translate( ( m_TParams.m_dThick / ( POINT_NBR - 1) * vtTan)) ;
IntersCurveCurve ICC( *pLine, *pCompo) ;
#if BISECTION_ALONG5AX
VT.emplace_back( pLine->Clone()) ; VC.emplace_back( AQUA) ;
#endif
if ( ICC.GetIntersCount() > 0) {
IntCrvCrvInfo aInfo ;
if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) {
ptInters = ( aInfo.bOverlap ? aInfo.IciA[1].ptI : aInfo.IciA[0].ptI) ;
dElev = Dist( ptLineS, ptInters) ;
}
}
}
#if BISECTION_ALONG5AX
if ( pCompoCollision != nullptr && pCompoCollision->IsValid()) {
VT.emplace_back( pCompoCollision->Clone()) ; VC.emplace_back( WHITE) ;
}
SaveGeoObj( VT, VC, "C:\\Temp\\Collision.nge") ;
#endif
// Traslo la linea
if ( ! pLine->Set( ptLineS + dElev * vtOut, ptLineS + 1e4 * vtOut))
return false ;
// Verifico la collisione con l'altra porzione di curva
bCollision = false ;
if ( pCompoCollision != nullptr && pCompoCollision->IsValid()) {
// costrusco la vera geometria della lama
PtrOwner<ICurveComposite> pCompoSaw( CreateCurveComposite()) ;
if ( IsNull( pCompoSaw) || ! pCompoSaw->AddPoint( ptLineS) ||
! pCompoSaw->AddLine( ptLineS + m_TParams.m_dDiam * vtOut) ||
! pCompoSaw->AddLine( ptLineS + m_TParams.m_dDiam * vtOut + vtTan * m_TParams.m_dThick) ||
! pCompoSaw->AddLine( ptLineS + vtTan * m_TParams.m_dThick) ||
! pCompoSaw->Close())
return false ;
IntersCurveCurve ICC( *pCompoSaw, *pCompoCollision) ;
if ( ICC.GetCrossIntersCount() > 0) {
bCollision = true ;
return true ;
}
}
return true ;
} ;
// ---
auto AdjustCompoByCollision = [&]( ICurveComposite* pCompo, const ICurveComposite* pCompoCollision, bool bStart) {
// Calcolo il punto corrente su cui posizionare il centro della lama
Point3d ptCurr ; Vector3d vtTan, vtOut ;
if ( bStart) {
if ( ! CalcPointAndDirections( pCompo, 0., ICurve::FROM_PLUS, ptCurr, vtTan, vtOut))
return false ;
}
else {
if ( ! CalcPointAndDirections( pCompo, double( pCompo->GetCurveCount()), ICurve::FROM_MINUS, ptCurr, vtTan, vtOut))
return false ;
}
// Verifico che in tale punto la collisione esista, altrimenti non faccio nulla
bool bCollision = false ;
if ( ! CheckCollision( pCompo, pCompoCollision, ptCurr, vtTan, vtOut, bCollision))
return false ;
if ( ! bCollision)
return true ;
// Scorro la curva per trovare un punto senza collisione (riferimento sempre per il centro lama)
double dLen ; pCompo->GetLength( dLen) ;
const double SAMPLE_LEN = m_TParams.m_dThick / 2. ;
double dCurrLen = ( bStart ? min( SAMPLE_LEN, dLen) : max( 0., dLen - SAMPLE_LEN)) ;
Point3d ptA = ptCurr ; // -->! punto con collisione !<--
Point3d ptB = ptCurr ; // -->! punto senza collisione !<--
bool bCollisionFound = false ;
while ( ( bStart ? dCurrLen < dLen - EPS_SMALL : dCurrLen > 0.)) {
// Recupero il Punto e le direzioni correnti
double dUCurr ;
if ( ! pCompo->GetParamAtLength( dCurrLen, dUCurr) ||
! CalcPointAndDirections( pCompo, dUCurr, bStart ? ICurve::FROM_PLUS : ICurve::FROM_MINUS, ptCurr, vtTan, vtOut))
return false ;
// Verifico la collisione
if ( ! CheckCollision( pCompo, pCompoCollision, ptCurr, vtTan, vtOut, bCollision))
return false ;
if ( ! bCollision) {
ptB = ptCurr ;
bCollisionFound = true ;
break ;
}
dCurrLen += ( bStart ? SAMPLE_LEN : - SAMPLE_LEN) ;
ptA = ptCurr ;
}
if ( ! bCollisionFound) {
// I due estremi per la bisezione non sono stati trovati, pCompo viene scartata
pCompo->Clear() ;
return true ;
}
if ( AreSamePointEpsilon( ptA, ptB, 10. * EPS_SMALL))
return true ; // tratto troppo piccolo per trovare una collisione, non modifico nulla
// Applico il metodo di bisezione per calcolare il punto ideale per posizionare l'utensile
const int MAX_ITER = 10 ;
int nIter = 0 ;
bool bCollisionA = true ;
double dLenA = 0., dLenB = 0. ;
while ( nIter < MAX_ITER && ! AreSamePointEpsilon( ptA, ptB, 10. * EPS_SMALL)) {
// Ricavo le rispettive lunghezze
if ( ! pCompo->GetLengthAtPoint( ptA, dLenA) || ! pCompo->GetLengthAtPoint( ptB, dLenB))
return false ;
// Recupero i parametri a metà lunghezza
double dUCurr ;
if ( ! pCompo->GetParamAtLength( 0.5 * ( dLenA + dLenB), dUCurr) ||
! pCompo->GetPointD1D2( dUCurr, bStart ? ICurve::FROM_PLUS : ICurve::FROM_MINUS, ptCurr) ||
! CalcPointAndDirections( pCompo, dUCurr, bStart ? ICurve::FROM_PLUS : ICurve::FROM_MINUS, ptCurr, vtTan, vtOut))
return false ;
// Verifico la collisione in tale punto
if ( ! CheckCollision( pCompo, pCompoCollision, ptCurr, vtTan, vtOut, bCollision))
return false ;
if ( bCollision == bCollisionA)
ptA = ptCurr ;
else
ptB = ptCurr ;
++ nIter ;
}
#if BISECTION_ALONG5AX
VT.clear(); VC.clear() ;
VT.emplace_back( pCompo->Clone()) ; VC.emplace_back( BLUE) ;
VT.emplace_back( pCompoCollision->Clone()) ; VC.emplace_back( WHITE) ;
double _dL = dLenB ;
double _dU ; pCompo->GetParamAtLength( _dL, _dU) ;
Point3d _ptA ; Vector3d _vtA, _vtB ;
CalcPointAndDirections( pCompo, _dU, bStart ? ICurve::FROM_PLUS : ICurve::FROM_MINUS, _ptA, _vtA, _vtB) ;
PtrOwner<ICurveComposite> _pCompoSaw( CreateCurveComposite()) ;
_pCompoSaw->AddPoint( _ptA + _vtA * m_TParams.m_dThick / 2) ;
_pCompoSaw->AddLine( _ptA + _vtA * m_TParams.m_dThick / 2 + _vtB * m_TParams.m_dDiam) ;
_pCompoSaw->AddLine( _ptA - _vtA * m_TParams.m_dThick / 2 + _vtB * m_TParams.m_dDiam) ;
_pCompoSaw->AddLine( _ptA - _vtA * m_TParams.m_dThick / 2) ;
_pCompoSaw->Close() ;
VT.emplace_back( _pCompoSaw->Clone()) ; VC.emplace_back( RED) ;
SaveGeoObj( VT, VC, "C:\\Temp\\Result.nge") ;
#endif
// Trim della curva nel punto ricavato (ultimo punto senza collissione)
double dLenTrim = dLenB ;
if ( bStart)
return ( pCompo->TrimStartAtLen( dLenTrim)) ;
else
return ( pCompo->TrimEndAtLen( dLenTrim)) ;
} ;
// ---
typedef vector<tuple<int, double, double>> SectionSplitParVector ;
auto SplitSectionInterval = [&] ( INTVECTOR vSectionInterval, double dUS, double dUE, SectionSplitParVector& vRes) {
vRes.clear() ;
// Se inizio maggiore di fine, l'intervallo non è valido
if ( dUS > dUE - EPS_SMALL)
return ;
// Scorro gli intervalli
for ( int i = 0 ; i < ssize( vSectionInterval) - 1 ; ++ i) {
double dIntS = double( vSectionInterval[i]) ;
double dIntE = double( vSectionInterval[i+1]) ;
// Se l'intero intervallo del vettore è prima del nostro inizio, passo oltre
if ( dIntE <= dUS + EPS_SMALL)
continue ;
// Se l'intero intervallo del vettore è dopo la fine, posso fermarmi
if ( dIntS >= dUE - EPS_SMALL) {
break ;
}
// Calcolo l'intersezione
double dCurrUS = max( dUS, dIntS) ;
double dCurrUE = min( dUE, dIntE) ;
// Se porzione valida, la aggiungo al risultato
if ( dCurrUS < dCurrUE)
vRes.emplace_back( make_tuple( i, dCurrUS, dCurrUE )) ;
}
} ;
// =======================================================================================================
const double SAW_EXTERNAL_ANGLE_LEN_TOL = 0.5 ;
// Scorro le sezioni (sono nel piano XY)
for ( SectionInfo5Ax& Section : vSections) {
// Se la sezione non è valida, errore
if ( Section.pSection == nullptr || ! Section.pSection->IsValid())
continue ;
// Il percorso che la lama deve seguire è definito dalle SubSections
PtrOwner<ICurveComposite> pMySection( CreateCurveComposite()) ;
if ( IsNull( pMySection))
return false ;
for ( const SubSectionInfo5Ax& SubSection : Section.vSubSections) {
if ( SubSection.pSubSection != nullptr && SubSection.pSubSection->IsValid()) {
if ( ! pMySection->AddCurve( SubSection.pSubSection->Clone()))
return false ;
}
}
// Numero di curve contenute in ogni SubSection della sezione corrente
INTVECTOR vnCrv( Section.vSubSections.size() + 1, 0) ;
for ( int i = 0 ; i < ssize( Section.vSubSections) ; ++ i) {
if ( Section.vSubSections[i].pSubSection == nullptr || ! Section.vSubSections[i].pSubSection->IsValid())
continue ;
int nToTCrv = Section.vSubSections[i].pSubSection->GetCurveCount() ;
vnCrv[i + 1] = vnCrv[i] + nToTCrv ;
}
// Scorro le curve della sezione corrente (valuto sempre l'estremo iniziale della singola curva)
vAngleParams.emplace_back( make_pair( 0., EXTERNAL)) ; // vertice iniziale associato ad angolo esterno
int nCrvCnt = pMySection->GetCurveCount() ;
#if BISECTION_ALONG5AX
VT.emplace_back( pMySection->Clone()) ;
VC.emplace_back( RED) ;
SaveGeoObj( VT, VC, "C:\\Temp\\section.nge") ;
#endif
for ( int nCrv = 1 ; nCrv < nCrvCnt ; ++ nCrv) {
// Recupero le due direzione di tangenza (precedente e successiva)
Point3d ptJoin ;
Vector3d vtTanPrev, vtTanNext ;
if ( ! pMySection->GetPointD1D2( double( nCrv), ICurve::FROM_MINUS, ptJoin, &vtTanPrev) || ! vtTanPrev.Normalize() ||
! pMySection->GetPointD1D2( double( nCrv), ICurve::FROM_PLUS, ptJoin, &vtTanNext) || ! vtTanNext.Normalize())
continue ;
// Se le direzioni sono tra loro parallele, allora è un tratto C' Locale, non faccio nulla
if ( AreSameVectorApprox( vtTanPrev, vtTanNext))
continue ;
// Verifico se angolo interno o esterno (Segno del determinante)
double dDet = ( vtTanPrev.x * vtTanNext.y) - ( vtTanPrev.y * vtTanNext.x) ;
bool bAngInt = ( dDet < EPS_ZERO) ;
// Memorizzo i risultati
vAngleParams.emplace_back( make_pair( double( nCrv), bAngInt ? INTERNAL : EXTERNAL)) ;
}
vAngleParams.emplace_back( make_pair( nCrvCnt, EXTERNAL)) ; // vertice finale associato ad angolo esterno
// Scorro le parametrizzazioni a coppie, in modo da isolare la parte di curva tra due spigoli
for ( int i = 0 ; i < ssize( vAngleParams) - 1 ; ++ i) {
const double& dUS = vAngleParams[i].first ;
const double& dUE = vAngleParams[i+1].first ;
// Verifico quale SubSection Comprende la curva C' corrente
SectionSplitParVector vSplit ; SplitSectionInterval( vnCrv, dUS, dUE, vSplit) ;
// Recupero il tratto di curva corrente
PtrOwner<ICurveComposite> pCompo( ConvertCurveToComposite( pMySection->CopyParamRange( dUS, dUE))) ;
if ( IsNull( pCompo) || ! pCompo->IsValid())
return false ;
// --- Inizio
// Se angolo esterno all'inizio
if ( vAngleParams[i].second == EXTERNAL)
pCompo->ExtendStartByLen( max( SAW_EXTERNAL_ANGLE_LEN_TOL, m_TParams.m_dThick / 2. - m_Params.m_dSideStep)) ;
// Se angolo interno all'inizio
else {
// Mediante la bisezione verifico se esiste collisione
PtrOwner<ICurveComposite> pCompoColl( ConvertCurveToComposite( pMySection->CopyParamRange( 0., dUS))) ;
if ( ! AdjustCompoByCollision( pCompo, pCompoColl, true))
return false ;
if ( ! pCompo->IsValid())
continue ;
}
// --- Fine
// Se angolo esterno alla fine
if ( vAngleParams[i+1].second == EXTERNAL) {
double dLen ; pCompo->GetLength( dLen) ;
pCompo->TrimEndAtLen( max( 0., dLen - m_TParams.m_dThick / 2. + SAW_EXTERNAL_ANGLE_LEN_TOL)) ;
}
// Se angolo interno alla fine
else {
// Mediante la bisezione verifico se esiste la collisione
PtrOwner<ICurveComposite> pCompoColl( ConvertCurveToComposite( pMySection->CopyParamRange( dUE, double( nCrvCnt)))) ;
if ( ! AdjustCompoByCollision( pCompo, pCompoColl, false))
return false ;
if ( ! pCompo->IsValid())
continue ;
}
// Memorizzo il risultato ottenuto
if ( vSplit.empty())
continue ;
else if ( ssize( vSplit) == 1) {
// Con le modifiche apportate alla curva, calcolo gli Step
int nStep ; double dStep ;
CalcSideStep( pCompo, nStep, dStep) ;
int nSection = get<0>( vSplit[0]) ;
Section.vSubSections[nSection].CompoMidSawParams.resize( Section.vSubSections[nSection].CompoMidSawParams.size() + 1) ;
Section.vSubSections[nSection].CompoMidSawParams.back().pCompo.Set( ::Release( pCompo)) ;
Section.vSubSections[nSection].CompoMidSawParams.back().nStep = nStep ;
Section.vSubSections[nSection].CompoMidSawParams.back().dStep = dStep ;
}
else {
for ( int j = 0 ; j < ssize( vSplit) ; ++ j) {
int nSection = get<0>( vSplit[j]) ;
// Recupero il punto finale della sezione corrente
Point3d ptEndSection ; Section.vSubSections[nSection].pSubSection->GetEndPoint( ptEndSection) ;
if ( pCompo->IsPointOn( ptEndSection)) {
double dUTrim ; pCompo->GetParamAtPoint( ptEndSection, dUTrim) ;
PtrOwner<ICurveComposite> pMyCompo( ConvertCurveToComposite( pCompo->CopyParamRange( 0, dUTrim))) ;
if ( ! IsNull( pMyCompo) && pMyCompo->IsValid()) {
int nStep ; double dStep ;
CalcSideStep( pMyCompo, nStep, dStep) ;
Section.vSubSections[nSection].CompoMidSawParams.resize( Section.vSubSections[nSection].CompoMidSawParams.size() + 1) ;
Section.vSubSections[nSection].CompoMidSawParams.back().pCompo.Set( ::Release( pMyCompo)) ;
Section.vSubSections[nSection].CompoMidSawParams.back().nStep = nStep ;
Section.vSubSections[nSection].CompoMidSawParams.back().dStep = dStep ;
pCompo->TrimStartAtParam( dUTrim) ;
}
}
}
if ( pCompo->IsValid()) {
int nLastSection = get<0>( vSplit.back()) ;
if ( Section.vSubSections[nLastSection].CompoMidSawParams.empty())
Section.vSubSections[nLastSection].CompoMidSawParams.resize( Section.vSubSections[nLastSection].CompoMidSawParams.size() + 1) ;
if ( IsNull( Section.vSubSections[nLastSection].CompoMidSawParams.back().pCompo) ||
! Section.vSubSections[nLastSection].CompoMidSawParams.back().pCompo->IsValid()) {
if ( ! Section.vSubSections[nLastSection].CompoMidSawParams.back().pCompo.Set( CreateCurveComposite()))
return false ;
}
if ( ! Section.vSubSections[nLastSection].CompoMidSawParams.back().pCompo->AddCurve( ::Release( pCompo)))
return false ;
int nStep ; double dStep ;
CalcSideStep( Section.vSubSections[nLastSection].CompoMidSawParams.back().pCompo, nStep, dStep) ;
Section.vSubSections[nLastSection].CompoMidSawParams.back().nStep = nStep ;
Section.vSubSections[nLastSection].CompoMidSawParams.back().dStep = dStep ;
}
}
}
#if BISECTION_ALONG5AX
VT.clear() ; VC.clear() ;
VT.emplace_back( pMySection->Clone()) ; VC.emplace_back( BLUE) ;
for ( int i = 0 ; i < ssize( Section.vSubSections) ; ++ i) {
for ( int j = 0 ; j < ssize( Section.vSubSections[i].CompoMidSawParams) ; ++ j) {
VT.emplace_back( Section.vSubSections[i].CompoMidSawParams[j].pCompo->Clone()) ; VC.emplace_back( AQUA) ;
Point3d ptA ; Vector3d vtA, vtB ;
CalcPointAndDirections( Section.vSubSections[i].CompoMidSawParams[j].pCompo, 0, ICurve::FROM_PLUS, ptA, vtA, vtB) ;
PtrOwner<ICurveComposite> pCompoSaw( CreateCurveComposite()) ;
pCompoSaw->AddPoint( ptA + vtA * m_TParams.m_dThick / 2) ;
pCompoSaw->AddLine( ptA + vtA * m_TParams.m_dThick / 2 + vtB * m_TParams.m_dDiam) ;
pCompoSaw->AddLine( ptA - vtA * m_TParams.m_dThick / 2 + vtB * m_TParams.m_dDiam) ;
pCompoSaw->AddLine( ptA - vtA * m_TParams.m_dThick / 2) ;
pCompoSaw->Close() ;
VT.emplace_back( pCompoSaw->Clone()) ; VC.emplace_back( RED) ;
CalcPointAndDirections( Section.vSubSections[i].CompoMidSawParams[j].pCompo, Section.vSubSections[i].CompoMidSawParams[j].pCompo->GetCurveCount(), ICurve::FROM_PLUS, ptA, vtA, vtB) ;
pCompoSaw->Clear() ;
pCompoSaw->AddPoint( ptA + vtA * m_TParams.m_dThick / 2) ;
pCompoSaw->AddLine( ptA + vtA * m_TParams.m_dThick / 2 + vtB * m_TParams.m_dDiam) ;
pCompoSaw->AddLine( ptA - vtA * m_TParams.m_dThick / 2 + vtB * m_TParams.m_dDiam) ;
pCompoSaw->AddLine( ptA - vtA * m_TParams.m_dThick / 2) ;
pCompoSaw->Close() ;
VT.emplace_back( pCompoSaw->Clone()) ; VC.emplace_back( RED) ;
}
}
SaveGeoObj( VT, VC, "C:\\Temp\\Result.nge") ;
#endif
}
return true ;
}
//----------------------------------------------------------------------------
bool
SawFinishing::CalcAlong5ACuts( SECTIONVECTOR& vSections, const Frame3d& frSect, bool bExtend,
const Point3d& ptGdStart, const Point3d& ptGdEnd, const Vector3d& vtGdDir, double dDepth,
const BBox3d& b3Raw, const ISurfTriMesh* pStmRaw)
{
@@ -3543,6 +4048,7 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr
double dRawMaxZ = b3Raw.GetMax().z ;
// aggiungo due tratti verticali agli estremi delle sezioni per il calcolo delle collisioni
// !<-- Queste sezioni servono solo per il calcolo delle collisioni -->!
ICRVCOMPOPOVECTOR vBoundedSections( vSections.size()) ;
for ( int nSect = 0 ; nSect < ssize( vSections) ; ++ nSect) {
if ( vSections[nSect].pSection != nullptr && vSections[nSect].pSection->IsValid() &&
@@ -3554,12 +4060,11 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr
}
}
// scorro le sezioni
double dLastElev = 0. ;
// per ogni sezione effettuo il trim (se richiesto)
for ( int nSect = 0 ; nSect < ssize( vSections) ; ++ nSect) {
// recupero la sezione
const SectionInfo& Section = vSections[nSect] ;
SectionInfo5Ax& Section = vSections[nSect] ;
if ( Section.pSection == nullptr || ! Section.pSection->IsValid())
continue ;
@@ -3604,164 +4109,185 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr
}
}
}
}
// scorro le SubSection ottenute
bool bLastToolInv = false ;
bool bFirst = true ;
// modifico le curve della sezione corrente in modo da pulire più materiale possibile in presenza di spigoli interni e di non
// eccedere con le passate in presenza di spigoli esterni
if ( ! CalcStepsFor5AxSections( vSections))
return false ;
// scorro le sezioni da lavorare
double dLastElev = 0. ;
for ( int nSect = 0 ; nSect < ssize( vSections) ; ++ nSect) {
// verifico che la Section corrente sia valida, altrimento passo alla successiva
const SectionInfo5Ax& Section = vSections[nSect] ;
if ( Section.pSection == nullptr || ! Section.pSection)
continue ;
// scorro le SubSections
bool bLastToolInv = false, bFirst = true ;
Point3d ptStartPrev ;
Vector3d vtCorrPrev = V_NULL,
vtToolPrev = V_NULL ;
Vector3d vtCorrPrev = V_NULL, vtToolPrev = V_NULL ;
for ( int nSubSect = 0 ; nSubSect < ssize( Section.vSubSections) ; ++ nSubSect) {
// recupero la SubSection corrente, se non valida, passo alla successiva
const SubSectionInfo& SubSection = Section.vSubSections[nSubSect] ;
PtrOwner<ICurveComposite> pSubSect( CloneCurveComposite( SubSection.pSubSection)) ;
if ( pSubSect == nullptr || ! pSubSect->IsValid())
// verifico che la SubSection corrente sia valida, altrimenti passo alla successiva
const SubSectionInfo5Ax& SubSection = Section.vSubSections[nSubSect] ;
if ( SubSection.pSubSection == nullptr || ! SubSection.pSubSection->IsValid())
continue ;
// calcolo della lunghezza dello step e del numero di step complessivi
double dStep = max( m_Params.m_dSideStep, 10. * EPS_SMALL) ;
double dLen ;
if ( ! pSubSect->GetLength( dLen))
return false ;
if ( dLen < 10. * EPS_SMALL)
return true ;
int nStep = static_cast<int>( ceil( dLen / dStep)) ;
dStep = dLen / nStep ;
// per ogni sezione recupero le curve di centro lama
for ( int nMidSawCrv = 0 ; nMidSawCrv < ssize( SubSection.CompoMidSawParams) ; ++ nMidSawCrv) {
// Ciclo sulle passate
for ( int i = 0 ; i <= nStep ; ++ i) {
// coordinate nel punto, del versore correzione e del versore utensile
double dLcurr = i * dStep ;
double dU ; pSubSect->GetParamAtLength( dLcurr, dU) ;
Point3d ptP ;
Vector3d vtTan, vtPerp ;
if ( ! pSubSect->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP, &vtTan) || ! vtTan.Normalize())
return false ;
Vector3d vtCorr = GetToGlob( vtTan, frSect) ;
vtCorr.Rotate( vtGdDir, m_Params.m_bInvert ? - ANG_RIGHT : ANG_RIGHT) ;
// se tangente circa orizzontale, correggo la direzione per evitare inversioni di vtTool
if ( abs( vtTan.y) < 5 * EPS_SMALL) {
if ( ( SubSection.nHeadSide == SAWFIN_HS_LEFT)) {
vtTan.y = abs( vtTan.y) ; // y > 0.
vtTan.x = - abs( vtTan.x) ; // x < 0.
}
else if ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) {
vtTan.y = - abs( vtTan.y) ; // y < 0.
vtTan.x = abs( vtTan.x) ; // x > 0.
}
}
Vector3d vtTool = GetToGlob( vtTan, frSect) ;
// determino l'orientamento della testa
// NB. vtTool deve sempre avere la componente Z come positiva (quindi vtCorr.y >= 0)
bool bCurrToolInv = ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) ;
if ( vtTool.z < - 5. * EPS_SMALL)
vtTool.Invert() ;
// punto di passata è sulla metà della sezione lama
ptP += - 0.5 * m_TParams.m_dThick * GetToLoc( vtTool, frSect) ;
// verifico posizionando la lama nel punto corrente se devo spostarmi per evitare collisione con la sezione
double dSectElev = 0. ;
bool bOtherColl = false, bAwayFromPoint = false ;
if ( ! CalcCAvSect5Ax( pSubSect, vBoundedSections, GetToLoc( vtTool, frSect), GetToLoc( vtCorr, frSect), ptP, dSectElev,
bOtherColl, bAwayFromPoint)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
// se collisione con altra sezione o collisione distante dal punto corrente, passo allo step successivo (non inserisco la passata corrente)
if ( bOtherColl || bAwayFromPoint)
// verifico che la Curva di Centro Lama sia valida, altrimenti passo alla successiva
const SubSectionStep5Ax& MidSawPath = SubSection.CompoMidSawParams[nMidSawCrv] ;
if ( MidSawPath.pCompo == nullptr || ! MidSawPath.pCompo->IsValid())
continue ;
const ICurveComposite* pCompoPath = MidSawPath.pCompo ;
const int& nStep = MidSawPath.nStep ;
const double& dStep = MidSawPath.dStep ;
// verifico se inversione della testa
bool bSpecialAppr = ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT && ! bFirst && ( bCurrToolInv != bLastToolInv)) ;
// Ciclo sulle passate
bool bFirstMidSawCrv = true ;
for ( int i = 0 ; i <= nStep ; ++ i) {
// definisco gli estremi del tratto rettilineo in globale
Point3d ptPCAvSect = GetToGlob( ptP, frSect) + vtCorr * dSectElev ;
if ( m_Params.m_bInvert)
ptPCAvSect.Translate( - vtGdDir * Dist( ptGdStart, ptGdEnd)) ;
Point3d ptStart = ptPCAvSect ;
Point3d ptEnd = ptPCAvSect + vtGdDir * ( Dist( ptGdStart, ptGdEnd)) ;
// verifico eventuale estensione degli estremi sul grezzo
if ( bExtend) {
if ( ! AdaptGuideLineToRaw( ptStart, ptEnd, vtGdDir, bExtend, pStmRaw))
// coordinate nel punto, del versore correzione e del versore utensile
double dLcurr = i * dStep ;
double dU ; pCompoPath->GetParamAtLength( dLcurr, dU) ;
Point3d ptP ;
Vector3d vtTan, vtPerp ;
if ( ! pCompoPath->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP, &vtTan) || ! vtTan.Normalize())
return false ;
}
Vector3d vtCorr = GetToGlob( vtTan, frSect) ;
vtCorr.Rotate( vtGdDir, m_Params.m_bInvert ? - ANG_RIGHT : ANG_RIGHT) ;
// se tangente circa orizzontale, correggo la direzione per evitare inversioni di vtTool
if ( abs( vtTan.y) < 5 * EPS_SMALL) {
if ( ( SubSection.nHeadSide == SAWFIN_HS_LEFT)) {
vtTan.y = abs( vtTan.y) ; // y > 0.
vtTan.x = - abs( vtTan.x) ; // x < 0.
}
else if ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) {
vtTan.y = - abs( vtTan.y) ; // y < 0.
vtTan.x = abs( vtTan.x) ; // x > 0.
}
}
Vector3d vtTool = GetToGlob( vtTan, frSect) ;
// determino l'elevazione del taglio ( per confrontarla con la MaxDepth consentita)
Vector3d vtThick = vtTool * m_TParams.m_dThick ;
double dElev, dElev2 ;
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, Z_AX, dElev) ||
! GetElevation( m_nPhase, ptStart + vtThick, ptEnd + vtThick, Z_AX, dElev2)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
dElev = max( dElev, dElev2) ;
if ( dElev < EPS_SMALL)
dElev = max( { dRawMaxZ - ptStart.z, dRawMaxZ - ptEnd.z, 0.}) ;
// la confronto con il massimo affondamento e con la massima lavorazione della lama. Se sotto alla massima Depth allora riporto
// l'utensile in verticale e ricalcolo il punto più adatto in z per il tratto lineare
double dMaxDepth = min( dDepth, m_TParams.m_dMaxMat) ;
if ( dElev > dMaxDepth) {
// modifica versore correzione e direzione utensile
vtTool.z = 0. ;
if ( ! vtTool.Normalize())
return false ;
vtCorr = Z_AX ;
double dElevTmp = 0. ;
if ( ! CalcCAvSect5Ax( pSubSect, vBoundedSections, GetToLoc( vtTool, frSect), GetToLoc( vtCorr, frSect), ptP, dElevTmp,
// determino l'orientamento della testa
// NB. -->! vtTool deve sempre avere la componente Z come positiva (quindi vtCorr.y >= 0) !<--
bool bCurrToolInv = ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) ;
if ( vtTool.z < - 5. * EPS_SMALL)
vtTool.Invert() ;
// verifico posizionando la lama nel punto corrente se devo spostarmi per evitare collisione con la sezione
double dSectElev = 0. ;
bool bOtherColl = false, bAwayFromPoint = false ;
if ( ! CalcCAvSect5Ax( pCompoPath, vBoundedSections, GetToLoc( vtTool, frSect), GetToLoc( vtCorr, frSect), ptP, dSectElev,
bOtherColl, bAwayFromPoint)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
// se collisione con altra sezione o collisione distante dal punto corrente, passo allo step successivo (non inserisco la passata corrente)
if ( bOtherColl || bAwayFromPoint)
continue ;
ptPCAvSect = GetToGlob( ptP, frSect) + vtCorr * dElevTmp ;
double dElev3 ;
if ( ! GetElevation( m_nPhase, ptPCAvSect, vtTool, m_TParams.m_dDiam / 2., m_TParams.m_dLen, vtCorr, dElev3)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
Point3d ptPTopRaw = ptPCAvSect + ( dElev3 - m_TParams.m_dDiam / 2.) * vtCorr ;
ptStart.z = max( ptPTopRaw.z - dMaxDepth, ptPCAvSect.z) ;
ptEnd.z = max( ptPTopRaw.z - dMaxDepth, ptPCAvSect.z) ;
dElev = dMaxDepth ;
}
else {
double dElev4, dElev5 ;
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, vtCorr, dElev4) ||
! GetElevation( m_nPhase, ptStart + vtThick, ptEnd + vtThick, vtCorr, dElev5)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
dElev = max( dElev4, dElev5) ;
}
// Imposto dati comune
SetToolDir( vtTool) ;
SetCorrAuxDir( vtCorr) ;
// se utensile non piatto
if ( bFirst || ! AreSamePointEpsilon( ptStart, ptStartPrev, 10. * EPS_SMALL)) {
if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) {
if ( ! CalcAlong5AOneWayCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, bExtend, false,
bFirst, bSpecialAppr))
// punto di passata è sulla metà della sezione lama
ptP += - 0.5 * m_TParams.m_dThick * GetToLoc( vtTool, frSect) ;
// verifico se inversione della testa
bool bSpecialAppr = ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT && ! bFirst && ( bCurrToolInv != bLastToolInv)) ;
// definisco gli estremi del tratto rettilineo in globale
Point3d ptPCAvSect = GetToGlob( ptP, frSect) + vtCorr * dSectElev ;
if ( m_Params.m_bInvert)
ptPCAvSect.Translate( - vtGdDir * Dist( ptGdStart, ptGdEnd)) ;
Point3d ptStart = ptPCAvSect ;
Point3d ptEnd = ptPCAvSect + vtGdDir * ( Dist( ptGdStart, ptGdEnd)) ;
// verifico eventuale estensione degli estremi sul grezzo
if ( bExtend) {
if ( ! AdaptGuideLineToRaw( ptStart, ptEnd, vtGdDir, bExtend, pStmRaw))
return false ;
}
// determino l'elevazione del taglio ( per confrontarla con la MaxDepth consentita)
Vector3d vtThick = vtTool * m_TParams.m_dThick ;
double dElev, dElev2 ;
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, Z_AX, dElev) ||
! GetElevation( m_nPhase, ptStart + vtThick, ptEnd + vtThick, Z_AX, dElev2)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
dElev = max( dElev, dElev2) ;
if ( dElev < EPS_SMALL)
dElev = max( { dRawMaxZ - ptStart.z, dRawMaxZ - ptEnd.z, 0.}) ;
// la confronto con il massimo affondamento e con la massima lavorazione della lama. Se sotto alla massima Depth allora riporto
// l'utensile in verticale e ricalcolo il punto più adatto in z per il tratto lineare
double dMaxDepth = min( dDepth, m_TParams.m_dMaxMat) ;
if ( dElev > dMaxDepth) {
// modifica versore correzione e direzione utensile
vtTool.z = 0. ;
if ( ! vtTool.Normalize())
return false ;
vtCorr = Z_AX ;
double dElevTmp = 0. ;
ptP += + 0.5 * m_TParams.m_dThick * GetToLoc( vtTool, frSect) ;
if ( ! CalcCAvSect5Ax( pCompoPath, vBoundedSections, GetToLoc( vtTool, frSect), GetToLoc( vtCorr, frSect), ptP, dElevTmp,
bOtherColl, bAwayFromPoint)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
if ( bOtherColl || bAwayFromPoint)
continue ;
ptP += - 0.5 * m_TParams.m_dThick * GetToLoc( vtTool, frSect) ;
ptPCAvSect = GetToGlob( ptP, frSect) + vtCorr * dElevTmp ;
double dElev3 ;
if ( ! GetElevation( m_nPhase, ptPCAvSect, vtTool, m_TParams.m_dDiam / 2., m_TParams.m_dLen, vtCorr, dElev3)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
Point3d ptPTopRaw = ptPCAvSect + ( dElev3 - m_TParams.m_dDiam / 2.) * vtCorr ;
ptStart.z = max( ptPTopRaw.z - dMaxDepth, ptPCAvSect.z) ;
ptEnd.z = max( ptPTopRaw.z - dMaxDepth, ptPCAvSect.z) ;
dElev = dMaxDepth ;
}
else {
if ( ! CalcAlong5AZigZagCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, dLastElev, bExtend, false,
bFirst, bSpecialAppr, 2. * ( dStep - 10. * EPS_SMALL)))
double dElev4, dElev5 ;
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, vtCorr, dElev4) ||
! GetElevation( m_nPhase, ptStart + vtThick, ptEnd + vtThick, vtCorr, dElev5)) {
m_pMchMgr->SetLastError( 2708, "Error in SawFinishing : GetElevation") ;
return false ;
}
dElev = max( dElev4, dElev5) ;
}
// salvo dati correnti
dLastElev = dElev ;
ptStartPrev = ptStart ;
// Imposto dati comune
SetToolDir( vtTool) ;
SetCorrAuxDir( vtCorr) ;
// se utensile non piatto
if ( bFirst || bFirstMidSawCrv || ! AreSamePointEpsilon( ptStart, ptStartPrev, 10. * EPS_SMALL)) {
if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) {
if ( ! CalcAlong5AOneWayCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, bExtend, false,
bFirst, bSpecialAppr))
return false ;
}
else {
if ( ! CalcAlong5AZigZagCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, dLastElev, bExtend, false,
bFirst, bSpecialAppr, 2. * ( dStep - 10. * EPS_SMALL)))
return false ;
}
// salvo dati correnti
dLastElev = dElev ;
ptStartPrev = ptStart ;
}
bFirst = false ;
bFirstMidSawCrv = false ;
vtCorrPrev = vtCorr ;
vtToolPrev = vtTool ;
bLastToolInv = bCurrToolInv ;
}
bFirst = false ;
vtCorrPrev = vtCorr ;
vtToolPrev = vtTool ;
bLastToolInv = bCurrToolInv ;
}
}
// se ZigZag e non centrato aggiungo risalita
+26 -12
View File
@@ -26,21 +26,34 @@ class ISurfFlatRegion ;
class ISurfTriMesh ;
class Polygon3d ;
// Definizione strutture per Section/SubSection ------------------------------
struct SubSectionInfo {
PtrOwner<ICurveComposite> pSubSection ;
int nHeadSide ;
SubSectionInfo()
// Definizione strutture per Section/SubSection/SubSectionStep per Along5Ax ------------------------------
// --------------------------
struct SubSectionStep5Ax {
PtrOwner<ICurveComposite> pCompo ; // Curva ideale per centro lama
int nStep ; // Numero di Step per lavorare pCompo
double dStep ; // Lunghezza degli Step per lavorare pCompo
SubSectionStep5Ax()
: pCompo( nullptr), nStep( 0), dStep( 0.) {} ;
} ;
typedef std::vector<SubSectionStep5Ax> SUBSECTIONSTEPVECTOR ;
// --------------------------
struct SubSectionInfo5Ax {
PtrOwner<ICurveComposite> pSubSection ; // Porzione della sezione da lavorare senza cambiare Side della testa
int nHeadSide ; // Side della testa per la lavorazione
SUBSECTIONSTEPVECTOR CompoMidSawParams ; // Curve modificate di pSubSection per posizionamento centro lama ideale
INTVECTOR vnClass ; // Insieme dei tratti di classificazione
SubSectionInfo5Ax()
: pSubSection( nullptr), nHeadSide( -1) {} ;
} ;
typedef std::vector<SubSectionInfo> SUBSECTIONVECTOR ;
struct SectionInfo {
PtrOwner<ICurveComposite> pSection ;
SUBSECTIONVECTOR vSubSections ;
SectionInfo()
// --------------------------
typedef std::vector<SubSectionInfo5Ax> SUBSECTIONVECTOR ;
struct SectionInfo5Ax {
PtrOwner<ICurveComposite> pSection ; // Curva di Sezione
SUBSECTIONVECTOR vSubSections ; // Partizione di pSection in SubSection (parti che mantengono il Side della testa costante)
SectionInfo5Ax()
: pSection( nullptr), vSubSections( SUBSECTIONVECTOR{}) {} ;
} ;
typedef std::vector<SectionInfo> SECTIONVECTOR ;
typedef std::vector<SectionInfo5Ax> SECTIONVECTOR ;
//----------------------------------------------------------------------------
class SawFinishing : public Machining
@@ -119,13 +132,14 @@ class SawFinishing : public Machining
bool CalcCAvSect5Ax( const ICurveComposite* pSubSect, const std::vector<PtrOwner<ICurveComposite>>& vBoundedSections,
const Vector3d& vtTool, const Vector3d& vtCorr, const Point3d& ptP, double& dElev, bool& bOtherCollision,
bool& bAwayFromPoint) const ;
bool CalcStepsFor5AxSections( SECTIONVECTOR& vSections) const ;
bool CalcAlongVerticalCuts( ICurve* pSect, int nUmin, int nUmax, const Frame3d& frSect, bool bExtend, const Point3d& ptGdStart,
const Point3d& ptGdEnd, const Vector3d& vtGdDir, double dDepth, double dRaxMaxZ,
const Vector3d& vtTool, const Vector3d& vtCorr, const ISurfTriMesh* pStmRaw) ;
bool CalcAlongStdCuts( ICurve* pSect, double dUmin, double dUmax, bool bSkipVertMin, bool bSkipVertMax, bool bSkipVertIni, bool bSkipVertFin, bool bInvert,
const Frame3d& frSect, bool bExtend, const Point3d& ptGdStart, const Point3d& ptGdEnd, const Vector3d& vtGdDir, double dDepth,
double dRawMaxZ, const Vector3d& vtTool, const Vector3d& vtCorr, const ISurfTriMesh* pStmRaw) ;
bool CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& frSect, bool bExtend,
bool CalcAlong5ACuts( SECTIONVECTOR& vSections, const Frame3d& frSect, bool bExtend,
const Point3d& ptGdStart, const Point3d& ptGdEnd, const Vector3d& vtGdDir, double dDepth,
const BBox3d& b3Raw, const ISurfTriMesh* pStmRaw) ;
bool CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool,