EgtMachKernel :
- in Finiture di lama Along5A migliorata la collisione tra lama e sezione e aggiunto ricalcolo SideStep.
This commit is contained in:
+688
-162
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user