0ebaa582c4
- aggiunto marching cube a Zmap.
3937 lines
140 KiB
C++
3937 lines
140 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2016
|
|
//----------------------------------------------------------------------------
|
|
// File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4
|
|
// Contenuto : Implementazione della classe Volume Zmap (tre griglie)
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 22.01.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "CurveLine.h"
|
|
#include "VolZmap.h"
|
|
#include "GeoConst.h"
|
|
#include "IntersLineSurfTm.h"
|
|
#include "\EgtDev\Include\EgtNumUtils.h"
|
|
|
|
|
|
using namespace std ;
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------- OPERAZIONI SU INTERVALLI --------------------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SubtractIntervals( unsigned int nGrid, unsigned int nI, unsigned int nJ,
|
|
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax)
|
|
{
|
|
|
|
// Controllo che dMin e dMax non siano quasi coincidenti
|
|
if ( abs( dMax - dMin) < EPS_SMALL)
|
|
return true ;
|
|
|
|
// Controllo che il numero di griglia sia entro i limiti
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
// Controllo che dMin < dMax
|
|
if ( dMin > dMax)
|
|
swap( dMin, dMax) ;
|
|
|
|
// Controllo che indici nI, nJ siano entro i limiti
|
|
if ( nI < 0 && nI >= m_nNx[nGrid] &&
|
|
nJ < 0 && nJ >= m_nNy[nGrid])
|
|
return false ;
|
|
|
|
// Riporto le coordinate cicliche nell'ordine di partenza
|
|
Vector3d vtNmi = vtNMin ;
|
|
Vector3d vtNma = vtNMax ;
|
|
if ( nGrid == 1) {
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
}
|
|
else if ( nGrid == 2) {
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
}
|
|
|
|
// Calcolo nPos
|
|
unsigned int nPos = nJ * m_nNx[nGrid] + nI ;
|
|
|
|
// Ciclo sugli intervalli del singolo dexel
|
|
bool bModified = false ;
|
|
unsigned int i = 0 ;
|
|
|
|
while ( i + 1 < m_Values[nGrid][nPos].size()) {
|
|
|
|
// Casi:
|
|
// Intervallo da sottrarre è tutto a sinistra di quello corrente, non vi è intersezione
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMax - EPS_SMALL) {
|
|
;
|
|
}
|
|
// Intersezione
|
|
else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMax + EPS_SMALL) {
|
|
// L'intervallo corrente corrente viene limitato a sinistra
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMin - EPS_SMALL) {
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos][i].dZVal = dMax ;
|
|
m_Values[nGrid][nPos][i].vtN = vtNma ;
|
|
}
|
|
// L'intervallo si divide in due intervalli
|
|
else {
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ;
|
|
|
|
for ( size_t j = m_Values[nGrid][nPos].size() - 1 ; j >= i + 3 ; -- j) {
|
|
|
|
m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j - 2].dZVal ;
|
|
m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j - 2].vtN ;
|
|
}
|
|
|
|
m_Values[nGrid][nPos][i + 1].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i + 2].dZVal = dMax ;
|
|
|
|
m_Values[nGrid][nPos][i + 1].vtN = vtNMin ;
|
|
m_Values[nGrid][nPos][i + 2].vtN = vtNma ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
}
|
|
else {
|
|
// L'intervallo corrente viene eliminato
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMin - EPS_SMALL) {
|
|
bModified = true ;
|
|
for ( unsigned int j = i ; j < m_Values[nGrid][nPos].size() - 2 ; ++ j) {
|
|
|
|
m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j + 2].dZVal ;
|
|
m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j + 2].vtN ;
|
|
}
|
|
|
|
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 2) ;
|
|
|
|
i = i - 2 ;
|
|
}
|
|
// L'intervallo corrente viene limitato a destra
|
|
else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMin + EPS_SMALL) {
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos][i + 1].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i + 1].vtN = vtNmi ;
|
|
}
|
|
// L'intervallo da sottrarre è tutto a destra di quello corrente, non vi è intersezione
|
|
else {
|
|
;
|
|
}
|
|
}
|
|
|
|
i = i + 2 ;
|
|
}
|
|
|
|
// Se eseguita modifica, imposto ricalcolo della grafica
|
|
if ( bModified) {
|
|
|
|
// Determino quali blocchi sono stati modificati
|
|
int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ;
|
|
|
|
if ( nGrid == 0) {
|
|
|
|
int nXBlock = min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
|
|
int nYBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
|
|
int nMinZBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxZBlock = min( int( m_nFracLin[2] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[k * nLayerBlock + nYBlock * m_nFracLin[0] + nXBlock] = true ;
|
|
}
|
|
else if ( nGrid == 1) {
|
|
|
|
int nYBlock = min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
|
|
int nZBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
|
|
int nMinXBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxXBlock = min( int( m_nFracLin[0] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[nZBlock * nLayerBlock + nYBlock * m_nFracLin[0] + k] = true ;
|
|
}
|
|
else if ( nGrid == 2) {
|
|
|
|
int nXBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
|
|
int nZBlock = min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
|
|
int nMinYBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxYBlock = min( int( m_nFracLin[1] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[nZBlock * nLayerBlock + k * m_nFracLin[0] + nXBlock] = true ;
|
|
}
|
|
|
|
m_OGrMgr.Reset() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SubtractIntervals( unsigned int nGrid, const Point3d & ptP,
|
|
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax)
|
|
{
|
|
// Controllo che il numero di griglia sia entro i limiti.
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
// ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame)
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( m_MapFrame[nGrid]) ;
|
|
|
|
double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco
|
|
double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP)
|
|
|
|
dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ;
|
|
dhMin = dZ + dMin ; dhMax = dZ + dMax ;
|
|
|
|
// Cerco il punto della griglia più vicino
|
|
double integerPartX = floor( dX / m_dStep) ;
|
|
double integerPartY = floor( dY / m_dStep) ;
|
|
|
|
unsigned int i = static_cast <unsigned int> (integerPartX) ; // Indici del punto di griglia più vicino.
|
|
unsigned int j = static_cast <unsigned int> (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1 ;
|
|
|
|
// Controllo che gli indici ottenuti siano nella griglia:
|
|
// se sono dentro la griglia chiamo l'altra subtract
|
|
if ( i >= 0 && i < m_nNx[nGrid] &&
|
|
j >= 0 && j < m_nNy[nGrid])
|
|
|
|
return SubtractIntervals( nGrid, i, j, dhMin, dhMax, vtNMin, vtNMax) ;
|
|
// altrimenti non succede niente
|
|
else
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddIntervals( unsigned int nGrid, unsigned int nI, unsigned int nJ,
|
|
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax)
|
|
{
|
|
// Controllo che dMin e dMax non siano quasi coincidenti
|
|
if ( abs( dMax - dMin) < EPS_SMALL)
|
|
return true ;
|
|
|
|
// Controllo che il numero di griglia sia entro i limiti
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
// Controllo che dMin < dMax
|
|
if ( dMin > dMax)
|
|
swap( dMin, dMax) ;
|
|
|
|
// Controllo che indici nI, nJ siano entro i limiti
|
|
if ( nI < 0 && nI >= m_nNx[nGrid] &&
|
|
nJ < 0 && nJ >= m_nNy[nGrid])
|
|
return false ;
|
|
|
|
// Riporto le coordinate cicliche nell'ordine di partenza
|
|
Vector3d vtNmi = vtNMin ;
|
|
Vector3d vtNma = vtNMax ;
|
|
if ( nGrid == 1) {
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
}
|
|
else if ( nGrid == 2) {
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
}
|
|
|
|
// Calcolo nPos
|
|
unsigned int nPos = nJ * m_nNx[nGrid] + nI ;
|
|
|
|
|
|
// Se spillone vuoto
|
|
if ( m_Values[nGrid][nPos].size() == 0) {
|
|
|
|
m_Values[nGrid][nPos].resize( 2) ;
|
|
|
|
m_Values[nGrid][nPos][0].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][1].dZVal = dMax ;
|
|
|
|
m_Values[nGrid][nPos][0].vtN = vtNmi ;
|
|
m_Values[nGrid][nPos][1].vtN = vtNma ;
|
|
|
|
if ( dMax > m_dMaxZ[nGrid])
|
|
m_dMinZ[nGrid] = dMax ;
|
|
|
|
if ( dMin < m_dMinZ[nGrid])
|
|
m_dMinZ[nGrid] = dMin ;
|
|
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
// Ciclo sugli intervalli dello spillone
|
|
bool bModified = false ;
|
|
unsigned int i = 0 ;
|
|
while ( i + 1 < m_Values[nGrid][nPos].size()) {
|
|
|
|
// Eventuale aggiustamento di intervalli sovrapposti
|
|
if ( i > 0) {
|
|
|
|
if ( m_Values[nGrid][nPos][i].dZVal < m_Values[nGrid][nPos][i - 1].dZVal + EPS_SMALL) {
|
|
|
|
// Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva
|
|
if ( m_Values[nGrid][nPos][i - 1].dZVal < m_Values[nGrid][nPos][i + 1].dZVal + EPS_SMALL) {
|
|
|
|
m_Values[nGrid][nPos][i - 1].dZVal = m_Values[nGrid][nPos][i + 1].dZVal ;
|
|
m_Values[nGrid][nPos][i - 1].vtN = m_Values[nGrid][nPos][i + 1].vtN ;
|
|
}
|
|
|
|
for ( unsigned int j = i ; j < m_Values[nGrid][nPos].size() - 2 ; ++ j) {
|
|
|
|
m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j + 2].dZVal ;
|
|
m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j + 2].vtN ;
|
|
}
|
|
|
|
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 2) ;
|
|
|
|
i = i - 2 ;
|
|
}
|
|
}
|
|
|
|
// Caso in cui devo aggiungere un intervallo a sinistra dell'intervallo corrente
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMax + EPS_SMALL) {
|
|
|
|
bModified = true ;
|
|
|
|
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ;
|
|
|
|
for ( size_t j = m_Values[nGrid][nPos].size() - 1 ; j >= i + 2 ; -- j) {
|
|
|
|
m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j - 2].dZVal ;
|
|
m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j - 2].vtN ;
|
|
}
|
|
|
|
|
|
m_Values[nGrid][nPos][i].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i + 1].dZVal = dMax ;
|
|
|
|
m_Values[nGrid][nPos][i].vtN = vtNMin ;
|
|
m_Values[nGrid][nPos][i + 1].vtN = vtNMax ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
|
|
// Casi d'intersezione:
|
|
else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMax - EPS_SMALL) {
|
|
|
|
// Se l'intervallo da aggiungere sconfina a sinistra modifico il minimo dell'intervalo corrente
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMin - EPS_SMALL) {
|
|
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos][i].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i].vtN = vtNmi ;
|
|
}
|
|
}
|
|
|
|
else {
|
|
// Se l'intervallo corrente è tutto contenuto nell'intervallo da aggungere modifico gli estremi
|
|
if ( m_Values[nGrid][nPos][i].dZVal > dMin + EPS_SMALL) {
|
|
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos][i].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i + 1].dZVal = dMax ;
|
|
m_Values[nGrid][nPos][i].vtN = vtNMin ;
|
|
m_Values[nGrid][nPos][i + 1].vtN = vtNma ;
|
|
}
|
|
// Se l'intervallo da aggiungere sconfina a destra modifico il massimo dell'intervallo corrente
|
|
else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMin - EPS_SMALL) {
|
|
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos][i + 1].dZVal = dMax ;
|
|
m_Values[nGrid][nPos][i + 1].vtN = vtNma ;
|
|
}
|
|
else {
|
|
// Aggiungo intervallo a destra dell'ultimo intervallo
|
|
if ( i == m_Values[nGrid][nPos].size() - 2) {
|
|
|
|
bModified = true ;
|
|
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ;
|
|
|
|
m_Values[nGrid][nPos][i + 2].dZVal = dMin ;
|
|
m_Values[nGrid][nPos][i + 3].dZVal = dMax ;
|
|
m_Values[nGrid][nPos][i + 2].vtN = vtNmi ;
|
|
m_Values[nGrid][nPos][i + 3].vtN = vtNma ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
i = i + 2 ;
|
|
}
|
|
|
|
// se eseguita modifica, imposto ricalcolo della grafica
|
|
if ( bModified) {
|
|
|
|
// Determino quali blocchi sono stati modificati
|
|
int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ;
|
|
|
|
if ( nGrid == 0) {
|
|
|
|
int nXBlock = min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
|
|
int nYBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
|
|
int nMinZBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxZBlock = min( int( m_nFracLin[2] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[k * nLayerBlock + nYBlock * m_nFracLin[0] + nXBlock] = true ;
|
|
}
|
|
else if ( nGrid == 1) {
|
|
|
|
int nYBlock = min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
|
|
int nZBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
|
|
int nMinXBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxXBlock = min( int( m_nFracLin[0] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[nZBlock * nLayerBlock + nYBlock * m_nFracLin[0] + k] = true ;
|
|
}
|
|
else if ( nGrid == 2) {
|
|
|
|
int nXBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
|
|
int nZBlock = min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
|
|
int nMinYBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
int nMaxYBlock = min( int( m_nFracLin[1] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ;
|
|
|
|
for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k)
|
|
|
|
m_BlockToUpdate[nZBlock * nLayerBlock + k * m_nFracLin[0] + nXBlock] = true ;
|
|
}
|
|
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// Aggiorno massima e minima Z
|
|
// sullo Zmap
|
|
if ( dMax > m_dMaxZ[nGrid])
|
|
m_dMinZ[nGrid] = dMax ;
|
|
|
|
if ( dMin < m_dMinZ[nGrid])
|
|
m_dMinZ[nGrid] = dMin ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddIntervals( unsigned int nGrid, const Point3d & ptP,
|
|
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax)
|
|
{
|
|
// Controllo che il numero di griglia sia entro i limiti.
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
// ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame)
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( m_MapFrame[nGrid]) ;
|
|
|
|
double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco
|
|
double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP)
|
|
|
|
dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ;
|
|
dhMin = dZ + dMin ; dhMax = dZ + dMax ;
|
|
|
|
// Cerco il punto della griglia più vicino
|
|
double integerPartX = floor( dX / m_dStep) ;
|
|
double integerPartY = floor( dY / m_dStep) ;
|
|
|
|
unsigned int i = static_cast <unsigned int> (integerPartX) ; // Indici del punto di griglia più vicino.
|
|
unsigned int j = static_cast <unsigned int> (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1
|
|
|
|
// Controllo che gli indici ottenuti siano nella griglia:
|
|
// se sono dentro la griglia chiamo l'altra add
|
|
if ( i >= 0 && i < m_nNx[nGrid] &&
|
|
j >= 0 && j < m_nNy[nGrid])
|
|
|
|
return AddIntervals( nGrid, i, j, dhMin, dhMax, vtNMin, vtNMax) ;
|
|
else
|
|
// altrimenti non succede niente
|
|
return false ;
|
|
}
|
|
|
|
// ------------------------- LAVORAZIONI --------------------------------------------------------------------------------------
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Point3d& ptPe, const Vector3d& vtDe)
|
|
{
|
|
// Controllo sull'effettiva esisenza del movimento
|
|
if ( AreSamePointApprox( ptPs, ptPe) && AreSameVectorApprox( vtDs, vtDe))
|
|
return true ;
|
|
|
|
// Punti nei sistemi di riferimento intrinseci dello Zmap
|
|
Point3d ptLs[3] ;
|
|
Point3d ptLe[3] ;
|
|
|
|
ptLs[0] = ptPs ;
|
|
ptLs[0].ToLoc( m_MapFrame[0]) ;
|
|
|
|
ptLe[0] = ptPe ;
|
|
ptLe[0].ToLoc( m_MapFrame[0]) ;
|
|
|
|
if ( m_nMapNum > 1) {
|
|
|
|
ptLs[1].x = ptLs[0].y ; ptLs[1].y = ptLs[0].z ; ptLs[1].z = ptLs[0].x ;
|
|
ptLs[2].x = ptLs[0].z ; ptLs[2].y = ptLs[0].x ; ptLs[2].z = ptLs[0].y ;
|
|
|
|
ptLe[1].x = ptLe[0].y ; ptLe[1].y = ptLe[0].z ; ptLe[1].z = ptLe[0].x ;
|
|
ptLe[2].x = ptLe[0].z ; ptLe[2].y = ptLe[0].x ; ptLe[2].z = ptLe[0].y ;
|
|
}
|
|
else {
|
|
|
|
ptLs[1].x = 0 ; ptLs[1].y = 0 ; ptLs[1].z = 0 ;
|
|
ptLs[2].x = 0 ; ptLs[2].y = 0 ; ptLs[2].z = 0 ;
|
|
|
|
ptLe[1].x = 0 ; ptLe[1].y = 0 ; ptLe[1].z = 0 ;
|
|
ptLe[2].x = 0 ; ptLe[2].y = 0 ; ptLe[2].z = 0 ;
|
|
}
|
|
|
|
|
|
// Vettori nei sistemi di riferimento intrinseci dello Zmap
|
|
Vector3d vtLs [3] ;
|
|
Vector3d vtLe [3] ;
|
|
|
|
vtLs[0] = vtDs ;
|
|
vtLs[0].ToLoc( m_MapFrame[0]) ;
|
|
|
|
vtLe[0] = vtDe ;
|
|
vtLe[0].ToLoc( m_MapFrame[0]) ;
|
|
|
|
if ( m_nMapNum > 1) {
|
|
|
|
vtLs[1].x = vtLs[0].y ; vtLs[1].y = vtLs[0].z ; vtLs[1].z = vtLs[0].x ;
|
|
vtLs[2].x = vtLs[0].z ; vtLs[2].y = vtLs[0].x ; vtLs[2].z = vtLs[0].y ;
|
|
|
|
vtLe[1].x = vtLe[0].y ; vtLe[1].y = vtLe[0].z ; vtLe[1].z = vtLe[0].x ;
|
|
vtLe[2].x = vtLe[0].z ; vtLe[2].y = vtLe[0].x ; vtLe[2].z = vtLe[0].y ;
|
|
}
|
|
else {
|
|
|
|
vtLs[1].x = 0 ; vtLs[1].y = 0 ; vtLs[1].z = 0 ;
|
|
vtLs[2].x = 0 ; vtLs[2].y = 0 ; vtLs[2].z = 0 ;
|
|
|
|
vtLe[1].x = 0 ; vtLe[1].y = 0 ; vtLe[1].z = 0 ;
|
|
vtLe[2].x = 0 ; vtLe[2].y = 0 ; vtLe[2].z = 0 ;
|
|
}
|
|
|
|
|
|
// Ciclo sulle mappe
|
|
for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) {
|
|
// Normalizzo i vettori
|
|
vtLs[i].Normalize() ;
|
|
vtLe[i].Normalize() ;
|
|
|
|
// Direzione utensile costante: pura traslazione
|
|
if ( AreSameVectorApprox( vtLs[i], vtLe[i])) {
|
|
|
|
// Proiezione dei vettori sulle rispettive griglie
|
|
Vector3d vtLsXY( vtLs[i].x, vtLs[i].y, 0) ;
|
|
|
|
// Versore utensile parallelo all'asse Z
|
|
if ( vtLsXY.SqLen() < EPS_SMALL * EPS_SMALL) {
|
|
|
|
Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ;
|
|
|
|
// Foratura
|
|
if ( vtMove.SqLenXY() < EPS_SMALL) {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa conica
|
|
else if ( m_nToolType == 4)
|
|
Conus_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
// Fresatura con vettore movimento perpendicolare all'utensile
|
|
else if ( abs( vtMove.z) < EPS_SMALL) {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_ZPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa conica
|
|
else if ( m_nToolType == 4)
|
|
Conus_ZPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
// Fresatura con vettore movimento generico rispetto all'utensile
|
|
else {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa conica
|
|
else
|
|
Conus_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
}
|
|
// Versore utensile nel piano
|
|
else if ( abs( vtLs[i].z) < EPS_SMALL) {
|
|
|
|
Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ;
|
|
Vector3d vtMLong = ( vtMove * vtLs[i]) * vtLs[i] ;
|
|
Vector3d vtMOrt = vtMove - vtMLong ;
|
|
|
|
double dSqLOrt = vtMOrt.SqLen() ;
|
|
|
|
// Foratura
|
|
if ( dSqLOrt < EPS_SMALL * EPS_SMALL) {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_XYDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa conica
|
|
else
|
|
Conus_XYDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
// Fresatura con vettore movimento perpendicolare all'utensile
|
|
else if ( 1 - dSqLOrt < EPS_SMALL * EPS_SMALL) {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa conica
|
|
else if ( m_nToolType == 4)
|
|
Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
// Fresatura con vettore movimento generico rispetto all'utensile
|
|
else {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica o sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_XYMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Altri utensili
|
|
else if ( m_nToolType == 4)
|
|
Conus_XYMilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
}
|
|
// Versore utensile con direzione generica
|
|
else {
|
|
|
|
Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ;
|
|
Vector3d vtMLong = ( vtMove * vtLs[i]) * vtLs[i] ;
|
|
Vector3d vtMOrt = vtMove - vtMLong ;
|
|
|
|
double dSqLOrt = vtMOrt.SqLen() ;
|
|
|
|
// Foratura
|
|
if ( dSqLOrt < EPS_SMALL * EPS_SMALL) {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica e sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
else if ( m_nToolType == 4)
|
|
Conus_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
else {
|
|
// Utensile generico
|
|
if ( m_nToolType == 0)
|
|
GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
// Fresa cilindrica e sferica
|
|
else if ( m_nToolType == 1 || m_nToolType == 2)
|
|
CylBall_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
else if ( m_nToolType == 4)
|
|
Conus_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
}
|
|
}
|
|
}
|
|
else ;
|
|
// Altri casi al momento non gestiti
|
|
// return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// ---------- VERSORE UTENSILE DERETTO COME Z --------------------------------
|
|
|
|
|
|
// ---------- Cilindro e sfera -----------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Proiezione dei punti sul piano
|
|
Point3d ptSxy( ptS.x, ptS.y, 0) ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
|
|
// Punte del gambo
|
|
Point3d ptTStemS = ptS - vtToolDir * dStemHeigth ;
|
|
Point3d ptTStemE = ptE - vtToolDir * dStemHeigth ;
|
|
|
|
// Quote estreme del gambo
|
|
double dMinStemZ = min( min( ptS.z, ptTStemS.z), min( ptE.z, ptTStemE.z)) ;
|
|
double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptE.z, ptTStemE.z)) ;
|
|
|
|
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptSxy ;
|
|
|
|
double dSqLen = vtC.SqLen() ;
|
|
|
|
// Se il punto si trova dentro il cerchio taglio
|
|
if ( dSqLen < dSqRad)
|
|
// utensile cilindrico
|
|
if ( m_nToolType == CylindricalMill)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, vtToolDir, - vtToolDir) ;
|
|
// utensile sferico
|
|
else if ( m_nToolType == BallEndMill) {
|
|
|
|
double dH = sqrt( dSqRad - dSqLen) ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
|
|
Vector3d vtNorm = Point3d( ptSxy.x, ptSxy.y, dMinStemZ) - Point3d( dX, dY, dMinStemZ - dH) ;
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, vtNorm, - vtToolDir) ;
|
|
}
|
|
else {
|
|
|
|
Vector3d vtNorm = Point3d( ptSxy.x, ptSxy.y, dMinStemZ) - Point3d( dX, dY, dMinStemZ + dH) ;
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ + dH, - vtToolDir, vtNorm) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZPerp( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
//Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
|
|
// Punte del gambo
|
|
Point3d ptTStemS = ptS - vtToolDir * dStemHeigth ;
|
|
Point3d ptTStemE = ptE - vtToolDir * dStemHeigth ;
|
|
|
|
// Quote estreme del gambo
|
|
double dMinStemZ = min( min( ptS.z, ptTStemS.z), min( ptE.z, ptTStemE.z)) ;
|
|
double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptS.z, ptTStemS.z)) ;
|
|
|
|
// Vettore movimento e sua lunghezza
|
|
Vector3d vtMove = ptE - ptS ; double dLen = vtMove.LenXY() ;
|
|
|
|
// Definizione di un sistema di riferimento ad hoc
|
|
Point3d ptSxy( ptS.x, ptS.y, 0) ;
|
|
Vector3d vtV1 = vtMove ; vtV1.Normalize() ; // se |vtMove| < EPS è un buco con dz = 0
|
|
Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptSxy ;
|
|
|
|
double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ;
|
|
|
|
// Utensile cilindrico
|
|
if ( m_nToolType == CylindricalMill) {
|
|
// Se il punto cade nella zona di interesse taglio
|
|
if ( ( dP1 * dP1 + dP2 * dP2 < dSqRad) ||
|
|
( ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2) < dSqRad ||
|
|
( dP1 > 0 && dP1 < dLen && abs( dP2) < m_dRadius))
|
|
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, V_NULL, V_NULL) ;
|
|
}
|
|
// Utensile sferico
|
|
else if ( m_nToolType == BallEndMill) {
|
|
|
|
if ( dP1 < 0 && dP1 * dP1 + dP2 * dP2 < m_dRadius * m_dRadius) {
|
|
|
|
double dH = sqrt( dSqRad - dP1 * dP1 - dP2 * dP2) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ + dH, V_NULL, V_NULL) ;
|
|
}
|
|
else if ( dP1 > dLen && ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2 < dSqRad) {
|
|
|
|
double dH = sqrt( dSqRad - ( dP1 - dLen) * ( dP1 - dLen) - dP2 * dP2) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ + dH, V_NULL, V_NULL) ;
|
|
}
|
|
else if ( dP1 > - EPS_SMALL && dP1 < dLen + EPS_SMALL && abs( dP2) < m_dRadius) {
|
|
|
|
double dH = sqrt( dSqRad - dP2 * dP2) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ + dH, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
|
|
// Studio delle simmetrie
|
|
Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ;
|
|
Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ;
|
|
Point3d ptIT = ptI - vtToolDir * dStemHeigth ;
|
|
Point3d ptFT = ptF - vtToolDir * dStemHeigth ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
// Quote iniziali e finali massime e
|
|
// minime del gambo dell'utensile e DeltaZ
|
|
double dZMaxI = max( ptI.z, ptIT.z) ;
|
|
double dZMaxF = max( ptF.z, ptFT.z) ;
|
|
double dZMinI = dZMaxI - dStemHeigth ;
|
|
double dZMinF = dZMaxF - dStemHeigth ;
|
|
double dDeltaZ = dZMaxF - dZMaxI ;
|
|
|
|
// Vettori caratterizzanti il moto
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
double dLen = vtMove.Len() ;
|
|
double dLenXY = vtMoveXY.LenXY() ;
|
|
vtMove.Normalize() ;
|
|
|
|
// Parametri per determinare l'ellisse proiettata
|
|
double dCos = vtToolDir * vtMove ;
|
|
double dSin = ( abs( dCos) < 1 ? 1 - dCos * dCos : 0) ;
|
|
double dSemiAxMin = m_dRadius * dCos ; // x1^2 = a^2 - (a / b)^2 x2^2 ; a = r dCos e b = r;
|
|
double dSqSemiAxMin = dSemiAxMin * dSemiAxMin ; // da cui si ottiene x1^2 = a^2 - dCos^2 x2^2
|
|
double dSqRatio = dSqSemiAxMin / dSqRad ;
|
|
|
|
// Definizione di un sistema di riferimento ad hoc
|
|
Vector3d vtV1, vtV2 ;
|
|
|
|
// Se la lunghezza è troppo piccola lo allungo
|
|
if ( dLenXY < EPS_SMALL)
|
|
vtV1 = ( 1 / dLenXY) * vtMoveXY ;
|
|
else
|
|
vtV1 = vtMoveXY ;
|
|
|
|
// Normalizzo vtV1
|
|
vtV1.Normalize() ;
|
|
// Definisco vtV2
|
|
vtV2 = vtV1 ;
|
|
vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
double dMin, dMax ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dX1 = vtC * vtV1 ;
|
|
double dX2 = vtC * vtV2 ;
|
|
|
|
// Se il punto appartiene alla proiezione del volume spazzato valuto massimo e minimo
|
|
if ( ( dX1 > 0 && dX1 < dLenXY && abs( dX2) < m_dRadius) ||
|
|
( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad ||
|
|
dX1 * dX1 + dX2 * dX2 < dSqRad) {
|
|
|
|
if ( m_nToolType == CylindricalMill) {
|
|
|
|
double dX1_0 = sqrt( dSqRad - dX2 * dX2) ;
|
|
// Massimo
|
|
if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad)
|
|
|
|
dMax = dZMaxF ;
|
|
else
|
|
dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ;
|
|
// Minimo
|
|
if ( dX1 * dX1 + dX2 * dX2 < dSqRad)
|
|
|
|
dMin = dZMinI ;
|
|
else
|
|
dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
else if ( m_nToolType == BallEndMill) {
|
|
|
|
double dCylX1_0 = sqrt( dSqRad - dX2 * dX2) ;
|
|
double dSqRoot = sqrt( dSqRad - dX2 * dX2) ;
|
|
double dX1_0 = dCos * dSqRoot ;
|
|
double dH0 = dSin * dSqRoot ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
// Massimo
|
|
if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad)
|
|
|
|
dMax = dZMaxF ;
|
|
else
|
|
dMax = dZMaxI + dDeltaZ * ( dX1 + dCylX1_0) / dLenXY ;
|
|
|
|
// Minimo
|
|
if ( dX1 < dX1_0)
|
|
|
|
dMin = dZMinI - sqrt( dSqRad - dX1 * dX1 - dX2 * dX2) ;
|
|
|
|
else if ( dX1 < dLenXY + dX1_0)
|
|
|
|
dMin = dZMinI - dH0 + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
|
|
else
|
|
dMin = dZMinF - sqrt( dSqRad - ( dX1 - dLenXY) * ( dX1 - dLenXY) - dX2 * dX2) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
else {
|
|
// Massimo
|
|
if ( dX1 < - dX1_0)
|
|
|
|
dMax = dZMaxI + sqrt( dSqRad - dX1 * dX1 - dX2 * dX2) ;
|
|
|
|
else if ( dX1 < dLenXY - dX1_0)
|
|
|
|
dMax = dZMaxI + dH0 + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
|
|
else
|
|
dMax = dZMaxF + sqrt( dSqRad - ( dX1 - dLenXY) * ( dX1 - dLenXY) - dX2 * dX2) ;
|
|
|
|
// Minimo
|
|
if ( dX1 * dX1 + dX2 * dX2 < dSqRad)
|
|
|
|
dMin = dZMinI ;
|
|
else
|
|
dMin = dZMinI + dDeltaZ * ( dX2 - dCylX1_0) / dLenXY ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
|
|
// ---------- Coni -----------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dDeltaRad = dMaxRad - dMinRad ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
|
|
// Proiezione delle posizioni sul piano
|
|
Point3d ptO( ptS.x, ptS.y, 0) ;
|
|
|
|
// Quote massime e minime dell'utensile durante il moto
|
|
double dZMax = max( max( ptS.z, ptS.z - vtToolDir.z * m_dHeight), max( ptE.z, ptE.z - vtToolDir.z * m_dHeight)) ;
|
|
double dZMin = min( min( ptS.z, ptS.z - vtToolDir.z * m_dHeight), min( ptE.z, ptE.z - vtToolDir.z * m_dHeight)) ;
|
|
|
|
// Trapano
|
|
if ( m_dTipRadius < m_dRadius) {
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptO ;
|
|
|
|
double dSqDist = vtC.SqLenXY() ;
|
|
|
|
if ( dSqDist < dSqMinRad)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax, V_NULL, V_NULL) ;
|
|
|
|
else if ( dSqDist < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDist) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin + m_dTipHeight * ( dr - dMinRad) / dDeltaRad, dZMax, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax - m_dTipHeight * ( dr - dMinRad) / dDeltaRad, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Coda di rondine
|
|
else {
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptO ;
|
|
|
|
double dSqDist = vtC.SqLenXY() ;
|
|
|
|
if ( dSqDist < dSqMinRad)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax, V_NULL, V_NULL) ;
|
|
|
|
else if ( dSqDist < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDist) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax - dStemHeigth - m_dTipHeight * ( dr - dMinRad) / dDeltaRad, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dZMin + dStemHeigth + m_dTipHeight * ( dr - dMinRad) / dDeltaRad, dZMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZPerp( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dDeltaRad = dMaxRad - dMinRad ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
|
|
// Quote fondo, punta e fine gambo
|
|
double dBaseZ = ptS.z ;
|
|
double dTipZ = ptS.z - m_dHeight * vtToolDir.z ;
|
|
double dStemZ = ptS.z - dStemHeigth * vtToolDir.z ;
|
|
double dZ1 = ( m_dRadius > m_dTipRadius ? dBaseZ : dTipZ) ;
|
|
double dZ2 = ( m_dRadius > m_dTipRadius ? dTipZ : dStemZ) ;
|
|
double dZ3 = ( m_dRadius > m_dTipRadius ? dStemZ : dTipZ) ;
|
|
|
|
|
|
// Sistemi di riferimento sul piano
|
|
Point3d ptIxy( ptS.x, ptS.y, 0) ;
|
|
Point3d ptFxy( ptE.x, ptE.y, 0) ;
|
|
Vector3d vtV1 = ptFxy - ptIxy ;
|
|
double dLenXY = vtV1.LenXY() ;
|
|
vtV1.Normalize() ;
|
|
Vector3d vtV2 = vtV1 ;
|
|
vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtCI = ptC - ptIxy ;
|
|
Vector3d vtCF = ptC - ptFxy ;
|
|
|
|
double dSqDistI = vtCI.SqLenXY() ;
|
|
double dSqDistF = vtCF.SqLenXY() ;
|
|
|
|
double dX1 = vtCI * vtV1 ;
|
|
double dX2 = vtCI * vtV2 ;
|
|
|
|
|
|
if ( dSqDistI < dSqMinRad || dSqDistF < dSqMinRad ||
|
|
( dX1 > 0 && dX1 < dLenXY && abs( dX2) < dMinRad))
|
|
|
|
SubtractIntervals( nGrid, i, j, min( dBaseZ, dTipZ), max( dBaseZ, dTipZ), V_NULL, V_NULL) ;
|
|
|
|
else if ( dSqDistI < dSqMaxRad && dX1 < 0) {
|
|
|
|
double dr = sqrt( dSqDistI) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, min( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad),
|
|
max( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad), V_NULL, V_NULL) ;
|
|
}
|
|
else if ( dX1 <= dLenXY && abs( dX2) < dMaxRad) {
|
|
|
|
double dr = abs( dX2) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, min( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad),
|
|
max( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad), V_NULL, V_NULL) ;
|
|
}
|
|
else if ( dSqDistF < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDistF) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, min( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad),
|
|
max( dZ1, dZ2 + ( dr - dMinRad) * ( dZ3 - dZ2) / dDeltaRad), V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
if ( m_dTipRadius < m_dRadius)
|
|
Dr_ZMilling( nGrid, ptS, ptE, vtToolDir) ;
|
|
else
|
|
Sw_ZMilling( nGrid, ptS, ptE, vtToolDir) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Dr_ZMilling( unsigned int nGrid, const Point3d & ptLs, const Point3d & ptLe, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza dell'utensile con lo Zmap
|
|
bool bTest = BoundingBox( nGrid, ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Punti iniziale e finale e proiezione sul piano del punto iniziale
|
|
Point3d ptI, ptF, ptO ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ;
|
|
}
|
|
else {
|
|
ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
}
|
|
|
|
// Raggio minimo e massimo
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Quote iniziale e finale della base dell'utensile e DeltaZ
|
|
double dZI = ptI.z ;
|
|
double dZF = ptF.z ;
|
|
double dDeltaZ = dZF - dZI ;
|
|
|
|
|
|
// Vettori di movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ;
|
|
|
|
// Sistema di riferimento sul cono e vertice del cono
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
Point3d ptV = ptI - ( m_dHeight + m_dTipHeight * dMinRad / ( dMaxRad - dMinRad)) * vtV1 ;
|
|
|
|
// Apertura del cono e parametri per determinare i piani
|
|
double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ;
|
|
double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ;
|
|
|
|
double dCos = dTanAlpha * dRatio ;
|
|
double dSin = ( abs( dCos) < 1 ? sqrt( 1 - dCos * dCos) : 0) ;
|
|
|
|
double dDen = sqrt( 1 + dTanAlpha * dTanAlpha) ;
|
|
|
|
// Versori normali e prodotti scalari per per determinare i piani
|
|
Vector3d vtNs = - ( dTanAlpha / dDen) * vtV1 +
|
|
( dCos / dDen) * vtV2 +
|
|
( dSin / dDen) * vtV3 ;
|
|
Vector3d vtNd = - ( dTanAlpha / dDen) * vtV1 +
|
|
( dCos / dDen) * vtV2 -
|
|
( dSin / dDen) * vtV3 ;
|
|
|
|
Vector3d vtR0 = ptV - ORIG ;
|
|
double dDots = vtR0 * vtNs ;
|
|
double dDotd = vtR0 * vtNd ;
|
|
|
|
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
// Grandezze per determinare la configurazione geometrica dell'utensile
|
|
double dMin, dMax ;
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptO ;
|
|
Vector3d vtCf = vtC - vtMoveXY ;
|
|
|
|
Vector3d vtUC = vtC ; vtUC.Normalize() ;
|
|
Vector3d vtUCf = vtCf ; vtUCf.Normalize() ;
|
|
|
|
double dCCos = vtUC * vtV2 ;
|
|
double dCCosf = vtUCf * vtV2 ;
|
|
|
|
double dProj = vtC * vtV2 ;
|
|
Vector3d vtOrt = vtC - dProj * vtV2 ;
|
|
|
|
double dSqDistI = vtC * vtC ;
|
|
double dSqDistM = vtOrt * vtOrt ;
|
|
double dSqDistF = vtCf * vtCf ;
|
|
|
|
// Se dentro la zona interessata dalla lavorazione valuto
|
|
// la tipologia di tale zona
|
|
if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad) ||
|
|
( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad) ||
|
|
( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) {
|
|
|
|
// Caso vettore utensile equiverso all'asse Z
|
|
if ( vtToolDir.z > 0) {
|
|
// Massimi
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
if ( dProj < dLen - dPMaxI)
|
|
|
|
dMax = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxI) ;
|
|
else
|
|
dMax = dZF ;
|
|
|
|
// Minimi
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZI - m_dHeight ;
|
|
|
|
else {
|
|
|
|
if ( ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMin = dZI - m_dHeight + ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMin = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ;
|
|
else
|
|
dMin = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMin = dZF - m_dHeight + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
|
|
dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZI - m_dHeight + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen)
|
|
|
|
dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
}
|
|
// Caso vettore utensile opposto all'asse Z
|
|
else {
|
|
// Massimi
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZI + m_dHeight ;
|
|
|
|
else {
|
|
|
|
if ( - ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMax = dZI + m_dHeight - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMax = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ;
|
|
else
|
|
dMax = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMax = dZF + m_dHeight - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
|
|
dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZI + m_dHeight - ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen)
|
|
|
|
dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
}
|
|
// Minimi
|
|
double dPMaxCirc = sqrt( dMaxRad * dMaxRad - dSqDistM) ;
|
|
|
|
if ( dProj > dLen - dPMaxCirc)
|
|
dMin = dZF ;
|
|
else
|
|
dMin = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxCirc) ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Sw_ZMilling( unsigned int nGrid, const Point3d & ptLs, const Point3d & ptLe, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza dell'utensile con lo Zmap
|
|
bool bTest = BoundingBox( nGrid, ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Punti iniziale e finale e proiezione sul piano del punto iniziale
|
|
Point3d ptI, ptF, ptO ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
|
|
ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
}
|
|
|
|
else {
|
|
ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ;
|
|
}
|
|
|
|
Point3d ptICyl = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
double dDeltaH = m_dHeight - m_dTipHeight ;
|
|
double dMinZCyl = min( ptICyl.z, ptICyl.z - vtToolDir.z * dDeltaH) ;
|
|
|
|
// Punti contatto cono cilindro
|
|
Point3d ptIS = ptI - ( m_dHeight - m_dTipHeight) * vtToolDir ;
|
|
Point3d ptFS = ptF - ( m_dHeight - m_dTipHeight) * vtToolDir ;
|
|
|
|
// Quote iniziali e finali e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ;
|
|
double dDeltaZ = dZF - dZI ; double dADeltaZ = abs( dDeltaZ) ;
|
|
double dZIS = ptIS.z ; double dZFS = ptFS.z ;
|
|
|
|
// Vettori di movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ;
|
|
|
|
// Sistema di riferimento sul cono e vertice del cono
|
|
Vector3d vtV1 = - vtToolDir ;
|
|
Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
Point3d ptV = ptI + ( m_dHeight - m_dTipHeight * ( 1 + dMinRad / ( dMaxRad - dMinRad))) * vtV1 ;
|
|
|
|
// Apertura del cono e parametri per determinare i piani
|
|
double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ;
|
|
double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ;
|
|
|
|
double dCos = dTanAlpha * dRatio ;
|
|
double dSin = ( abs( dCos) < 1 ? sqrt( 1- dCos * dCos) : 0) ;
|
|
|
|
double dDen = sqrt( 1 + dTanAlpha * dTanAlpha) ;
|
|
|
|
// Versori normali e prodotti scalari per per determinare i piani
|
|
Vector3d vtNp = - ( dTanAlpha / dDen) * vtV1 +
|
|
( dCos / dDen) * vtV2 +
|
|
( dSin / dDen) * vtV3 ;
|
|
Vector3d vtNm = - ( dTanAlpha / dDen) * vtV1 +
|
|
( dCos / dDen) * vtV2 -
|
|
( dSin / dDen) * vtV3 ;
|
|
|
|
Vector3d vtR0 = ptV - ORIG ;
|
|
double dDotp = vtR0 * vtNp ;
|
|
double dDotm = vtR0 * vtNm ;
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++j) {
|
|
|
|
double dMin, dMax ;
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; Vector3d vtCf = vtC - vtMoveXY ;
|
|
|
|
Vector3d vtUC = vtC ; Vector3d vtUCf = vtCf ; vtUC.Normalize() ; vtUCf.Normalize() ;
|
|
|
|
double dCCos = vtUC * vtV2 ; double dCCosf = vtUCf * vtV2 ;
|
|
|
|
double dProj = vtC * vtV2 ;
|
|
Vector3d vtOrt = vtC - dProj * vtV2 ;
|
|
|
|
double dSqDistI = vtC * vtC ;
|
|
double dSqDistM = vtOrt * vtOrt ;
|
|
double dSqDistF = vtCf * vtCf ;
|
|
|
|
if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad) ||
|
|
( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad) ||
|
|
( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) {
|
|
// Caso vettore utensile equiverso all'asse Z
|
|
if ( vtV1.z < 0) {
|
|
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
// Massimi
|
|
if ( dRatio <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS ;
|
|
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMax = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ;
|
|
else
|
|
dMax = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMax = dZFS - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS ;
|
|
|
|
else if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else {
|
|
|
|
if ( dProj >= dPMaxI)
|
|
|
|
dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
// Minimi
|
|
|
|
if ( dSqDistF < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZFS - m_dTipHeight ;
|
|
|
|
else if ( dProj <= dLen - dPMaxI)
|
|
|
|
dMin = dZIS - m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
// Caso vettore utensile opposto all'asse Z
|
|
else {
|
|
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
// Massimi
|
|
if ( dSqDistF < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZFS + m_dTipHeight ;
|
|
|
|
else if ( dProj <= dLen - dPMaxI)
|
|
|
|
dMax = dZIS + m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
// Minimi
|
|
if ( dRatio <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS ;
|
|
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMin = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ;
|
|
else
|
|
dMin = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMin = dZFS + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS ;
|
|
|
|
else if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else
|
|
|
|
dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
}
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Parte cilindrica
|
|
Vector3d vtCyl = ( vtV1.z < 0 ? vtCf : vtC) ;
|
|
Vector3d vtCylf = ( vtV1.z < 0 ? vtC : vtCf) ;
|
|
Vector3d vtMot = ( vtV1.z < 0 ? - vtV2 : vtV2) ;
|
|
|
|
double dCylProj = vtCyl * vtMot ;
|
|
double dCylSqDistI = vtCyl * vtCyl ;
|
|
double dCylSqDistF = vtCylf * vtCylf ;
|
|
double dCylSqDistM = ( vtCyl - dCylProj * vtMot) * ( vtCyl - dCylProj * vtMot) ;
|
|
|
|
|
|
if ( dCylSqDistI < dMinRad * dMinRad
|
|
|| dCylSqDistF < dMinRad * dMinRad
|
|
|| ( dCylProj > 0 && dCylProj < dLen && dCylSqDistM < dMinRad * dMinRad)) {
|
|
|
|
double dSt = sqrt( dMinRad * dMinRad - dCylSqDistM) ;
|
|
|
|
// Minimi
|
|
if ( dCylSqDistI < dMinRad * dMinRad )
|
|
|
|
dMin = dMinZCyl ;
|
|
|
|
else if ( dCylProj >= dSt)
|
|
|
|
dMin = dMinZCyl + ( dCylProj - dSt) * dADeltaZ / dLen ;
|
|
|
|
// Massimi
|
|
if ( dCylSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dMinZCyl + dDeltaH + dADeltaZ ;
|
|
|
|
else if ( dCylProj <= dLen - dSt)
|
|
|
|
dMax = dMinZCyl + dDeltaH + ( dCylProj + dSt) * dADeltaZ / dLen ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// --------- Utensile generico ------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Posizioni iniziale e finale dell'utensile
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
|
|
// vettore movimento
|
|
Vector3d vtMove = ptE - ptS ;
|
|
|
|
// Settaggio profilo
|
|
CurveComposite* pToolProfile ;
|
|
if ( m_ToolArcLineApprox.GetCurveCount() == 0)
|
|
// Se l'utensile non è stato approssimato uso l'originale
|
|
pToolProfile = &m_ToolOutline ;
|
|
else
|
|
// altrimenti usi l'approssimazione
|
|
pToolProfile = &m_ToolArcLineApprox ;
|
|
|
|
// Ciclo sulle curve
|
|
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
|
|
while ( pCurve != nullptr) {
|
|
|
|
double dHeight ;
|
|
|
|
int nCurveType = pCurve -> GetType() ;
|
|
|
|
// Caso segmento
|
|
if ( nCurveType == CRV_LINE) {
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
|
|
if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) {
|
|
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
|
|
// Il componente è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
|
|
double dRadius = ptStart.x ;
|
|
|
|
CompCyl_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
|
|
}
|
|
// Il componente è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
|
|
CompConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
// Il componente è un cono con vettore opposto a quello dell'utesile
|
|
else if ( ptStart.x < ptEnd.x) {
|
|
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
|
|
Point3d ptIn = ptI - vtToolDir * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
|
|
CompConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
}
|
|
else
|
|
dHeight = 0 ;
|
|
}
|
|
// Caso arco
|
|
else if ( nCurveType == CRV_ARC) {
|
|
|
|
// Centro e Punti iniziale e finale del cerchio
|
|
Point3d ptStart, ptEnd, ptO ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
pCurve -> GetCenterPoint( ptO) ;
|
|
|
|
// Determino il raggio
|
|
Vector3d vtStRad = ptStart - ptO ;
|
|
Vector3d vtEnRad = ptEnd - ptO ;
|
|
|
|
double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ;
|
|
|
|
// Determino le posizioni iniziale e finale del centrodella sfera
|
|
Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ;
|
|
Point3d ptOEn = ptOSt + vtMove ;
|
|
|
|
// Eseguo l'asportazione del materiale
|
|
CompBall_Milling( nGrid, ptOSt, ptOEn, dRadius) ;
|
|
|
|
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// Aggiorno il puntatore
|
|
pCurve = pToolProfile->GetNextCurve() ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Posizioni iniziale e finale dell'utensile
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
|
|
// vettore movimento
|
|
Vector3d vtMove = ptE - ptS ;
|
|
|
|
// Settaggio profilo
|
|
CurveComposite* pToolProfile ;
|
|
if ( m_ToolArcLineApprox.GetCurveCount() == 0)
|
|
// Se l'utensile non è stato approssimato uso l'originale
|
|
pToolProfile = &m_ToolOutline ;
|
|
else
|
|
// altrimenti usi l'approssimazione
|
|
pToolProfile = &m_ToolArcLineApprox ;
|
|
|
|
// Ciclo sulle curve
|
|
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
|
|
while ( pCurve != nullptr) {
|
|
|
|
double dHeight ;
|
|
|
|
int nCurveType = pCurve -> GetType() ;
|
|
|
|
// Caso segmento
|
|
if ( nCurveType == CRV_LINE) {
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
|
|
if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) {
|
|
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
|
|
// Il componente è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
|
|
double dRadius = ptStart.x ;
|
|
|
|
CompCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
|
|
}
|
|
// Il componente è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
|
|
CompConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
// Il componente è un cono con vettore opposto a quello dell'utensile
|
|
else if ( ptStart.x < ptEnd.x) {
|
|
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
|
|
Point3d ptIn = ptI - vtToolDir * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
|
|
CompConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
}
|
|
else
|
|
dHeight = 0 ;
|
|
}
|
|
// Caso arco
|
|
else if ( nCurveType == CRV_ARC) {
|
|
|
|
// Centro e Punti iniziale e finale del cerchio
|
|
Point3d ptStart, ptEnd, ptO ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
pCurve -> GetCenterPoint( ptO) ;
|
|
|
|
// Determino il raggio
|
|
Vector3d vtStRad = ptStart - ptO ;
|
|
Vector3d vtEnRad = ptEnd - ptO ;
|
|
|
|
double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ;
|
|
|
|
// Determino le posizioni iniziale e finale del centrodella sfera
|
|
Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ;
|
|
Point3d ptOEn = ptOSt + vtMove ;
|
|
|
|
// Eseguo l'asportazione del materiale
|
|
CompBall_Milling( nGrid, ptOSt, ptOEn, dRadius) ;
|
|
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// Aggiorno il puntatore
|
|
pCurve = pToolProfile->GetNextCurve() ;
|
|
}
|
|
return true ;
|
|
|
|
}
|
|
|
|
|
|
// ---------- VERSORE UTENSILE NEL PIANO XY ----------------------------------
|
|
|
|
// --------- Cilindro e sfera ------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_XYDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile e quota Z del movimento
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
double dZ = ptS.z ;
|
|
|
|
// Vettore movimento e sua lunghezza
|
|
Vector3d vtMove = ptE - ptS ; double dLen = vtMove.LenXY() ;
|
|
|
|
// Definizione di un sistema di riferimento ad hoc
|
|
Point3d ptI = ( vtMove * vtToolDir > 0 ? ptE : ptS) ;
|
|
Point3d ptF = ( vtMove * vtToolDir > 0 ? ptS - dStemHeigth * vtToolDir : ptE - dStemHeigth * vtToolDir) ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ; vtV1.Normalize() ;
|
|
Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
for( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ;
|
|
|
|
Vector3d vtBall = ptC - ptFxy ; double dSqLen = vtBall.SqLenXY() ;
|
|
|
|
// Zona lavorata dalla parte cilindrica
|
|
if ( dP1 > 0 && dP1 < dStemHeigth + dLen &&
|
|
abs( dP2) < m_dRadius ) {
|
|
|
|
double dH = sqrt( dSqRad - dP2 * dP2) ;
|
|
double dMin = dZ - dH ;
|
|
double dMax = dZ + dH ;
|
|
|
|
Vector3d vtMin = ( ptI - Point3d( dX, dY, dMin)) -
|
|
( ( ptI - Point3d( dX, dY, dMin)) * vtToolDir) * vtToolDir ;
|
|
Vector3d vtMax = ( ptI - Point3d( dX, dY, dMax)) -
|
|
( ( ptI - Point3d( dX, dY, dMax)) * vtToolDir) * vtToolDir ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
|
|
}
|
|
|
|
// Se l'utensile è sferico sottraggo anche la punta
|
|
if ( m_nToolType == BallEndMill)
|
|
if ( dSqLen < dSqRad) { // LA SOLUZIONE MOMENTANEA è CREARE UTENSILE GENERICO SE LO STELO è PIù CORTO DEL RAGGIO
|
|
|
|
double dH = sqrt( dSqRad - dSqLen) ;
|
|
double dMin = dZ - dH ;
|
|
double dMax = dZ + dH ;
|
|
|
|
Vector3d vtMin = ptF - Point3d( dX, dY, dMin) ;
|
|
Vector3d vtMax = ptF - Point3d( dX, dY, dMax) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dZ - dH, dZ + dH, vtMin, vtMax) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_XYPerp( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
|
|
// Studio simmetrie del problema
|
|
Point3d ptI = ( ptS.z <= ptE.z ? ptS : ptE) ;
|
|
Point3d ptF = ( ptS.z <= ptE.z ? ptE : ptS) ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
// Quote punti iniziale e finale
|
|
double dZI = ptI.z ;
|
|
double dZF = ptF.z ;
|
|
double dDeltaZ = ptF.z - ptI.z ;
|
|
|
|
// Vettori caratterizzanti il moto
|
|
Vector3d vtMove = ptF - ptI ;
|
|
double dLen = vtMove.Len() ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
double dLenXY = vtMoveXY.LenXY() ;
|
|
vtMove.Normalize() ;
|
|
|
|
// Sistema di riferimento ad hoc
|
|
Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ; vtV1.Normalize() ;
|
|
Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ;
|
|
if ( vtV2 * vtMove < 0)
|
|
vtV2 = - vtV2 ;
|
|
|
|
// Vettori e punti determinanti i piani
|
|
Vector3d vtP = vtMove ; // Se dLen < EPS_SMALL non si usa
|
|
vtP.Rotate( vtToolDir, 90) ;
|
|
Point3d ptUp = ptI + m_dRadius * ( vtP.z > 0 ? vtP : - vtP) ;
|
|
Point3d ptDw = ptI + m_dRadius * ( vtP.z > 0 ? - vtP : vtP) ;
|
|
|
|
Vector3d vtPXY( vtP.x, vtP.y, 0) ;
|
|
|
|
Vector3d vtUp = ptUp - ORIG ; double dDotUp = vtUp * vtP ;
|
|
Vector3d vtDw = ptDw - ORIG ; double dDotDw = vtDw * vtP ;
|
|
|
|
double dSmall = m_dRadius * vtPXY.LenXY() ;
|
|
|
|
// Parte sferica
|
|
double dCos = vtMove.z ; // vtMove.z > 0 : ptF.z >= ptI.z
|
|
double dSin = ( dCos < 1 ? sqrt( 1 - dCos * dCos) : 0) ;
|
|
double dSemiAxMin = m_dRadius * dCos ;
|
|
|
|
double dInfZ, dSupZ ;
|
|
|
|
|
|
for( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dP1 = vtC * vtV1 ;
|
|
double dP2 = vtC * vtV2 ;
|
|
|
|
// Parte cilindrica
|
|
if ( dP1 > 0 && dP1 < dStemHeigth) {
|
|
|
|
if ( dP2 > - m_dRadius && dP2 < dLenXY + m_dRadius) {
|
|
// Massimi
|
|
if ( dP2 < - dSmall + EPS_SMALL) {
|
|
double dHsq = dSqRad - dP2 * dP2 ;
|
|
double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ;
|
|
dSupZ = dZI + dH ;
|
|
}
|
|
else if ( dP2 < dLenXY - dSmall - EPS_SMALL) {
|
|
|
|
dSupZ = ( dDotUp - dX * vtP.x - dY * vtP.y) / vtP.z ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
|
|
dSupZ = dZF + dH ;
|
|
}
|
|
// Minimi
|
|
if ( dP2 < dSmall + EPS_SMALL) {
|
|
double dHsq = dSqRad - dP2 * dP2 ;
|
|
double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ;
|
|
dInfZ = dZI - dH ;
|
|
}
|
|
else if ( dP2 < dLenXY + dSmall - EPS_SMALL) {
|
|
|
|
dInfZ = ( dDotDw - dX * vtP.x - dY * vtP.y) / vtP.z ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
|
|
dInfZ = dZF - dH ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
// Se l'utensile è ball-end sottraggo la punta
|
|
if ( m_nToolType == BallEndMill) {
|
|
|
|
if ( ( ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + dP2 * dP2 < dSqRad ||
|
|
( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + ( dP2 - dLenXY) * ( dP2 - dLenXY) < dSqRad ||
|
|
( dP2 > 0 && dP2 < dLenXY && dP1 < m_dHeight)) && ( dP1 >= dStemHeigth)) {
|
|
|
|
double dSqRoot = sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth)) ;
|
|
double dP2_0 = dCos * dSqRoot ;
|
|
double dH0 = dSin * dSqRoot ;
|
|
|
|
double dMin, dMax ;
|
|
|
|
// Massimo
|
|
if ( dP2 < - dP2_0)
|
|
|
|
dMax = dZI + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
|
|
|
|
else if ( dP2 < dLenXY - dP2_0)
|
|
|
|
dMax = dZI + dH0 + dDeltaZ * ( dP2 + dP2_0) / dLenXY ;
|
|
else
|
|
dMax = dZF + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
|
|
|
|
// Minimo
|
|
if ( dP2 < dP2_0)
|
|
|
|
dMin = dZI - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
|
|
|
|
else if ( dP2 < dLenXY + dP2_0)
|
|
|
|
dMin = dZI - dH0 + dDeltaZ * ( dP2 - dP2_0) / dLenXY ;
|
|
else
|
|
dMin = dZF - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_XYMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
if ( m_nToolType == CylindricalMill)
|
|
|
|
return CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, m_dHeight, m_dRadius) ;
|
|
|
|
else if ( m_nToolType == BallEndMill) {
|
|
|
|
double dHei = m_dHeight - m_dTipHeight ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, m_dRadius) ;
|
|
|
|
CompBall_Milling( nGrid, ptS - dHei * vtToolDir, ptE - dHei * vtToolDir, m_dRadius) ;
|
|
|
|
return true ;
|
|
}
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
|
|
// --------- Coni ------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dDeltaRad = dMaxRad - dMinRad ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
|
|
// Geometria del moto
|
|
double dLenXY = ( ptE - ptS).LenXY() ;
|
|
Point3d ptI = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) ;
|
|
double dMatStemLen = ( m_dRadius > m_dTipRadius ? dStemHeigth + dLenXY : dStemHeigth) ;
|
|
double dSqTipRad = m_dTipRadius * m_dTipRadius ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
|
|
// Sistema di riferimento sul piano
|
|
Vector3d vtV1 = - vtToolDir ;
|
|
Vector3d vtV2 = vtV1 ;
|
|
vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
// Proiezione di ptI sul piano
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC ( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dX1 = vtC * vtV1 ;
|
|
double dX2 = vtC * vtV2 ;
|
|
|
|
double dr = m_dRadius + ( dX1 - dMatStemLen) * ( m_dTipRadius - m_dRadius) / m_dTipHeight ;
|
|
|
|
if ( dX1 > 0 && dX1 < dMatStemLen &&
|
|
abs( dX2) < m_dRadius) {
|
|
|
|
double dH = sqrt( dSqRad - dX2 * dX2) ;
|
|
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, V_NULL, V_NULL) ;
|
|
}
|
|
else if ( dX1 >= dMatStemLen &&
|
|
dX1 < dMatStemLen + m_dTipHeight &&
|
|
abs( dX2) < dr) {
|
|
|
|
double dH = sqrt( dr * dr - dX2 * dX2) ;
|
|
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
if ( m_dTipRadius >= m_dRadius) {
|
|
|
|
if ( dX1 >= dMatStemLen + m_dTipHeight &&
|
|
dX1 < dMatStemLen + m_dTipHeight + dLenXY &&
|
|
abs( dX2) < dSqTipRad) {
|
|
|
|
double dH = sqrt( dSqTipRad - dX2 * dX2) ;
|
|
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYPerp( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dSqTipRad = m_dTipRadius * m_dTipRadius ;
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
double dDeltaRad = dMaxRad - dMinRad ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
|
|
// Studio delle simmetrie
|
|
Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ;
|
|
Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ;
|
|
|
|
// Vettori caratterizzanti il moto
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
double dLen = vtMove.Len() ;
|
|
double dLenXY = vtMoveXY.LenXY() ;
|
|
|
|
// Quote iniziale e finale
|
|
double dZI = ptI.z ;
|
|
double dZF = ptF.z ;
|
|
|
|
// Sistema di riferimento sul piano
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
// Primo vettore del riferimento
|
|
Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ;
|
|
vtV1.Normalize() ;
|
|
Vector3d vtV2 ;
|
|
|
|
// Movimento verticale
|
|
if ( dLenXY / dLen < EPS_SMALL) {
|
|
|
|
// Secondo vettore del riferimento
|
|
vtV2 = vtV1 ;
|
|
vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dX1 = vtC * vtV1 ;
|
|
double dX2 = vtC * vtV2 ;
|
|
|
|
double dr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dX1 - dStemHeigth) / m_dTipHeight ;
|
|
// Parte cilindrica
|
|
if ( dX1 > 0 && dX1 < dStemHeigth && abs( dX2) < m_dRadius) {
|
|
|
|
double dH = sqrt( dSqRad - dX2 * dX2) ;
|
|
SubtractIntervals( nGrid, i, j, dZI - dH, dZF + dH, V_NULL, V_NULL) ;
|
|
}
|
|
// Parte conica
|
|
else if ( dX1 >= dStemHeigth && dX1 < m_dHeight && abs( dX2) < dr) {
|
|
|
|
double dH = sqrt( dr * dr - dX2 * dX2) ;
|
|
SubtractIntervals ( nGrid, i, j, dZI - dH, dZF + dH, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
// Secondo vettore del riferimento
|
|
Vector3d vtV2 = vtMoveXY ;
|
|
vtV2.Normalize() ;
|
|
|
|
// Sistema di riferimento per determinare i piani
|
|
Vector3d vtW1 = ( m_dHeight > m_dTipHeight ? vtV1 : - vtV1) ;
|
|
Vector3d vtW2 = vtMove ;
|
|
vtW2.Normalize() ;// Se vtMove non è suff ort a vtW1 vtMove = vtMoveOrt + vtMoveLong e via
|
|
Vector3d vtW3 = vtW1 ^ vtW2 ;
|
|
|
|
// Altezza cono
|
|
double dL = dMaxRad * m_dTipHeight / dDeltaRad ;
|
|
|
|
// Vertice del cono iniziale
|
|
Point3d ptV = ptI - ( m_dHeight > m_dTipHeight ? ( dStemHeigth + dL) * vtW1 : ( dL - m_dHeight) * vtW1) ;
|
|
|
|
//
|
|
double dCos = vtW2.z ;
|
|
double dSin = ( dCos < 1 ? sqrt( 1 - dCos * dCos) : 0) ;
|
|
|
|
double dLimXY = dCos * m_dRadius ;
|
|
double dLimH = dSin * m_dRadius ;
|
|
double dDeltaZ = ptF.z - ptI.z ;
|
|
|
|
double dMin, dMax ;
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dX1 = vtC * vtV1 ;
|
|
double dX2 = vtC * vtV2 ;
|
|
|
|
double dr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dX1 - dStemHeigth) / m_dTipHeight ;
|
|
|
|
// Parte cilindrica
|
|
if ( dX1 > 0 && dX1 < dStemHeigth &&
|
|
dX2 > - m_dRadius && dX2 < dLenXY + m_dRadius) {
|
|
// Massimi
|
|
if ( dX2 < - dLimXY)
|
|
dMax = dZI + sqrt( dSqRad - dX2 * dX2) ;
|
|
else if ( dX2 < dLenXY - dLimXY)
|
|
dMax = dZI + dLimH + dDeltaZ * ( dX2 + dLimXY) / dLenXY ;
|
|
else
|
|
dMax = dZF + sqrt( dSqRad - ( dX2 - dLenXY) * ( dX2 - dLenXY)) ;
|
|
|
|
// Minimi
|
|
if ( dX2 < dLimXY)
|
|
dMin = dZI + sqrt( dSqRad - dX2 * dX2) ;
|
|
else if ( dX2 < dLenXY + dLimXY)
|
|
dMin = dZI - dLimH + dDeltaZ * ( dX2 - dLimXY) / dLenXY ;
|
|
else
|
|
dMin = dZF + sqrt( dSqRad - ( dX2 - dLenXY) * ( dX2 - dLenXY)) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
// Parte conica
|
|
else if ( dX1 >= dStemHeigth && dX1 < m_dHeight &&
|
|
dX2 > - dr && dX2 < dLenXY + dr) {
|
|
|
|
double dRadLimXY = dr * dCos ;
|
|
double dRadLimH = dr * dSin ;
|
|
|
|
// Massimi
|
|
if ( dX2 < - dRadLimXY)
|
|
dMax = dZI + sqrt( dr * dr - dX2 * dX2) ;
|
|
else if ( dX2 < dLenXY - dRadLimXY)
|
|
dMax = dZI + dRadLimH + dDeltaZ * ( dX2 + dRadLimXY) / dLenXY ;
|
|
else
|
|
dMax = dZF + sqrt( dr * dr - ( dX2 - dLenXY) * ( dX2 - dLenXY)) ;
|
|
|
|
// Minimi
|
|
if ( dX2 < dRadLimXY)
|
|
dMin = dZI + sqrt( dr * dr - dX2 * dX2) ;
|
|
else if ( dX2 < dLenXY + dRadLimXY)
|
|
dMin = dZI - dRadLimH + dDeltaZ * ( dX2 - dRadLimXY) / dLenXY ;
|
|
else
|
|
dMin = dZF + sqrt( dr * dr - ( dX2 - dLenXY) * ( dX2 - dLenXY)) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) {
|
|
|
|
double dStemHeigth = m_dHeight - m_dTipRadius ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_dRadius) ;
|
|
|
|
if ( m_dTipRadius < m_dRadius) {
|
|
|
|
Point3d ptSTip = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptETip = ptE - dStemHeigth * vtToolDir ;
|
|
|
|
CompConus_Milling( nGrid, ptSTip, ptETip, vtToolDir, m_dTipHeight, m_dRadius, m_dTipRadius) ;
|
|
}
|
|
else {
|
|
|
|
Point3d ptSTip = ptS - m_dHeight * vtToolDir ;
|
|
Point3d ptETip = ptE - m_dHeight * vtToolDir ;
|
|
|
|
CompConus_Milling( nGrid, ptSTip, ptETip, - vtToolDir, m_dTipHeight, m_dTipRadius, m_dRadius) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- VERSORE UTENSILE CON ORIENTAZIONE GENERICA ---------------------
|
|
|
|
// ---------- Cilindro e sfera -----------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) {
|
|
|
|
double dStemHeigth = m_dHeight - m_dRadius ;
|
|
|
|
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_dRadius) ;
|
|
// Sfera
|
|
if ( m_nToolType == 2) {
|
|
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
|
|
CompBall_Milling( nGrid, ptSBall, ptEBall, m_dRadius) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) {
|
|
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_dRadius) ;
|
|
// Sfera
|
|
if ( m_nToolType == 2) {
|
|
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
|
|
CompBall_Milling( nGrid, ptSBall, ptEBall, m_dRadius) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Coni -----------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) {
|
|
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
|
|
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_dRadius) ;
|
|
// Trapano
|
|
if ( m_dTipRadius < m_dRadius) {
|
|
|
|
Point3d ptSCone = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptECone = ptE - dStemHeigth * vtToolDir ;
|
|
|
|
CompConus_Drilling( nGrid, ptSCone, ptECone, vtToolDir, m_dTipHeight, m_dRadius, m_dTipRadius) ;
|
|
}
|
|
else {
|
|
|
|
Point3d ptSCone = ptS - m_dHeight * vtToolDir ;
|
|
Point3d ptECone = ptE - m_dHeight * vtToolDir ;
|
|
|
|
CompConus_Drilling( nGrid, ptSCone, ptECone, - vtToolDir, m_dTipHeight, m_dTipRadius, m_dRadius) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) {
|
|
|
|
double dStemHeigth = m_dHeight - m_dTipHeight ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_dRadius) ;
|
|
// Trapano
|
|
if ( m_dTipRadius < m_dRadius) {
|
|
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
|
|
CompConus_Milling( nGrid, ptSBall, ptEBall, vtToolDir, m_dTipHeight, m_dRadius, m_dTipRadius) ;
|
|
}
|
|
else {
|
|
|
|
Point3d ptSBall = ptS - m_dHeight * vtToolDir ;
|
|
Point3d ptEBall = ptE - m_dHeight * vtToolDir ;
|
|
|
|
CompConus_Milling( nGrid, ptSBall, ptEBall, - vtToolDir, m_dTipHeight, m_dTipRadius, m_dRadius) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Utensile generico ----------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Posizioni iniziale e finale dell'utensile
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
|
|
// vettore movimento
|
|
Vector3d vtMove = ptE - ptS ;
|
|
|
|
// Settaggio profilo
|
|
CurveComposite* pToolProfile ;
|
|
if ( m_ToolArcLineApprox.GetCurveCount() == 0)
|
|
// Se l'utensile non è stato approssimato uso l'originale
|
|
pToolProfile = & m_ToolOutline ;
|
|
else
|
|
// altrimenti usi l'approssimazione
|
|
pToolProfile = &m_ToolArcLineApprox ;
|
|
|
|
// Ciclo sulle curve
|
|
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
|
|
while ( pCurve != nullptr) {
|
|
|
|
double dHeight ;
|
|
|
|
int nCurveType = pCurve -> GetType() ;
|
|
|
|
// Caso di semento
|
|
if ( nCurveType == CRV_LINE) {
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
|
|
if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) {
|
|
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
|
|
// Il componente è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
|
|
double dRadius = ptStart.x ;
|
|
|
|
// CompCyl_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
|
|
}
|
|
// Il componente è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
|
|
CompConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
// Il componente è un cono con vettore opposto a quello dell'utensile
|
|
else if ( ptStart.x < ptEnd.x) {
|
|
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
|
|
Point3d ptIn = ptI - vtToolDir * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
|
|
CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
}
|
|
else
|
|
dHeight = 0 ;
|
|
}
|
|
|
|
// Caso arco
|
|
else if ( nCurveType == CRV_ARC) {
|
|
|
|
// Centro e Punti iniziale e finale del cerchio
|
|
Point3d ptStart, ptEnd, ptO ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
pCurve -> GetCenterPoint( ptO) ;
|
|
|
|
// Determino il raggio
|
|
Vector3d vtStRad = ptStart - ptO ;
|
|
Vector3d vtEnRad = ptEnd - ptO ;
|
|
|
|
double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ;
|
|
|
|
// Determino le posizioni iniziale e finale del centrodella sfera
|
|
Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ;
|
|
Point3d ptOEn = ptOSt + vtMove ;
|
|
|
|
// Eseguo l'asportazione del materiale
|
|
CompBall_Milling( nGrid, ptOSt, ptOEn, dRadius) ;
|
|
|
|
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// Aggiorno il puntatore
|
|
pCurve = pToolProfile->GetNextCurve() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Posizioni iniziale e finale dell'utensile
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
|
|
// vettore movimento
|
|
Vector3d vtMove = ptE - ptS ;
|
|
|
|
// Settaggio profilo
|
|
CurveComposite* pToolProfile ;
|
|
if ( m_ToolArcLineApprox.GetCurveCount() == 0)
|
|
// Se l'utensile non è stato approssimato uso l'originale
|
|
pToolProfile = &m_ToolOutline ;
|
|
else
|
|
// altrimenti usi l'approssimazione
|
|
pToolProfile = &m_ToolArcLineApprox ;
|
|
|
|
// Ciclo sulle curve
|
|
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
|
|
while ( pCurve != nullptr) {
|
|
|
|
double dHeight ;
|
|
|
|
int nCurveType = pCurve -> GetType() ;
|
|
|
|
// Caso di semento
|
|
if ( nCurveType == CRV_LINE) {
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
|
|
if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) {
|
|
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
|
|
// Il componente è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
|
|
double dRadius = ptStart.x ;
|
|
|
|
CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
|
|
}
|
|
// Il componente è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
|
|
CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
// Il componente è un cono con vettore opposto a quello dell'utensile
|
|
else if ( ptStart.x < ptEnd.x) {
|
|
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
|
|
Point3d ptIn = ptI - vtToolDir * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
|
|
CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ;
|
|
}
|
|
}
|
|
else
|
|
dHeight = 0 ;
|
|
}
|
|
// Caso arco
|
|
else if ( nCurveType == CRV_ARC) {
|
|
|
|
// Centro e Punti iniziale e finale del cerchio
|
|
Point3d ptStart, ptEnd, ptO ;
|
|
|
|
pCurve -> GetStartPoint( ptStart) ;
|
|
pCurve -> GetEndPoint( ptEnd) ;
|
|
pCurve -> GetCenterPoint( ptO) ;
|
|
|
|
// Determino il raggio
|
|
Vector3d vtStRad = ptStart - ptO ;
|
|
Vector3d vtEnRad = ptEnd - ptO ;
|
|
|
|
double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ;
|
|
|
|
// Determino le posizioni iniziale e finale del centrodella sfera
|
|
Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ;
|
|
Point3d ptOEn = ptOSt + vtMove ;
|
|
|
|
// Eseguo l'asportazione del materiale
|
|
CompBall_Milling( nGrid, ptOSt, ptOEn, dRadius) ;
|
|
|
|
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// Aggiorno il puntatore
|
|
pCurve = pToolProfile->GetNextCurve() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
// ------------------------- SOLIDI ELEMENTARI -----------------------------------------------------------------------------
|
|
|
|
// Asse di simmetria diretto come l'asse Z: FORATURA
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompCyl_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dRad)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza con lo Zmap
|
|
bool bTest = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ,
|
|
dRad, dRad, dHei) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Proiezione dei punti sul piano
|
|
Point3d ptSxy( ptS.x, ptS.y, 0) ;
|
|
|
|
// Parametri geometrici dell'utensile
|
|
double dSqRad = dRad * dRad ;
|
|
|
|
// Punte del gambo
|
|
Point3d ptTStemS = ptS - vtToolDir * dHei ;
|
|
Point3d ptTStemE = ptE - vtToolDir * dHei ;
|
|
|
|
// Quote estreme del gambo
|
|
double dMinStemZ = min( min( ptS.z, ptTStemS.z), min( ptE.z, ptTStemE.z)) ;
|
|
double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptS.z, ptTStemS.z)) ;
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptSxy ;
|
|
|
|
double dSqLen = vtC.SqLen() ;
|
|
|
|
// Se il punto si trova dentro il cerchio taglio
|
|
if ( dSqLen < dSqRad)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompConus_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dMaxRad, double dMinRad)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza con lo Zmap
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
Point3d ptO( ptS.x, ptS.y, 0) ;
|
|
|
|
double dZMin, dZMax ;
|
|
double dAngC = dHei / ( dMaxRad - dMinRad) ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
|
|
// Studio delle simmetrie
|
|
if ( vtToolDir.z > 0) {
|
|
|
|
dZMin = ( ptS.z < ptE.z ? ptS.z - dHei : ptE.z - dHei) ;
|
|
dZMax = ( ptS.z < ptE.z ? ptE.z : ptS.z) ;
|
|
}
|
|
else {
|
|
|
|
dZMin = ( ptS.z < ptE.z ? ptS.z : ptE.z) ;
|
|
dZMax = ( ptS.z < ptE.z ? ptE.z + dHei : ptS.z + dHei) ;
|
|
}
|
|
|
|
// Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ;
|
|
|
|
double dSqDist = vtC * vtC ;
|
|
|
|
if ( dSqDist < dSqMinRad)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax, V_NULL, V_NULL) ;
|
|
|
|
else if ( dSqDist < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDist) ;
|
|
|
|
if ( vtToolDir.z > 0)
|
|
|
|
SubtractIntervals( nGrid, i, j, dZMin + dAngC * ( dr - dMinRad), dZMax, V_NULL, V_NULL) ;
|
|
else
|
|
SubtractIntervals( nGrid, i, j, dZMin, dZMax - dAngC * ( dr - dMinRad), V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// Asse di simmetria diretto come l'asse Z: FRESATURA
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompCyl_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dRad)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza con lo Zmap
|
|
bool bTest = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ;
|
|
|
|
if ( ! bTest)
|
|
return true ;
|
|
|
|
// Parametri geometrici
|
|
double dSqRad = dRad * dRad ;
|
|
|
|
// Studio delle simmetrie
|
|
Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ;
|
|
Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ;
|
|
Point3d ptIT = ptI - vtToolDir * dHei ;
|
|
Point3d ptFT = ptF - vtToolDir * dHei ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
// Quote iniziali e finali massime e
|
|
// minime del gambo dell'utensile e DeltaZ
|
|
double dZMaxI = max( ptI.z, ptIT.z) ;
|
|
double dZMaxF = max( ptF.z, ptFT.z) ;
|
|
double dZMinI = dZMaxI - dHei ;
|
|
double dZMinF = dZMaxF - dHei ;
|
|
double dDeltaZ = dZMaxF - dZMaxI ;
|
|
|
|
// Vettori caratterizzanti il moto
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
double dLen = vtMove.Len() ;
|
|
double dLenXY = vtMoveXY.LenXY() ;
|
|
vtMove.Normalize() ;
|
|
|
|
// Parametri per determinare l'ellisse proiettata
|
|
double dCos = vtToolDir * vtMove ;
|
|
double dSin = ( abs( dCos) < 1 ? 1 - dCos * dCos : 0) ;
|
|
double dSemiAxMin = dRad * dCos ; // x1^2 = a^2 - (a / b)^2 x2^2 ; a = r dCos e b = r;
|
|
double dSqSemiAxMin = dSemiAxMin * dSemiAxMin ; // da cui si ottiene x1^2 = a^2 - dCos^2 x2^2
|
|
double dSqRatio = dSqSemiAxMin / dSqRad ;
|
|
|
|
// Definizione di un sistema di riferimento ad hoc
|
|
Vector3d vtV1, vtV2 ;
|
|
|
|
// Se la lunghezza è troppo piccola lo allungo
|
|
if ( dLenXY < EPS_SMALL)
|
|
vtV1 = ( 1 / dLenXY) * vtMoveXY ;
|
|
else
|
|
vtV1 = vtMoveXY ;
|
|
|
|
// Normalizzo vtV1
|
|
vtV1.Normalize() ;
|
|
// Definisco vtV2
|
|
vtV2 = vtV1 ;
|
|
vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
double dMin, dMax ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dX1 = vtC * vtV1 ;
|
|
double dX2 = vtC * vtV2 ;
|
|
|
|
// Se il punto appartiene alla proiezione del volume spazzato valuto massimo e minimo
|
|
if ( ( dX1 > 0 && dX1 < dLenXY && abs( dX2) < dRad) ||
|
|
( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad ||
|
|
dX1 * dX1 + dX2 * dX2 < dSqRad) {
|
|
|
|
double dX1_0 = sqrt( dSqRad - dX2 * dX2) ;
|
|
// Massimo
|
|
if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad)
|
|
|
|
dMax = dZMaxF ;
|
|
else
|
|
dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ;
|
|
// Minimo
|
|
if ( dX1 * dX1 + dX2 * dX2 < dSqRad)
|
|
|
|
dMin = dZMinI ;
|
|
else
|
|
dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompConus_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dMaxRad, double dMinRad)
|
|
{
|
|
double dMin, dMax, dPLim, dMLim ;
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ;
|
|
Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ;
|
|
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ;
|
|
Vector3d vtMLong = ( vtMove * vtToolDir) * vtToolDir ; double dLLong = vtMLong.Len() ;
|
|
Vector3d vtMOrt = vtMove - vtMLong ; double dLOrt = vtMOrt.Len() ;
|
|
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
double dZI = ptI.z ;
|
|
double dZTI = ptI.z - vtV1.z * dHei ;
|
|
double dDeltaZ = ptF.z - ptI.z ;
|
|
double dDeltaR = dMaxRad - dMinRad ;
|
|
|
|
double dTan = dDeltaR / dHei ;
|
|
double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ;
|
|
|
|
double dCos = dTan * dRatio ;
|
|
double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ;
|
|
|
|
double dDen = sqrt( 1 + dTan * dTan) ;
|
|
|
|
Point3d ptV = ptI - vtV1 * ( dHei * dMaxRad / dDeltaR) ;
|
|
|
|
Vector3d vtNs = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ;
|
|
Vector3d vtNd = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ;
|
|
Vector3d vtR0 = ptV - ORIG ;
|
|
|
|
double dDots = vtR0 * vtNs ;
|
|
double dDotd = vtR0 * vtNd ;
|
|
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Vector3d vtCI = ptC - ptIxy ; double dSqDI = vtCI.SqLenXY() ;
|
|
Vector3d vtCF = ptC - ptFxy ; double dSqDF = vtCF.SqLenXY() ;
|
|
|
|
double dIDO = vtCI * vtV3 ;
|
|
double dIDL = vtCI * vtV2 ;
|
|
double dIVarCos = dIDL / sqrt( dSqDI) ;
|
|
|
|
double dFDL = vtCF * vtV2 ;
|
|
double dFVarCos = dFDL / sqrt( dSqDF) ;
|
|
|
|
if ( dSqDI < dMaxRad * dMaxRad || dSqDF < dMaxRad * dMaxRad ||
|
|
(abs( dIDO) < dMaxRad && dIDL > 0 && dIDL < dLOrt)) {
|
|
|
|
// Caso dTan > 1 / dRatio
|
|
if ( dRatio > 1 / dTan) {
|
|
|
|
// Limiti nella direzione positiva di vtV1
|
|
if ( dSqDF < dMaxRad * dMaxRad)
|
|
|
|
dPLim = dZI + dDeltaZ ;
|
|
|
|
else
|
|
|
|
dPLim = dZI + ( dIDL + sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
|
|
// Limiti nella direzione negativa di vtV1
|
|
if ( dSqDI < dMinRad * dMinRad)
|
|
|
|
dMLim = dZTI ;
|
|
|
|
else if ( dSqDI < dMaxRad * dMaxRad)
|
|
|
|
dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
|
|
|
|
else
|
|
|
|
dMLim = dZI + ( dIDL - sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
|
|
}
|
|
else {
|
|
|
|
// Limiti nella direzione positiva di vtV1
|
|
if ( dSqDF < dMaxRad * dMaxRad)
|
|
|
|
dPLim = dZI + dDeltaZ ;
|
|
|
|
else
|
|
|
|
dPLim = dZI + ( dIDL + sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
|
|
// Limiti nella direzione negativa di vtV1
|
|
if ( dSqDI < dMinRad * dMinRad)
|
|
|
|
dMLim = dZTI ;
|
|
|
|
else if ( dSqDI >= dMinRad * dMinRad && dSqDI < dMaxRad * dMaxRad && dIVarCos < dCos)
|
|
|
|
dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
|
|
|
|
else if ( dSqDI >= dMinRad * dMinRad && dIVarCos >= dCos && dFVarCos < dCos && abs( dIDO) < dMaxRad * dSin) { // da qui
|
|
|
|
if ( dIDO > - dMaxRad * dSin && dIDO <= - dMinRad * dSin)
|
|
|
|
dMLim = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
|
|
|
|
else if ( dIDO > - dMinRad * dSin && dIDO < dMinRad * dSin)
|
|
|
|
dMLim = dZTI + ( dIDL - sqrt( dMinRad * dMinRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
|
|
else if ( dIDO >= dMinRad * dSin && dIDO < dMaxRad * dSin)
|
|
|
|
dMLim = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; // a qui
|
|
}
|
|
else if ( dFVarCos >= dCos) {
|
|
|
|
if ( dSqDF < dMinRad * dMinRad)
|
|
|
|
dMLim = dZTI + ( dIDL - sqrt( dMinRad * dMinRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
|
|
else
|
|
|
|
dMLim = dZTI + dDeltaZ + ( sqrt( dSqDF) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
|
|
}
|
|
else
|
|
|
|
dMLim = dZI + ( dIDL - sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ;
|
|
}
|
|
|
|
dMin = min( dPLim, dMLim) ;
|
|
dMax = max( dPLim, dMLim) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
// Asse di simmetria con orientazione generica: FORATURA
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompCyl_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir,
|
|
double dHei, double dRad)
|
|
{
|
|
double dMin, dMax;
|
|
unsigned int nStartI, nEndI, nStartJ, nEndJ ;
|
|
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ,
|
|
dRad, dRad, dHei) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
// Studio delle simmetrie
|
|
Point3d ptI = ( ( ptE - ptS) * vtToolDir > 0 ? ptE : ptS) ;
|
|
Point3d ptF = ( ( ptE - ptS) * vtToolDir > 0 ? ptS - vtToolDir * dHei : ptE - vtToolDir * dHei) ;
|
|
|
|
// Sistema di riferimento cilindro
|
|
Vector3d vtV1 = - vtToolDir ;
|
|
|
|
Point3d ptP = ( abs( vtV1.z) < EPS_SMALL ? Point3d( ptI.x, ptI.y, ptI.z + 1) : Point3d( ptI.x + 1, ptI.y, ptI.z)) ;
|
|
Vector3d vtV = ( abs( vtV1.z) < EPS_SMALL ? vtToolDir : Z_AX) ;
|
|
|
|
Vector3d vtV2 = ptP - ptI + ( ( ( ptI - ptP) * vtV1) / ( vtV * vtV1)) * vtV ;
|
|
|
|
vtV2.Normalize() ;
|
|
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
Frame3d CylFrame ; CylFrame.Set( ptI, vtV1, vtV2, vtV3) ;
|
|
|
|
// Lunghezzza cilindro totale altezza + moto
|
|
double dLen = ( ptF - ptI).Len() ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Point3d ptInt1, ptInt2 ;
|
|
|
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLen, dRad, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompConus_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE,
|
|
const Vector3d & vtToolDir, double dHei, double dMaxRad, double dMinRad)
|
|
{
|
|
double dMin, dMax ;
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
// Apertura del cono
|
|
double dDeltaR = dMaxRad - dMinRad ;
|
|
double dTan = dDeltaR / dHei ;
|
|
double dL = ( ( dMaxRad * dHei) / dDeltaR) ;
|
|
double dl = dL - dHei ;
|
|
|
|
Point3d ptVertex = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) - vtToolDir * dL ;
|
|
|
|
// Sistema di riferimento del cono
|
|
Vector3d vtV1 = vtToolDir ;
|
|
|
|
Point3d ptP = ( abs( vtV1.z) < EPS_SMALL ? Point3d( ptVertex.x, ptVertex.y, ptVertex.z + 1) : Point3d( ptVertex.x + 1, ptVertex.y, ptVertex.z)) ;
|
|
|
|
Vector3d vtV = ( abs( vtV1.z) < EPS_SMALL ? vtToolDir : Z_AX) ;
|
|
|
|
Vector3d vtV2 = ptP - ptVertex + ( ( ( ptVertex - ptP) * vtV1) / ( vtV * vtV1)) * vtV ;
|
|
|
|
vtV2.Normalize() ;
|
|
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
Frame3d ConusFrame ; ConusFrame.Set( ptVertex, vtV1, vtV2, vtV3) ;
|
|
|
|
// Lunghezzza cilindro totale altezza + moto
|
|
double dLen = ( ptE - ptS).Len() ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Point3d ptInt1, ptInt2 ;
|
|
|
|
// Cilindro
|
|
if ( IntersLineCylinder( ptC - vtV1 * dL, Z_AX, ConusFrame, dLen, dMaxRad, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
dMax = max( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Cono
|
|
if ( IntersLineConus( ptC , Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// Asse di simmetria con orientazione generica: FRESATURA
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompCyl_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|
const Vector3d& vtToolDir, double dHei, double dRad)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir,
|
|
nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ;
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
|
|
// Studio delle simmetrie
|
|
Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ;
|
|
Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ;
|
|
|
|
|
|
Point3d ptITip = ptI - vtToolDir * dHei ;
|
|
Point3d ptFTip = ptF - vtToolDir * dHei ;
|
|
|
|
|
|
// Definizione terne vettoriali e sistemi di riferimento intrinseci al movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveLong = ( vtMove * vtToolDir) * vtToolDir ;
|
|
Vector3d vtMoveOrt = vtMove - vtMoveLong ;
|
|
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
|
|
Frame3d CylFrame ; CylFrame.Set( ptITip, vtV1, vtV2, vtV3) ;
|
|
|
|
|
|
// Parametri geometrici di moto e cilindro
|
|
double dSqRad = dRad * dRad ;
|
|
double dLongLen = vtMoveLong.Len() ;
|
|
double dOrtLen = vtMoveOrt.Len() ;
|
|
|
|
// Minima e massima quota z
|
|
double dMin, dMax ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
|
|
|
|
Point3d ptInt1, ptInt2 ;
|
|
|
|
// Cilindro iniziale
|
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Cilindro finale
|
|
if ( IntersLineCylinder( ptC - vtMove, Z_AX, CylFrame, dHei, dRad, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtMove.z, ptInt2.z + vtMove.z) ;
|
|
dMax = max( ptInt1.z + vtMove.z, ptInt2.z + vtMove.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
|
|
// Poliedro interno
|
|
if ( IntersLineMyPolyhedron( ptC, Z_AX, CylFrame, dHei, dOrtLen, 2 * dRad, dLongLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Cilindro ellittico di punta
|
|
if ( IntersLineEllipticalCylinder( Z_AX, ptC, CylFrame, dSqRad,
|
|
dLongLen, dOrtLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Cilindro ellittico di base: L'unica differenza rispetto a prima è l'origine
|
|
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
|
|
// il vettore che congiunge le due origini.
|
|
if ( IntersLineEllipticalCylinder( Z_AX, ptC - dHei * vtV1, CylFrame, dSqRad,
|
|
dLongLen, dOrtLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + dHei * vtV1.z, ptInt2.z + dHei * vtV1.z) ;
|
|
dMax = max( ptInt1.z + dHei * vtV1.z, ptInt2.z + dHei * vtV1.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompConus_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir,
|
|
double dHei, double dMaxRad, double dMinRad)
|
|
{
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
bool Control = BBoxComponent( nGrid, ptS, ptE, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ,
|
|
dMaxRad, dMinRad, dHei) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
// Geometria del cono
|
|
double dDeltaR = dMaxRad - dMinRad ;
|
|
double dSqMaxRad = dMaxRad * dMaxRad ;
|
|
double dSqMinRad = dMinRad * dMinRad ;
|
|
|
|
// Studio simmetrie
|
|
Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ;
|
|
Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * dHei ;
|
|
Point3d ptFT = ptF - vtToolDir * dHei ;
|
|
|
|
double dL = ( ( dMaxRad * dHei) / ( dDeltaR)) ;
|
|
double dl = dL - dHei ;
|
|
|
|
Point3d ptV = ptI - vtToolDir * dL ;
|
|
|
|
// Vettori caratteristici del movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMvLong = ( vtMove * vtToolDir) * vtToolDir ;
|
|
Vector3d vtMvOrt = vtMove - vtMvLong ;
|
|
|
|
// Terna destrorsa e unitaria
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMvOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Sistema di riferimento intrinseco del movimento
|
|
Frame3d ConusFrame ; ConusFrame.Set( ptV, vtV1, vtV2, vtV3) ;
|
|
|
|
// Dimensioni lineari movimento
|
|
double dLongLen = vtMvLong.Len() ;
|
|
double dOrtLen = vtMvOrt.Len() ;
|
|
|
|
// Apertura del cono
|
|
double dTan = dDeltaR / dHei ;
|
|
double dRatio = dLongLen / dOrtLen ;
|
|
|
|
// Per costruire piani laterali poliedro interno
|
|
double dCos = dTan * dRatio ;
|
|
double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ;
|
|
double dDen = sqrt( 1 + dTan * dTan) ;
|
|
|
|
// Dimensioni lineari descriventi il poliedro interno
|
|
double dLenX = dLongLen ;
|
|
double dLenY = dOrtLen ;
|
|
double dLenZ = dSin * dMinRad ;
|
|
double dDeltaX = dHei ;
|
|
double dDeltaY = dCos * dDeltaR ;
|
|
double dDeltaZ = dSin * dDeltaR ;
|
|
|
|
// Sistema di riferimento poliedro
|
|
Point3d ptO = ptV + vtV1 * dl + vtV2 * ( dCos * dMinRad) ;
|
|
|
|
Frame3d PolyFrame ; PolyFrame.Set( ptO, vtV1, vtV2, vtV3) ;
|
|
|
|
// Versori piani nel riferimento poliedro
|
|
// (Sx, Dx, Iniziale, Finale, Up, Down sono riferiti
|
|
// al sistema di riferimento):
|
|
|
|
// Sx, Dx
|
|
Vector3d vtNs( - ( dTan / dDen), ( dCos / dDen), ( dSin / dDen)) ;
|
|
Vector3d vtNd( - ( dTan / dDen), ( dCos / dDen), - ( dSin / dDen)) ;
|
|
|
|
// Iniziale e finale
|
|
Vector3d vtIF( - dDeltaY, dDeltaX, 0) ;
|
|
|
|
// Up e Down
|
|
Vector3d vtUD( - dLenY, dLenX, 0) ;
|
|
|
|
// Punti dei piani (sempre espressi nel sistema PolyFrame)
|
|
Point3d ptFacet135( 0, 0, dLenZ) ;
|
|
Point3d ptFacet246( dLenX + dDeltaX, dLenY + dDeltaY, - dLenZ - dDeltaZ) ;
|
|
|
|
double dSqIndet = EPS_SMALL * EPS_SMALL ;
|
|
|
|
double dMin, dMax ;
|
|
|
|
if ( dRatio * dTan <= 1) {
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Point3d ptInt1, ptInt2 ;
|
|
|
|
// Cono iniziale
|
|
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Cono finale
|
|
if ( IntersLineConus( ptC - vtMove, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtMove.z, ptInt2.z + vtMove.z) ;
|
|
dMax = max( ptInt1.z + vtMove.z, ptInt2.z + vtMove.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Solido interno
|
|
Point3d ptPoly = ptC ;
|
|
Vector3d vtPoly = Z_AX ;
|
|
|
|
ptPoly.ToLoc( PolyFrame) ;
|
|
vtPoly.ToLoc( PolyFrame) ;
|
|
|
|
Point3d ptPoly1 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtNs) / ( vtPoly * vtNs)) * vtPoly ;
|
|
Point3d ptPoly2 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtNd) / ( vtPoly * vtNd)) * vtPoly ;
|
|
Point3d ptPoly3 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ;
|
|
Point3d ptPoly4 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ;
|
|
Point3d ptPoly5 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ;
|
|
Point3d ptPoly6 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ;
|
|
|
|
int nIntNum = 0 ;
|
|
|
|
// Intersezione con la prima faccia
|
|
if ( dLenY * ptPoly1.x >= dLenX * ptPoly1.y &&
|
|
dLenY * ( ptPoly1.x - dDeltaX) <= dLenX * ptPoly1.y &&
|
|
dDeltaX * ptPoly1.y >= dDeltaY * ptPoly1.x &&
|
|
dDeltaX * ( ptPoly1.y - dLenY) <= dDeltaY * ( ptPoly1.x - dLenX)) {
|
|
|
|
ptInt1 = ptPoly1 ;
|
|
++ nIntNum ;
|
|
}
|
|
// Intersezione con la seconda faccia
|
|
if ( dLenY * ptPoly2.x >= dLenX * ptPoly2.y &&
|
|
dLenY * ( ptPoly2.x - dDeltaX) <= dLenX * ptPoly2.y &&
|
|
dDeltaX * ptPoly2.y >= dDeltaY * ptPoly2.x &&
|
|
dDeltaX * ( ptPoly2.y - dLenY) <= dDeltaY * ( ptPoly2.x - dLenX)) {
|
|
|
|
if ( nIntNum == 0) {
|
|
|
|
ptInt1 = ptPoly2 ;
|
|
++ nIntNum ;
|
|
}
|
|
else if ( ( ptInt1 - ptPoly2).SqLen() > dSqIndet) {
|
|
|
|
ptInt2 = ptPoly2 ;
|
|
++ nIntNum ;
|
|
}
|
|
}
|
|
// Intersezione con la terza faccia
|
|
if ( nIntNum < 2 &&
|
|
ptPoly3.x >= 0 && ptPoly3.x <= dDeltaX &&
|
|
dDeltaX * abs( ptPoly3.z) < dDeltaX * dLenZ + dDeltaZ * ptPoly3.x) {
|
|
|
|
if ( nIntNum == 0) {
|
|
|
|
ptInt1 = ptPoly3 ;
|
|
++ nIntNum ;
|
|
}
|
|
else if ( ( ptInt1 - ptPoly3).SqLen() > dSqIndet) {
|
|
|
|
ptInt2 = ptPoly3 ;
|
|
++ nIntNum ;
|
|
}
|
|
}
|
|
|
|
// Intersezione con la quarta faccia
|
|
if ( nIntNum < 2 &&
|
|
ptPoly4.x >= dLenX && ptPoly4.x <= dLenX + dDeltaX &&
|
|
dDeltaX * abs( ptPoly4.z) < dDeltaX * dLenZ + dDeltaZ * ( ptPoly4.x - dLenX)) {
|
|
|
|
if ( nIntNum == 0) {
|
|
|
|
ptInt1 = ptPoly4 ;
|
|
++ nIntNum ;
|
|
}
|
|
else if ( ( ptInt1 - ptPoly4).SqLen() > dSqIndet) {
|
|
|
|
ptInt2 = ptPoly4 ;
|
|
++ nIntNum ;
|
|
}
|
|
}
|
|
|
|
// Intersezione con la quinta faccia
|
|
if ( nIntNum < 2 &&
|
|
ptPoly5.y >= 0 && ptPoly5.y <= dLenY &&
|
|
abs( ptPoly5.z) <= dLenZ) {
|
|
|
|
if ( nIntNum == 0) {
|
|
|
|
ptInt1 = ptPoly5 ;
|
|
++ nIntNum ;
|
|
}
|
|
else if ( ( ptInt1 - ptPoly5).SqLen() > dSqIndet) {
|
|
|
|
ptInt2 = ptPoly5 ;
|
|
++ nIntNum ;
|
|
}
|
|
}
|
|
|
|
// Intersezione con la sesta faccia
|
|
if ( nIntNum < 2 &&
|
|
ptPoly6.y >= dDeltaY && ptPoly6.y <= dLenY + dDeltaY &&
|
|
abs( ptPoly6.z) <= dLenZ + dDeltaZ) {
|
|
|
|
if ( nIntNum == 0) {
|
|
|
|
ptInt1 = ptPoly6;
|
|
++ nIntNum ;
|
|
}
|
|
else if ( ( ptInt1 - ptPoly6).SqLen() > dSqIndet) {
|
|
|
|
ptInt2 = ptPoly6;
|
|
++ nIntNum ;
|
|
}
|
|
}
|
|
// Se il poliedro è attraversato taglio
|
|
if ( nIntNum == 2) {
|
|
|
|
// Riporto le intersezioni nel sistema griglia
|
|
ptInt1.ToGlob( PolyFrame) ;
|
|
ptInt2.ToGlob( PolyFrame) ;
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Traslazione ellisse di punta
|
|
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dl, ConusFrame, dSqMinRad,
|
|
dLongLen, dOrtLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtV1.z * dl, ptInt2.z + vtV1.z * dl) ;
|
|
dMax = max( ptInt1.z + vtV1.z * dl, ptInt2.z + vtV1.z * dl) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Traslazione ellisse di base
|
|
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dSqMaxRad,
|
|
dLongLen, dOrtLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
dMax = max( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
else {
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Point3d ptInt1, ptInt2 ;
|
|
|
|
// Cono
|
|
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z, ptInt2.z) ;
|
|
dMax = max( ptInt1.z, ptInt2.z) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
|
|
// Traslazione ellisse
|
|
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dSqMaxRad,
|
|
dLongLen, dOrtLen, ptInt1, ptInt2)) {
|
|
|
|
dMin = min( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
dMax = max( ptInt1.z + vtV1.z * dL, ptInt2.z + vtV1.z * dL) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
// ---------- SFERA ----------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompBall_Milling( unsigned int nGrid, const Point3d & ptLs, const Point3d & ptLe, double dRad)
|
|
{
|
|
double dMin, dMax ;
|
|
unsigned int nStartI, nStartJ, nEndI, nEndJ ;
|
|
|
|
bool Control = BBoxComponent( nGrid, ptLs, ptLe, V_NULL, V_NULL, nStartI, nStartJ, nEndI, nEndJ, dRad, 0, 0) ;
|
|
|
|
if ( ! Control)
|
|
return true ;
|
|
|
|
Point3d ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
Point3d ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ;
|
|
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
|
|
double dVLen = abs( vtMove.z) ; // Verticale e planare rispetto ai dexel
|
|
double dPLen = vtMoveXY.LenXY() ;
|
|
double dLen = vtMove.Len() ;
|
|
|
|
double dR1 = dVLen / dLen ;
|
|
double dR2 = dPLen / dLen ;
|
|
|
|
double dZI = ptI.z ;
|
|
double dDeltaZ = ptF.z - ptI.z ;
|
|
double dSqRad = dRad * dRad ;
|
|
|
|
|
|
if ( dPLen < EPS_SMALL) {
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dSqLen = vtC.SqLen() ;
|
|
|
|
if ( dSqLen < dSqRad) {
|
|
|
|
double dH = sqrt( dSqRad - dSqLen) ;
|
|
|
|
dMin = dZI - dH ;
|
|
dMax = dZI + dDeltaZ + dH ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
Vector3d vtV1 = vtMoveXY ; vtV1.Normalize() ;
|
|
Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtCI = ptC - ptIxy ; Vector3d vtCF = ptC - ptFxy ;
|
|
|
|
double dX1 = vtCI * vtV1 ; double dX2 = vtCI * vtV2 ;
|
|
|
|
double dISqDist = vtCI * vtCI ; double dFSqDist = vtCF * vtCF ;
|
|
|
|
if ( dISqDist < dSqRad || dFSqDist < dSqRad ||
|
|
( dX1 > 0 && dX1 < dPLen && dX2 * dX2 < dSqRad)) {
|
|
|
|
// Massimi
|
|
if ( dX1 < - dR1 * sqrt( dSqRad - ( dX2 * dX2)))
|
|
|
|
dMax = dZI + sqrt( dSqRad - dISqDist) ;
|
|
|
|
else if ( dX1 < dPLen - dR1 * sqrt( dSqRad - ( dX2 * dX2)))
|
|
|
|
dMax = dZI + dR2 * sqrt( dSqRad - dX2 * dX2) + ( dX1 + dR1 * sqrt( dSqRad - ( dX2 * dX2))) * dVLen / dPLen ;
|
|
|
|
else
|
|
|
|
dMax = dZI + dDeltaZ + sqrt( dSqRad - dFSqDist) ;
|
|
|
|
// Minimi
|
|
if ( dX1 < dR1 * sqrt( dSqRad - ( dX2 * dX2)))
|
|
|
|
dMin = dZI - sqrt( dSqRad - dISqDist) ;
|
|
|
|
else if ( dX1 < dPLen + dR1 * sqrt( dSqRad - ( dX2 * dX2)))
|
|
|
|
dMin = dZI - dR2 * sqrt( dSqRad - dX2 * dX2) + ( dX1 - dR1 * sqrt( dSqRad - ( dX2 * dX2))) * dVLen / dPLen ;
|
|
|
|
else
|
|
|
|
dMin = dZI + dDeltaZ - sqrt( dSqRad - dFSqDist) ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, V_NULL, V_NULL) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::BoundingBox( unsigned int nGrid, const Point3d & ptP1, const Point3d & ptP2, const Vector3d & vtV1, const Vector3d & vtV2,
|
|
unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ)
|
|
{
|
|
// NB: E' vitale che vengano passati i punti e i vettori nel sistema di riferimento
|
|
// di riferimento opportuno.
|
|
|
|
// Controllo sull'ammissibilità del numero di griglia
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
unsigned int nMaxNx, nMaxNy ;
|
|
|
|
double dMaxXValue, dMaxYValue ;
|
|
double dMinZValue, dMaxZValue ;
|
|
|
|
nMaxNx = m_nNx[nGrid] ; nMaxNy = m_nNy[nGrid] ;
|
|
|
|
dMaxXValue = nMaxNx * m_dStep ; dMaxYValue = nMaxNy * m_dStep ;
|
|
|
|
dMinZValue = m_dMinZ[nGrid] ; dMaxZValue = m_dMaxZ[nGrid] ;
|
|
|
|
|
|
// Determinazione del raggio massimo dell'utensile
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale
|
|
Point3d ptP1T = ptP1 - m_dHeight * vtV1 ;
|
|
Point3d ptP2T = ptP2 - m_dHeight * vtV2 ;
|
|
|
|
// Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento
|
|
double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad ;
|
|
double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad ;
|
|
double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad ;
|
|
double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad ;
|
|
double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad ;
|
|
double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad ;
|
|
|
|
// Verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > dMaxXValue - EPS_SMALL)
|
|
return false ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > dMaxYValue - EPS_SMALL)
|
|
return false ;
|
|
if ( dMaxZ < dMinZValue + EPS_SMALL || dMinZ > dMaxZValue - EPS_SMALL)
|
|
return false ;
|
|
|
|
// Limiti su indici
|
|
nStI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::BBoxComponent( unsigned int nGrid, const Point3d & ptP1, const Point3d & ptP2, const Vector3d & vtV1, const Vector3d & vtV2,
|
|
unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ,
|
|
double dRad, double dTipRad, double dHei)
|
|
{
|
|
// NB: E' vitale che vengano passati i punti e i vettori nel sistema di riferimento
|
|
// di riferimento opportuno.
|
|
|
|
// Controllo sull'ammissibilità del numero di griglia
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
unsigned int nMaxNx, nMaxNy ;
|
|
|
|
double dMaxXValue, dMaxYValue ;
|
|
double dMinZValue, dMaxZValue ;
|
|
|
|
nMaxNx = m_nNx[nGrid] ; nMaxNy = m_nNy[nGrid] ;
|
|
|
|
dMaxXValue = nMaxNx * m_dStep ; dMaxYValue = nMaxNy * m_dStep ;
|
|
|
|
dMinZValue = m_dMinZ[nGrid] ; dMaxZValue = m_dMaxZ[nGrid] ;
|
|
|
|
// Determinazione del raggio massimo del componente
|
|
double dMaxRad = max( dRad, dTipRad) ;
|
|
|
|
// Determinazione delle posizioni della punta del componente nelle posizioni iniziale e finale
|
|
Point3d ptP1T = ptP1 - dHei * vtV1 ;
|
|
Point3d ptP2T = ptP2 - dHei * vtV2 ;
|
|
|
|
// Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento
|
|
double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad;
|
|
double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad;
|
|
double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad;
|
|
double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad;
|
|
double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad;
|
|
double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad;
|
|
|
|
// Verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > dMaxXValue - EPS_SMALL)
|
|
return false ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > dMaxYValue - EPS_SMALL)
|
|
return false ;
|
|
if ( dMaxZ < dMinZValue + EPS_SMALL || dMinZ > dMaxZValue - EPS_SMALL)
|
|
return false ;
|
|
|
|
// Limiti su indici
|
|
nStI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
return true ;
|
|
}
|