Files
EgtGeomKernel/VolTriZmapVolume.cpp
T
Dario Sassi 76d94d6194 EgtGeomKernel 1.8g1 :
- modifiche a Zmap
- aggiunto clamp a ratio di font
- migliorata ricerca nomi con *.
2017-08-01 07:59:56 +00:00

4931 lines
170 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 < m_Values[nGrid][nPos].size()) {
// Casi:
// Intervallo da sottrarre è tutto a sinistra di quello corrente, non vi è intersezione
if ( m_Values[nGrid][nPos][i].dMin > dMax - EPS_SMALL) {
;
}
// Intersezione
else if ( m_Values[nGrid][nPos][i].dMax > dMax + EPS_SMALL) {
// L'intervallo corrente viene limitato a sinistra
if ( m_Values[nGrid][nPos][i].dMin > dMin - EPS_SMALL) {
bModified = true ;
// Aggiornamento dati del tratto di dexel
m_Values[nGrid][nPos][i].dMin = dMax ;
m_Values[nGrid][nPos][i].vtMinN = vtNma ;
m_Values[nGrid][nPos][i].nToolMin = m_nCurrentToolNum ;
}
// L'intervallo si divide in due intervalli
else {
bModified = true ;
// Aumento la dimensione del dexel
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 1) ;
size_t nStartT = max( 0, int( m_Values[nGrid][nPos].size()) - 1) ;
// Sposto i tratti successivi a quello corrente in avanti di una posizione
for ( size_t j = nStartT ; j >= i + 2 ; -- j) {
// Quote estreme
m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j - 1].dMax ;
m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j - 1].dMin ;
// Normali
m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j - 1].vtMaxN ;
m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j - 1].vtMinN ;
// Numero utensile
m_Values[nGrid][nPos][j].nToolMax = m_Values[nGrid][nPos][j - 1].nToolMax ;
m_Values[nGrid][nPos][j].nToolMin = m_Values[nGrid][nPos][j - 1].nToolMin ;
// Indice di componente
m_Values[nGrid][nPos][j].nCompo = m_Values[nGrid][nPos][j - 1].nCompo ;
}
// Divido in due il tratto corrente
// Parte superiore
m_Values[nGrid][nPos][i + 1].dMax = m_Values[nGrid][nPos][i].dMax ;
m_Values[nGrid][nPos][i + 1].vtMaxN = m_Values[nGrid][nPos][i].vtMaxN ;
m_Values[nGrid][nPos][i + 1].nToolMax = m_Values[nGrid][nPos][i].nToolMax ;
m_Values[nGrid][nPos][i + 1].dMin = dMax ;
m_Values[nGrid][nPos][i + 1].vtMinN = vtNma ;
m_Values[nGrid][nPos][i + 1].nToolMin = m_nCurrentToolNum ;
m_Values[nGrid][nPos][i + 1].nCompo = m_Values[nGrid][nPos][i].nCompo ;
// Parte inferiore
m_Values[nGrid][nPos][i].dMax = dMin ;
m_Values[nGrid][nPos][i].vtMaxN = vtNmi ;
m_Values[nGrid][nPos][i].nToolMax = m_nCurrentToolNum ;
i = i + 1 ;
}
}
else {
// L'intervallo corrente viene eliminato
if ( m_Values[nGrid][nPos][i].dMin > dMin - EPS_SMALL) {
bModified = true ;
// Sposto i tratti successivi a quello corrente indietro di una posizione
for ( unsigned int j = i ; j < m_Values[nGrid][nPos].size() - 1 ; ++ j) {
m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j + 1].dMin ;
m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j + 1].dMax ;
m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j + 1].vtMinN ;
m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j + 1].vtMaxN ;
m_Values[nGrid][nPos][j].nToolMin = m_Values[nGrid][nPos][j + 1].nToolMin ;
m_Values[nGrid][nPos][j].nToolMax = m_Values[nGrid][nPos][j + 1].nToolMax ;
m_Values[nGrid][nPos][j].nCompo = m_Values[nGrid][nPos][j + 1].nCompo ;
}
// Riduco la dimensione del dexel
m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 1) ;
i = i - 1 ;
}
// L'intervallo corrente viene limitato a destra
else if ( m_Values[nGrid][nPos][i].dMax > dMin + EPS_SMALL) {
bModified = true ;
m_Values[nGrid][nPos][i].dMax = dMin ;
m_Values[nGrid][nPos][i].vtMaxN = vtNmi ;
m_Values[nGrid][nPos][i].nToolMax = m_nCurrentToolNum ;
}
// L'intervallo da sottrarre è tutto a destra di quello corrente, non vi è intersezione
else {
;
}
}
i = i + 1 ;
}
// Se eseguita modifica, imposto ricalcolo della grafica
if ( bModified) {
// Dichiaro numero di componenti connesse da ricalcolare
m_nConnectedCompoCount = - 1 ;
// Determino quali blocchi sono stati modificati
int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ;
if ( nGrid == 0) {
/*INTVECTOR nXBlock ;
INTVECTOR nYBlock ;
nXBlock.emplace_back( min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1)) ;
nYBlock.emplace_back( min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1)) ;
if ( nI % N_DEXBLOCK == 0 && nXBlock[0] > 0)
nXBlock.emplace_back( nXBlock[0] - 1) ;
if ( nJ % N_DEXBLOCK == 0 && nYBlock[0] > 0)
nYBlock.emplace_back( nYBlock[0] - 1) ;*/
int nXStop = 1 ;
int nYStop = 1 ;
int nXBlock[2] ;
int nYBlock[2] ;
nXBlock[0] = min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
nYBlock[0] = min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
if ( nI % N_DEXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
if ( nJ % N_DEXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / m_dStep - EPS_SMALL))), 0, m_nNy[1] - 1) ;
int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / m_dStep + EPS_SMALL))), 0, m_nNy[1] - 1) ;
int nMinZBlock = ( m_nMapNum == 1 ? 0 : max( 0, nMinK / int( m_nDexNumPBlock))) ;
int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nDexNumPBlock)) ;
for ( int tI = 0 ; tI < nXStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) {
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) {
int nBlockNum = k * nLayerBlock + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 1) {
/*INTVECTOR nYBlock ;
INTVECTOR nZBlock ;
nYBlock.emplace_back( min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1)) ;
nZBlock.emplace_back( min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1)) ;
if ( nI % N_DEXBLOCK == 0 && nYBlock[0] > 0)
nYBlock.emplace_back( nYBlock[0] - 1) ;
if ( nJ % N_DEXBLOCK == 0 && nZBlock[0] > 0)
nZBlock.emplace_back( nZBlock[0] - 1) ;*/
int nYStop = 1 ;
int nZStop = 1 ;
int nYBlock[2] ;
int nZBlock[2] ;
nYBlock[0] = min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1) ;
nZBlock[0] = min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
if ( nI % N_DEXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
if ( nJ % N_DEXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / m_dStep - EPS_SMALL))), 0, m_nNx[0] - 1) ;
int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / m_dStep + EPS_SMALL))), 0, m_nNx[0] - 1) ;
int nMinXBlock = max( 0, nMinI / int( m_nDexNumPBlock)) ;
int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nDexNumPBlock)) ;
for ( int tI = 0 ; tI < nYStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) {
for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) {
int nBlockNum = nZBlock[tJ] * nLayerBlock + nYBlock[tI] * m_nFracLin[0] + k ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 2) {
/*INTVECTOR nXBlock ;
INTVECTOR nZBlock ;
nXBlock.emplace_back( min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1)) ;
nZBlock.emplace_back( min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1)) ;
if ( nJ % N_DEXBLOCK == 0 && nXBlock[0] > 0)
nXBlock.emplace_back( nXBlock[0] - 1) ;
if ( nI % N_DEXBLOCK == 0 && nZBlock[0] > 0)
nZBlock.emplace_back( nZBlock[0] - 1) ;*/
int nXStop = 1 ;
int nZStop = 1 ;
int nXBlock[2] ;
int nZBlock[2] ;
nXBlock[0] = min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1) ;
nZBlock[0] = min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1) ;
if ( nJ % N_DEXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
if ( nI % N_DEXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / m_dStep - EPS_SMALL))), 0, m_nNy[0] - 1) ;
int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / m_dStep + EPS_SMALL))), 0, m_nNy[0] - 1) ;
int nMinYBlock = max( 0, nMinJ / int( m_nDexNumPBlock)) ;
int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nDexNumPBlock)) ;
for ( int tI = 0 ; tI < nZStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) {
for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) {
int nBlockNum = nZBlock[tI] * nLayerBlock + k * m_nFracLin[0] + nXBlock[tJ] ;
m_BlockToUpdate[nBlockNum] = 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( 1) ;
//
// m_Values[nGrid][nPos][0].dMin = dMin ;
// m_Values[nGrid][nPos][0].dMax = dMax ;
//
// m_Values[nGrid][nPos][0].vtMinN = vtNmi ;
// m_Values[nGrid][nPos][0].vtMaxN = 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 < m_Values[nGrid][nPos].size()) {
//
// // Eventuale aggiustamento di intervalli sovrapposti
// if ( i < m_Values[nGrid][nPos].size() - 1) {
// if ( m_Values[nGrid][nPos][i].dMax > m_Values[nGrid][nPos][i + 1].dMin - EPS_SMALL) {
//
// // Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva
// if ( m_Values[nGrid][nPos][i].dMin < m_Values[nGrid][nPos][i + 1].dMin + EPS_SMALL) {
//
// m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i + 1].dMax ;
// m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i + 1].vtMaxN ;
// }
// // altrimenti
// else {
//
// m_Values[nGrid][nPos][i].dMin = m_Values[nGrid][nPos][i].dMin ;
// m_Values[nGrid][nPos][i].vtMinN = m_Values[nGrid][nPos][i].vtMinN ;
//
// m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i].dMax ;
// m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i].vtMaxN ;
// }
//
// for ( unsigned int j = i + 1 ; j < m_Values[nGrid][nPos].size() - 1 ; ++ j) {
//
// m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j + 1].dMin ;
// m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j + 1].vtMinN ;
//
// m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j + 1].dMax ;
// m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j + 1].vtMaxN ;
// }
//
// m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 1) ;
//
// i = i - 1 ;
// }
// }
//
//
// // 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 - 2 * m_dRadius * EPS_SMALL)
// utensile cilindrico
if ( m_nToolType == CylindricalMill)
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ;
// 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) ;
vtNorm.Normalize() ;
SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, vtNorm, - vtToolDir) ;
}
else {
Vector3d vtNorm = Point3d( ptSxy.x, ptSxy.y, dMinStemZ) - Point3d( dX, dY, dMinStemZ + dH) ;
vtNorm.Normalize() ;
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 ;
double dSafeRad = m_dRadius - EPS_SMALL ;
double dSafeSqRad = dSafeRad * dSafeRad ;
// Punte del gambo
Point3d ptTStemS = ptS - vtToolDir * dStemHeigth ;
Point3d ptTStemE = ptE - vtToolDir * dStemHeigth ;
// Quote estreme del gambo
double dMinStemZ = min( ptS.z, ptTStemS.z) ;
double dMaxStemZ = 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 < dSafeSqRad) ||
( ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2) < dSafeSqRad ||
( dP1 > 0 && dP1 < dLen && abs( dP2) < dSafeRad))
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ;
}
// Utensile sferico
else if ( m_nToolType == BallEndMill) {
if ( abs( dP2) < dSafeRad) {
if ( dP1 < 0) {
if ( dP1 * dP1 + dP2 * dP2 < dSafeSqRad) {
double dH = sqrt( dSafeSqRad - dP1 * dP1 - dP2 * dP2) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, ptTStemS.z - dH) ;
Vector3d vtN = ptTStemS - ptInt ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptTStemS.z - dH, ptS.z, vtN, - Z_AX) ;
}
else {
Point3d ptInt( dX, dY, ptTStemS.z + dH) ;
Vector3d vtN = ptTStemS - ptInt ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptS.z, ptTStemS.z + dH, Z_AX, vtN) ;
}
}
}
else if ( dP1 < dLen) {
double dH = sqrt( dSafeSqRad - dP2 * dP2) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, ptTStemS.z - dH) ;
Vector3d vtN = - ( ptInt - ptTStemS) + ( ptInt - ptTStemS) * vtV1 * vtV1 ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptTStemS.z - dH, ptS.z, vtN, - Z_AX) ;
}
else {
Point3d ptInt( dX, dY, ptTStemS.z + dH) ;
Vector3d vtN = - ( ptInt - ptTStemS) + ( ptInt - ptTStemS) * vtV1 * vtV1 ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptS.z, ptTStemS.z + dH, Z_AX, vtN) ;
}
}
else {
if ( ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2 < dSafeSqRad) {
double dH = sqrt( dSafeSqRad - ( dP1 - dLen) * ( dP1 - dLen) - dP2 * dP2) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, ptTStemE.z - dH) ;
Vector3d vtN = ptTStemE - ptInt ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptTStemE.z - dH, ptS.z, vtN, - Z_AX) ;
}
else {
Point3d ptInt( dX, dY, ptTStemE.z + dH) ;
Vector3d vtN = ptTStemE - ptInt ;
vtN.Normalize() ;
SubtractIntervals( nGrid, i, j, ptS.z, ptTStemE.z + dH, Z_AX, vtN) ;
}
}
}
}
}
}
}
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 dSafeRadius = m_dRadius - EPS_SMALL ;
double dSqRad = m_dRadius * m_dRadius ;
double dSafeSqRad = dSqRad - 2 * m_dRadius * EPS_SMALL ;
// 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) ;
Point3d ptIUp( ptI.x, ptI.y, max( ptI.z, ptIT.z)) ;
Point3d ptIDw( ptI.x, ptI.y, min( ptI.z, ptIT.z)) ;
// 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) ;
//Frame3d frNewFrame ; frNewFrame.Set( ptIT, vtMove) ;
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) < dSafeRadius) ||
( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSafeSqRad ||
dX1 * dX1 + dX2 * dX2 < dSafeSqRad) {
double dX1_0 = sqrt( dSqRad - dX2 * dX2) ;
Vector3d vtNmin, vtNmax ;
// Massimo
if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad) {
vtNmax = - Z_AX ;
dMax = dZMaxF ;
}
else {
//vtNmax = - ( dX2 / dX1_0) * vtMove ^ vtV1 - vtMove ^ vtV2 ;
dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ;
Vector3d vtCirc = dX1_0 * vtV1 - dX2 * vtV2 ; // Punta verso il centro
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; // Tangente alla circonferenza
Vector3d vtCross = vtTan ^ vtMove ;
vtNmax = ( vtCross * vtCirc > - EPS_ZERO ? vtCross : - vtCross) ;
vtNmax.Normalize() ;
}
// Minimo
if ( dX1 * dX1 + dX2 * dX2 < dSqRad) {
vtNmin = Z_AX ;
dMin = dZMinI ;
}
else {
//vtNmin = - ( dX2 / dX1_0) * vtMove ^ vtV1 + vtMove ^ vtV2 ;
dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
Vector3d vtCirc = - dX1_0 * vtV1 - dX2 * vtV2 ; // Punta verso il centro
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; // Tangente alla circonferenza
Vector3d vtCross = vtTan ^ vtMove ;
vtNmin = ( vtCross * vtCirc > - EPS_ZERO ? vtCross : - vtCross) ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
if ( m_nToolType == 2)
CompBall_Milling( nGrid, ptIT, ptFT, m_dRadius) ;
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)) ;
// Parametri geometrici per
// determinare il vettore normale
double dL = m_dTipHeight * dMaxRad / dDeltaRad ;
// 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, Z_AX, - Z_AX) ;
else if ( dSqDist < dSqMaxRad) {
double dr = sqrt( dSqDist) ;
double dl = dr * dMaxRad / dL ;
if ( vtToolDir.z > 0) {
double dMin = dZMin + m_dTipHeight * ( dr - dMinRad) / dDeltaRad ;
double dMax = dZMax ;
Point3d ptInt( dX, dY, dMin) ;
Point3d ptPn( ptO.x, ptO.y, dMin + dl) ;
Vector3d vtNmin = ptPn - ptInt ;
vtNmin.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, - Z_AX) ;
}
else {
double dMin = dZMin ;
double dMax = dZMax - m_dTipHeight * ( dr - dMinRad) / dDeltaRad ;
Point3d ptInt( dX, dY, dMax) ;
Point3d ptPn( ptO.x, ptO.y, dMax - dl) ;
Vector3d vtNmax = ptPn - ptInt ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, vtNmax) ;
}
}
}
}
}
// 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, Z_AX, - Z_AX) ;
}
else if ( dSqDist < dSqMaxRad) {
double dr = sqrt( dSqDist) ;
double dl = dr * dMaxRad / dL ;
if ( vtToolDir.z > 0) {
double dMin = dZMin ;
double dMax = dZMax - dStemHeigth - m_dTipHeight * ( dr - dMinRad) / dDeltaRad ;
Point3d ptInt( dX, dY, dMax) ;
Point3d ptPn( ptO.x, ptO.y, dMax - dl) ;
Vector3d vtNmax = ptPn - ptInt ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, vtNmax) ;
}
else {
double dMin = dZMin + dStemHeigth + m_dTipHeight * ( dr - dMinRad) / dDeltaRad ;
double dMax = dZMax ;
Point3d ptInt( dX, dY, dMin) ;
Point3d ptPn( ptO.x, ptO.y, dMin + dl) ;
Vector3d vtNmin = ptPn - ptInt ;
vtNmin.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, - Z_AX) ;
}
}
}
}
}
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 ;
double dSafeMinRad = dMinRad - EPS_SMALL ;
double dSafeMaxRad = dMaxRad - EPS_SMALL ;
double dSafeSqMaxRad = dSafeMaxRad * dSafeMaxRad ;
double dSafeSqMinRad = dSafeMinRad * dSafeMinRad ;
Point3d ptSxy( ptS.x, ptS.y, 0) ;
Point3d ptExy( ptE.x, ptE.y, 0) ;
Vector3d vtV1( ptE.x - ptS.x, ptE.y - ptS.y, 0) ;
Vector3d vtV2( - vtV1.y, vtV1.x, 0) ;
double dLen = vtV1.LenXY() ;
vtV1.Normalize() ;
vtV2.Normalize() ;
double dBaseZ = ptS.z ;
double dStemZ = ptS.z - vtToolDir.z * dStemHeigth ;
double dTipZ = ptS.z - vtToolDir.z * m_dHeight ;
// Lunghezza cono
double dL = m_dTipHeight * dMaxRad / dDeltaRad ;
// Punta a trapano
if ( m_dTipRadius < m_dRadius) {
double dMin, dMax ;
Vector3d vtV = vtToolDir ;
Point3d ptVS = ptS - vtToolDir * ( dStemHeigth + dL) ;
Point3d ptVE = ptE - vtToolDir * ( dStemHeigth + dL) ;
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 vtCS = ptC - ptSxy ;
Vector3d vtCE = ptC - ptExy ;
double dP1 = vtCS * vtV1 ;
double dP2 = vtCS * vtV2 ;
double dSqLenS = vtCS.SqLenXY() ;
double dSqLenE = vtCE.SqLenXY() ;
if ( dSqLenS < dSafeSqMaxRad || dSqLenE < dSafeSqMaxRad ||
( abs( dP2) < dSafeMaxRad && dP1 >= 0 && dP1 <= dLen)) {
if ( dSqLenS < dSqMinRad || dSqLenE < dSqMinRad ||
( abs( dP2) < dMinRad && dP1 >= 0 && dP1 <= dLen)) {
dMin = min( dBaseZ, dTipZ) ;
dMax = max( dBaseZ, dTipZ) ;
SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, - Z_AX) ;
}
else {
Vector3d vtNmin, vtNmax ;
if ( dP1 < 0) {
double dr = sqrt( dSqLenS) ;
dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
vtNmax = - Z_AX ;
}
else {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else if ( dP1 <= dLen) {
double dr = abs( dP2) ;
dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
Point3d ptVtemp = ptVS + vtV1 * dP1 ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
vtNmax = - Z_AX ;
}
else {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else {
double dr = sqrt( dSqLenE) ;
dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
vtNmax = -Z_AX ;
}
else {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
}
}
// Coda di rondine
else {
double dMin, dMax ;
Vector3d vtV = - vtToolDir ;
Point3d ptVS = ptS - vtToolDir * ( m_dHeight - dL) ;
Point3d ptVE = ptE - vtToolDir * ( m_dHeight - dL) ;
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 vtCS = ptC - ptSxy ;
Vector3d vtCE = ptC - ptExy ;
double dP1 = vtCS * vtV1 ;
double dP2 = vtCS * vtV2 ;
double dSqLenS = vtCS.SqLenXY() ;
double dSqLenE = vtCE.SqLenXY() ;
if ( dSqLenS < dSqMaxRad || dSqLenE < dSqMaxRad ||
( abs( dP2) < dMaxRad && dP1 >= 0 && dP1 <= dLen)) {
if ( dSqLenS < dSafeSqMinRad || dSqLenE < dSafeSqMinRad ||
( abs( dP2) < dSafeMinRad && dP1 >= 0 && dP1 <= dLen)) {
dMin = min( dBaseZ, dTipZ) ;
dMax = max( dBaseZ, dTipZ) ;
SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, - Z_AX) ;
}
else {
Vector3d vtNmin, vtNmax ;
if ( dP1 < 0) {
double dr = sqrt( dSqLenS) ;
dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
else {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ;
vtU.Normalize() ;
vtNmax = -Z_AX ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else if ( dP1 <= dLen) {
double dr = abs( dP2) ;
Point3d ptVtemp = ptVS + vtV1 * dP1 ;
dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
else {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ;
vtU.Normalize() ;
vtNmax = -Z_AX ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else {
double dr = sqrt( dSqLenE) ;
dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
if ( vtToolDir.z > 0) {
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = Z_AX ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
else {
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ;
vtU.Normalize() ;
vtNmax = -Z_AX ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
double dStemH = m_dHeight - m_dTipHeight ;
CompCyl_ZMilling( nGrid, ptS, ptE, vtToolDir, dStemH, m_dRadius) ;
if ( m_dTipRadius < m_dRadius) {
Point3d ptSC = ptS - vtToolDir * dStemH ;
Point3d ptEC = ptE - vtToolDir * dStemH ;
CompConus_ZMilling( nGrid, ptSC, ptEC, vtToolDir, m_dTipHeight, m_dRadius, m_dTipRadius) ;
}
else {
Point3d ptSC = ptS - vtToolDir * m_dHeight ;
Point3d ptEC = ptE - vtToolDir * m_dHeight ;
CompConus_ZMilling( nGrid, ptSC, ptEC, - vtToolDir, m_dTipHeight, m_dTipRadius, m_dRadius) ;
}
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 > EPS_SMALL && dP1 < dStemHeigth + dLen - EPS_SMALL &&
abs( dP2) < m_dRadius ) {
double dH = sqrt( dSqRad - dP2 * dP2) ;
double dMin = dZ - dH ;
double dMax = dZ + dH ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtMin = ( ptI - ptIntMin) -
( ptI - ptIntMin) * vtToolDir * vtToolDir ;
Vector3d vtMax = ( ptI - ptIntMax) -
( ptI - ptIntMax) * vtToolDir * vtToolDir ;
vtMin.Normalize() ;
vtMax.Normalize() ;
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) ;
vtMin.Normalize() ;
vtMax.Normalize() ;
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 ;
double dSafeSqRad = dSqRad - 2 * m_dRadius * EPS_SMALL ;
// 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) ;
Point3d ptIStemT = ptI - vtToolDir * dStemHeigth ;
Point3d ptFStemT = ptF - vtToolDir * dStemHeigth ;
// 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 ;
if ( dLenXY < 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 dP1 = vtC * vtV1 ;
double dP2 = vtC * vtV2 ;
Vector3d vtNmin, vtNmax ;
if ( dP1 > EPS_SMALL && dP1 < dStemHeigth - EPS_SMALL &&
dP2 > - m_dRadius + EPS_SMALL &&
dP2 < m_dRadius - EPS_SMALL) {
dInfZ = ptI.z - sqrt( dSqRad - dP2 * dP2) ;
dSupZ = ptF.z + sqrt( dSqRad - dP2 * dP2) ;
Point3d ptIntInf( dX, dY, dInfZ) ;
Point3d ptIntSup( dX, dY, dSupZ) ;
vtNmin = - ( ptIntInf - ptI) + ( ptIntInf - ptI) * vtV1 * vtV1 ;
vtNmax = - ( ptIntSup - ptF) + ( ptIntSup - ptF) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ;
}
if ( m_nToolType == BallEndMill) {
if ( dP1 > dStemHeigth - 2 * EPS_SMALL && ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + dP2 * dP2 < dSafeSqRad) {
dInfZ = ptI.z - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
dSupZ = ptF.z + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
Point3d ptIntInf( dX, dY, dInfZ) ;
Point3d ptIntSup( dX, dY, dSupZ) ;
vtNmin = ptIStemT - ptIntInf ;
vtNmax = ptFStemT - ptIntSup ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ;
}
}
}
}
}
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) ;
Vector3d vtC = ptC - ptIxy ;
double dP1 = vtC * vtV1 ;
double dP2 = vtC * vtV2 ;
// Parte cilindrica
if ( dP1 > EPS_SMALL && dP1 < dStemHeigth - EPS_SMALL) {
if ( dP2 > - m_dRadius && dP2 < dLenXY + m_dRadius) {
Vector3d vtNmin, vtNmax ;
// Massimi
if ( dP2 < - dSmall + EPS_SMALL) {
double dHsq = dSqRad - dP2 * dP2 ;
double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ;
dSupZ = dZI + dH ;
Point3d ptInt( dX, dY, dSupZ) ;
vtNmax = - ( ptInt - ptI - ( ptInt - ptI) * vtToolDir * vtToolDir) ;
vtNmax.Normalize() ;
}
else if ( dP2 < dLenXY - dSmall - EPS_SMALL) {
dSupZ = ( dDotUp - dX * vtP.x - dY * vtP.y) / vtP.z ;
Vector3d vtT = vtToolDir ^ vtMove ;
vtNmax = ( vtT.z < 0 ? vtT : - vtT) ;
vtNmax.Normalize() ;
}
else {
double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
dSupZ = dZF + dH ;
Point3d ptInt( dX, dY, dSupZ) ;
vtNmax = - ( ptInt - ptF - ( ptInt - ptF) * vtToolDir * vtToolDir) ;
vtNmax.Normalize() ;
}
// Minimi
if ( dP2 < dSmall + EPS_SMALL) {
double dHsq = dSqRad - dP2 * dP2 ;
double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ;
dInfZ = dZI - dH ;
Point3d ptInt( dX, dY, dInfZ) ;
vtNmin = - ( ( ptInt - ptI) - ( ptInt - ptI) * vtToolDir * vtToolDir) ;
vtNmin.Normalize() ;
}
else if ( dP2 < dLenXY + dSmall - EPS_SMALL) {
dInfZ = ( dDotDw - dX * vtP.x - dY * vtP.y) / vtP.z ;
Vector3d vtT = vtToolDir ^ vtMove ;
vtNmin = ( vtT.z < 0 ? - vtT : vtT) ;
vtNmin.Normalize() ;
}
else {
double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
dInfZ = dZF - dH ;
Point3d ptInt( dX, dY, dInfZ) ;
vtNmin = - ( ( ptInt - ptF) - ( ptInt - ptF) * vtToolDir * vtToolDir) ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ;
}
}
// 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 - 2 * EPS_SMALL)) {
double dSqRoot = sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth)) ;
double dP2_0 = dCos * dSqRoot ;
double dH0 = dSin * dSqRoot ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
// Massimo
if ( dP2 < - dP2_0) {
dMax = dZI + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
Point3d ptInt( dX, dY, dMax) ;
vtNmax = ptIStemT - ptInt ;
vtNmax.Normalize() ;
}
else if ( dP2 < dLenXY - dP2_0) {
dMax = dZI + dH0 + dDeltaZ * ( dP2 + dP2_0) / dLenXY ;
Point3d ptInt( dX, dY, dMax) ;
vtNmax = - ( ptInt - ptIStemT) + ( ptInt - ptIStemT) * vtMove * vtMove ;
vtNmax.Normalize() ;
}
else {
dMax = dZF + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
Point3d ptInt( dX, dY, dMax) ;
vtNmax = ptFStemT - ptInt;
vtNmax.Normalize() ;
}
// Minimo
if ( dP2 < dP2_0) {
dMin = dZI - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ;
Point3d ptInt( dX, dY, dMin) ;
vtNmin = ptIStemT - ptInt ;
vtNmin.Normalize() ;
}
else if ( dP2 < dLenXY + dP2_0) {
dMin = dZI - dH0 + dDeltaZ * ( dP2 - dP2_0) / dLenXY ;
Point3d ptInt( dX, dY, dMin) ;
vtNmin = - ( ptInt - ptIStemT) + ( ptInt - ptIStemT) * vtMove * vtMove ;
vtNmin.Normalize() ;
}
else {
dMin = dZF - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ;
Point3d ptInt( dX, dY, dMin) ;
vtNmin = ptFStemT - ptInt ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
}
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, false, false) ;
else if ( m_nToolType == BallEndMill) {
double dHei = m_dHeight - m_dTipHeight ;
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, m_dRadius, false, false) ;
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 ;
// Determinazione del vertice del cono
double dL = m_dTipHeight * dMaxRad / dDeltaRad ;
Point3d ptV ; // Vertice
Vector3d vtV ; // Vettore riferimento con origine nel vertice
if ( m_dRadius > m_dTipRadius) {
vtV = vtToolDir ;
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * ( dStemHeigth + dL) ;//dStemHeigth ;
}
else {
vtV = - vtToolDir ;
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) - vtToolDir * ( m_dHeight - dL) ;//dStemHeigth ;
}
// 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 > EPS_SMALL && dX1 < dMatStemLen &&
abs( dX2) < m_dRadius) {
double dH = sqrt( dSqRad - dX2 * dX2) ;
double dMin = ptI.z - dH ;
double dMax = ptI.z + dH ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ;
Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ;
}
else if ( dX1 >= dMatStemLen &&
dX1 < dMatStemLen + m_dTipHeight - EPS_SMALL &&
abs( dX2) < dr) {
double dH = sqrt( dr * dr - dX2 * dX2) ;
double dMin = ptI.z - dH ;
double dMax = ptI.z + dH ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtUmin = ( ptIntMin - ptV) - ( ptIntMin - ptV) * vtV * vtV ;
Vector3d vtUmax = ( ptIntMax - ptV) - ( ptIntMax - ptV) * vtV * vtV ;
Vector3d vtNmin = dDeltaRad * vtV - m_dTipHeight * vtUmin ;
Vector3d vtNmax = dDeltaRad * vtV - m_dTipHeight * vtUmax ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
if ( m_dTipRadius >= m_dRadius) {
if ( dX1 > dMatStemLen + m_dTipHeight - 2 * EPS_SMALL &&
dX1 < dMatStemLen + m_dTipHeight + dLenXY - EPS_SMALL &&
abs( dX2) < dSqTipRad) {
double dH = sqrt( dSqTipRad - dX2 * dX2) ;
double dMin = ptI.z - dH ;
double dMax = ptI.z + dH ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ;
Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ;
}
}
}
}
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 del moto
Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ;
Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ;
Point3d ptIxy( ptI.x, ptI.y, 0) ;
Point3d ptFxy( ptF.x, ptF.y, 0) ;
// Cinematica del moto
Vector3d vtMove = ptF - ptI ;
double dLenPath = vtMove.Len() ;
double dLengthPathXY = vtMove.LenXY() ;
double dDeltaZ = ptF.z - ptI.z ;
double dZI = ptI.z ;
double dZF = ptF.z ;
vtMove.Normalize() ;
// Riferimento coni
double dL = m_dTipHeight * dMaxRad / dDeltaRad ;
Vector3d vtV = ( m_dRadius > m_dTipRadius ? vtToolDir : - vtToolDir) ;
Point3d ptVI = ptI - ( m_dRadius > m_dTipRadius ? dStemHeigth + dL : m_dHeight - dL) * vtToolDir ;
Point3d ptVF = ptF - ( m_dRadius > m_dTipRadius ? dStemHeigth + dL : m_dHeight - dL) * vtToolDir ;
// Movimento verticale
if ( dLengthPathXY < EPS_SMALL) {
// Riferimento sul piano
Vector3d vtV1 = - vtToolDir ;
Vector3d vtV2( - vtV1.y, vtV1.x, 0) ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
Point3d ptIntMin, ptIntMax ;
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 > EPS_SMALL && dP1 <= dStemHeigth &&
dP2 > - m_dRadius + EPS_SMALL && dP2 < m_dRadius - EPS_SMALL) {
dMin = dZI - sqrt( dSqRad - dP2 * dP2) ;
dMax = dZF + sqrt( dSqRad - dP2 * dP2) ;
ptIntMin.Set( dX, dY, dMin) ;
ptIntMax.Set( dX, dY, dMax) ;
vtNmin = - ( ptIntMin - ptI) + ( ptIntMin - ptI) * vtV1 * vtV1 ;
vtNmax = - ( ptIntMax - ptF) + ( ptIntMax - ptF) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Parte conica
else if ( dP1 > dStemHeigth && dP1 < m_dHeight - EPS_SMALL && abs( dP2) < m_dRadius +
( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight - EPS_SMALL) {
double dr = dP2 ;
double dMr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight ;
dMin = dZI - sqrt( dMr * dMr - dr * dr) ;
dMax = dZF + sqrt( dMr * dMr - dr * dr) ;
ptIntMin.Set( dX, dY, dMin) ;
ptIntMax.Set( dX, dY, dMax) ;
Vector3d vtUmin = ( ptIntMin - ptVI) - ( ptIntMin - ptVI) * vtV * vtV ;
Vector3d vtUmax = ( ptIntMax - ptVF) - ( ptIntMax - ptVF) * vtV * vtV ;
vtUmin.Normalize() ;
vtUmax.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtUmin ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtUmax ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
else {
// Riferimento sul piano
Vector3d vtV1 = - vtToolDir ;
Vector3d vtV2( vtMove.x, vtMove.y, 0) ;
vtV2.Normalize() ;
// Vettore per individuare i punti di tangenza
// dei piani con il cilindro
Vector3d vtCross = vtToolDir ^ vtMove ;
if ( vtCross.z < 0) vtCross = - vtCross ;
// Punti di tangenza
Point3d ptUp = ptI - vtToolDir * dStemHeigth + m_dRadius * vtCross ;
Point3d ptDw = ptI - vtToolDir * dStemHeigth - m_dRadius * vtCross ;
double dSmallLength = m_dRadius * vtCross.LenXY() ;
// Punti di tangenza in corrispondenza della punta
Point3d ptTipUp = ptI - vtToolDir * m_dHeight + m_dTipRadius * vtCross ;
Point3d ptTipDw = ptI - vtToolDir * m_dHeight - m_dTipRadius * vtCross ;
Vector3d vtUpTan = ptTipUp - ptUp ;
Vector3d vtDwTan = ptTipDw - ptDw ;
Vector3d vtUpTanXY( vtUpTan.x, vtUpTan.y, 0) ;
double dDeltaSmallAbs = abs( vtUpTanXY * vtV2) ;
double dDeltaSmall = ( m_dRadius > m_dTipRadius ? dDeltaSmallAbs : - dDeltaSmallAbs) ;
vtUpTan.Normalize() ;
vtDwTan.Normalize() ;
Vector3d vtUpCross = vtMove ^ vtUpTan ;
Vector3d vtDwCross = - vtMove ^ vtDwTan ;
if ( vtUpCross.z > 0)
vtUpCross = - vtUpCross ;
if ( vtDwCross.z < 0)
vtDwCross = - vtDwCross ;
// Descrizione piani tangenti al cono
Vector3d vtR0Up = ptUp - ORIG ;
Vector3d vtR0Dw = ptDw - ORIG ;
double dDotUp = vtR0Up * vtUpCross ;
double dDotDw = vtR0Dw * vtDwCross ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
Point3d ptInt ;
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 > EPS_SMALL && dP1 <= dStemHeigth && // vedere se conviene dP1 < dStemHeigth + eps oppure dP1 <= dStemHeigth
dP2 > - m_dRadius && dP2 < dLengthPathXY + m_dRadius) {
// Massimi
if ( dP2 < - dSmallLength) {
dMax = dZI + sqrt( dSqRad - dP2 * dP2) ;
ptInt.Set( dX, dY, dMax) ;
vtNmax = - ( ptInt - ptI) + ( ptInt - ptI) * vtV1 * vtV1 ;
vtNmax.Normalize() ;
}
else if ( dP2 < dLengthPathXY - dSmallLength) {
dMax = ptUp.z + dDeltaZ * ( dP2 + dSmallLength) / dLengthPathXY ;
vtNmax = - vtCross ;
}
else {
dMax = dZF + sqrt( dSqRad - ( dP2 - dLengthPathXY) * ( dP2 - dLengthPathXY)) ;
ptInt.Set( dX, dY, dMax) ;
vtNmax = - ( ptInt - ptF) + ( ptInt - ptF) * vtV1 * vtV1 ;
vtNmax.Normalize() ;
}
// Minimi
if ( dP2 < dSmallLength) {
dMin = dZI - sqrt( dSqRad - dP2 * dP2) ;
ptInt.Set( dX, dY, dMin) ;
vtNmin = - ( ptInt - ptI) + ( ptInt - ptI) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
}
else if ( dP2 < dLengthPathXY + dSmallLength) {
dMin = ptDw.z + dDeltaZ * ( dP2 - dSmallLength) / dLengthPathXY ;
vtNmin = vtCross ;
}
else {
dMin = dZF - sqrt( dSqRad - ( dP2 - dLengthPathXY) * ( dP2 - dLengthPathXY)) ;
ptInt.Set( dX, dY, dMin) ;
vtNmin = - ( ptInt - ptF) + ( ptInt - ptF) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Parte conica
else if ( dP1 > dStemHeigth && dP1 < m_dHeight - EPS_SMALL &&
dP2 > - m_dRadius - ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight &&
dP2 < m_dRadius + dLengthPathXY +
( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight) {
// Massimi
if ( dP2 < - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_dTipHeight) {
double dr = dP2 ;
double dMr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight ;
dMax = dZI + sqrt( dMr * dMr - dr * dr) ;
ptInt.Set( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVI) - ( ptInt - ptVI) * vtV * vtV ;
vtU.Normalize() ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
else if ( dP2 < dLengthPathXY - dSmallLength +
dDeltaSmall * ( dP1 - dStemHeigth) / m_dTipHeight) {
dMax = ( dDotUp - dX * vtUpCross.x - dY * vtUpCross.y) / vtUpCross.z ;
vtNmax = vtUpCross ;
}
else {
double dr = dP2 - dLengthPathXY ;
double dMr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight ;
dMax = dZF + sqrt( dMr * dMr - dr * dr) ;
ptInt.Set( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtV * vtV ;
vtU.Normalize() ;
vtNmax = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmax.Normalize() ;
}
// Minimi
if ( dP2 < dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_dTipHeight) {
double dr = dP2 ;
double dMr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight ;
dMin = dZI - sqrt( dMr * dMr - dr * dr) ;
ptInt.Set( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVI) - ( ptInt - ptVI) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
}
else if ( dP2 < dLengthPathXY + dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_dTipHeight) {
dMin = ( dDotDw - dX * vtDwCross.x - dY * vtDwCross.y) / vtDwCross.z ;
vtNmin = vtDwCross ;
}
else {
double dr = dP2 - dLengthPathXY ;
double dMr = m_dRadius + ( m_dTipRadius - m_dRadius) * ( dP1 - dStemHeigth) / m_dTipHeight ;
dMin = dZF - sqrt( dMr * dMr - dr * dr) ;
ptInt.Set( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtV * vtV ;
vtU.Normalize() ;
vtNmin = dDeltaRad * vtV - m_dTipHeight * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_XYMilling( 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, false, true) ;
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, true, false) ;
}
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, false, true) ;
}
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, false, false) ;
// 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, false, false) ;
// 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, false, true) ;
// 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, true, false) ;
}
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, false, true) ;
}
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, false, true) ;
// 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, true, false) ;
}
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, false, true) ;
}
return true ;
}
// ---------- Utensile generico ----------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::GenTool_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
// Descrizione geometrica del moto
Point3d ptI = ptS ;
Point3d ptF = ptE ;
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 uso l'approssimazione
pToolProfile = &m_ToolArcLineApprox ;
// Ciclo sulle curve
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
const ICurve* pFirstConst = pCurve ;
while ( pCurve != nullptr) {
double dHeight ;
int nCurveType = pCurve -> GetType() ;
// Caso di 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) ;
bool bTapB, bTapT ;
pCurve = pToolProfile -> GetPrevCurve() ;
// Dettagli curva precedente
int nPrevType = pCurve -> GetType() ;
Point3d ptPrevFirst, ptPrevLast ;
pCurve -> GetStartPoint( ptPrevFirst) ;
pCurve -> GetEndPoint( ptPrevLast) ;
double dAbsDYPr = abs( ptPrevFirst.y - ptPrevLast.y) ;
double dDeltaXPr = ptPrevFirst.x - ptPrevLast.x ;
// Setto le variabili per il tappo superiore
if ( pCurve == pFirstConst ||
nPrevType == CRV_ARC ||
( dDeltaXPr < 0 && dAbsDYPr))
bTapB = false ;
else
bTapB = true ;
// Dettagli curva successiva
pCurve = pToolProfile -> GetNextCurve() ;
pCurve = pToolProfile -> GetNextCurve() ;
int nNextType = pCurve -> GetType() ;
Point3d ptNextFirst ;
Point3d ptNextLast ;
pCurve -> GetStartPoint( ptNextFirst) ;
pCurve -> GetEndPoint( ptNextLast) ;
double dAbsDYNx = abs( ptNextFirst.y - ptNextLast.y) ;
double dDeltaXNx = ptNextFirst.x - ptNextLast.x ;
double dAbsXEnd = abs( ptNextLast.x) ;
if ( pCurve == nullptr ||
nNextType == CRV_ARC ||
( dAbsDYNx < EPS_SMALL && ( dDeltaXNx > 0 || dAbsXEnd < EPS_SMALL)))
bTapT = false ;
else
bTapT = true ;
// Il componente è un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
CompCyl_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ;
}
// 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, bTapB, bTapT) ;
}
// 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, bTapT, bTapB) ;
}
}
else {
dHeight = 0 ;
pCurve = pToolProfile -> GetNextCurve() ;
}
}
// 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 centro della 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) ;
pCurve = pToolProfile -> GetNextCurve() ;
}
// 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)
{
// Descrizione geometrica del moto
Point3d ptI = ptS ;
Point3d ptF = ptE ;
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 uso l'approssimazione
pToolProfile = &m_ToolArcLineApprox ;
// Ciclo sulle curve
const ICurve* pCurve = pToolProfile->GetFirstCurve() ;
const ICurve* pFirstConst = pCurve ;
while ( pCurve != nullptr) {
double dHeight ;
int nCurveType = pCurve -> GetType() ;
// Caso di 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) ;
bool bTapB, bTapT ;
pCurve = pToolProfile -> GetPrevCurve() ;
// Dettagli curva precedente
int nPrevType = pCurve -> GetType() ;
Point3d ptPrevFirst, ptPrevLast ;
pCurve -> GetStartPoint( ptPrevFirst) ;
pCurve -> GetEndPoint( ptPrevLast) ;
double dAbsDYPr = abs( ptPrevFirst.y - ptPrevLast.y) ;
double dDeltaXPr = ptPrevFirst.x - ptPrevLast.x ;
// Setto le variabili per il tappo superiore
if ( pCurve == pFirstConst ||
nPrevType == CRV_ARC ||
( dDeltaXPr < 0 && dAbsDYPr))
bTapB = false ;
else
bTapB = true ;
// Dettagli curva successiva
pCurve = pToolProfile -> GetNextCurve() ;
pCurve = pToolProfile -> GetNextCurve() ;
int nNextType = pCurve -> GetType() ;
Point3d ptNextFirst ;
Point3d ptNextLast ;
pCurve -> GetStartPoint( ptNextFirst) ;
pCurve -> GetEndPoint( ptNextLast) ;
double dAbsDYNx = abs( ptNextFirst.y - ptNextLast.y) ;
double dDeltaXNx = ptNextFirst.x - ptNextLast.x ;
double dAbsXEnd = abs( ptNextLast.x) ;
if ( pCurve == nullptr ||
nNextType == CRV_ARC ||
( dAbsDYNx < EPS_SMALL && ( dDeltaXNx > 0 || dAbsXEnd < EPS_SMALL)))
bTapT = false ;
else
bTapT = true ;
// Il componente è un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ;
}
// 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, bTapB, bTapT) ;
}
// 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, bTapT, bTapB) ;
}
}
else {
dHeight = 0 ;
pCurve = pToolProfile -> GetNextCurve() ;
}
}
// 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 centro della 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) ;
pCurve = pToolProfile -> GetNextCurve() ;
}
// 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 ;
double dSqfeSqRad = dSqRad - 2 * dRad * EPS_SMALL ;
// 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 < dSqfeSqRad)
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ;
}
}
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 ;
double dDeltaR = dMaxRad - dMinRad ;
// 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) ;
}
double dL = dMaxRad * dAngC ;
Point3d ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * dL ;
double dMin, dMax ;
Vector3d vtMin, vtMax ;
// 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, Z_AX, -Z_AX) ;
else if ( dSqDist < dSqMaxRad) {
double dr = sqrt( dSqDist) ;
if ( vtToolDir.z > 0) {
dMin = dZMin + dAngC * ( dr - dMinRad) ;
dMax = dZMax ;
vtMax = - Z_AX ;
Point3d ptInt( dX, dY, dMin) ;
Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ;
vtU.Normalize() ;
vtMin = dDeltaR * vtToolDir - dHei * vtU ;
vtMin.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
else {
dMin = dZMin ;
dMax = dZMax - dAngC * ( dr - dMinRad) ;
vtMin = Z_AX ;
Point3d ptInt( dX, dY, dMax) ;
Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ;
vtU.Normalize() ;
vtMax = dDeltaR * vtToolDir - dHei * vtU ;
vtMax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
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) ;
Point3d ptIUp( ptI.x, ptI.y, max( ptI.z, ptIT.z)) ;
Point3d ptIDw( ptI.x, ptI.y, min( ptI.z, ptIT.z)) ;
// 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 ;
double dSafeRad = dRad - EPS_SMALL ;
// 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 ;
Vector3d vtMin, vtMax ;
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 ;
Point3d ptInt ;
// Se il punto appartiene alla proiezione del volume spazzato valuto massimo e minimo
if ( ( dX1 > 0 && dX1 < dLenXY && abs( dX2) < dSafeRad) ||
( 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 ;
vtMax = - Z_AX ;
}
else {
dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ;
if ( abs( vtMove * vtToolDir) < EPS_SMALL) {
vtMax = - Z_AX ;
}
else {
Vector3d vtCirc = dX1_0 * vtV1 - dX2 * vtV2 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtMove ;
vtMax = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ;
vtMax.Normalize() ;
}
}
// Minimo
if ( dX1 * dX1 + dX2 * dX2 < dSqRad) {
dMin = dZMinI ;
vtMin = Z_AX ;
}
else {
dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ;
if ( abs( vtMove * vtToolDir) < EPS_SMALL) {
vtMin = Z_AX ;
}
else {
Vector3d vtCirc = - dX1_0 * vtV1 - dX2 * vtV2 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtMove ;
vtMin = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ;
vtMin.Normalize() ;
}
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_ZMilling( 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 ;
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 ;
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) ;
bool bCase = ( dRatio * dTan > 1 ? true : false) ;
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) ;
Point3d ptVF = ptV + vtMove ;
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 ;
vtNs.Normalize() ;
vtNd.Normalize() ;
double dDots = vtR0 * vtNs ;
double dDotd = vtR0 * vtNd ;
double dMin, dMax, dPLim, dMLim ;
Vector3d vtMin, vtMax, vtP, vtM ;
Vector3d vtUmv = vtMove ;
vtUmv.Normalize() ;
Point3d ptInt ;
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 * dRatio > 1
if ( bCase) {
// Limiti nella direzione positiva di vtV1
if ( dSqDF < dMaxRad * dMaxRad) {
dPLim = dZI + dDeltaZ ;
vtP = - vtV1 ;
}
else {
double dIDL_0 = - sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ;
dPLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtV1 * vtUmv) < EPS_SMALL) {
vtP = - vtV1 ;
}
else {
Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtUmv ;
vtP = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ;
vtP.Normalize() ;
}
}
// Limiti nella direzione negativa di vtV1
if ( dSqDI < dMinRad * dMinRad) {
dMLim = dZTI ;
vtM = vtToolDir ;
}
else if ( dSqDI < dMaxRad * dMaxRad) {
dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
ptInt.Set( dX, dY, dMLim) ;
Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ;
vtU.Normalize() ;
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
else {
double dIDL_0 = sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ;
dMLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtUmv * vtV1) < EPS_SMALL) {
vtM = vtV1 ;
}
else {
Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtUmv ;
vtM = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ;
vtM.Normalize() ;
}
}
}
else {
// Limiti nella direzione positiva di vtV1
if ( dSqDF < dMaxRad * dMaxRad) {
dPLim = dZI + dDeltaZ ;
vtP = - vtV1 ;
}
else {
double dIDL_0 = - sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ;
dPLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtUmv * vtToolDir) < EPS_SMALL) {
vtP = - vtV1 ;
}
else {
Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtUmv ;
////////////////////////////////////////////////////////////////////////////////////////
vtP = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; // vtCross * vtCirc o vtCross * vtMove?
////////////////////////////////////////////////////////////////////////////////////////
vtP.Normalize() ;
}
}
// Limiti nella direzione negativa di vtV1
if ( dSqDI < dMinRad * dMinRad) {
dMLim = dZTI ;
vtM = vtV1 ;
}
else if ( dSqDI >= dMinRad * dMinRad && dSqDI < dMaxRad * dMaxRad && dIVarCos < dCos) {
dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
ptInt.Set( dX, dY, dMLim) ;
Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ;
vtU.Normalize() ;
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
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 ;
vtM = - vtNd ;
}
else if ( dIDO > - dMinRad * dSin && dIDO < dMinRad * dSin) {
double dIDL_0 = sqrt( dMinRad * dMinRad - dIDO * dIDO) ;
dMLim = dZTI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtUmv * vtV1) < EPS_SMALL) {
vtM = vtV1 ;
}
else {
Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtUmv ;
double dDotCrossCirc = vtCross * vtCirc ;
vtM = ( dDotCrossCirc > 0 ? vtCross : - vtCross) ;
vtM.Normalize() ;
}
}
else if ( dIDO >= dMinRad * dSin && dIDO < dMaxRad * dSin) {
dMLim = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; // a qui
vtM = - vtNs ;
}
}
else if ( dFVarCos >= dCos) {
if ( dSqDF < dMinRad * dMinRad) {
double dIDL_0 = sqrt( dMinRad * dMinRad - dIDO * dIDO) ;
dMLim = dZTI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtUmv * vtV1) < EPS_SMALL) {
vtM = vtV1 ;
}
else {
Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtUmv ;
vtM = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ;
vtM.Normalize() ;
}
}
else {
dMLim = dZTI + dDeltaZ + ( sqrt( dSqDF) - dMinRad) * ( dZI - dZTI) / dDeltaR ;
ptInt.Set( dX, dY, dMLim) ;
Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtToolDir * vtToolDir ;
vtU.Normalize() ;
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
}
else {
double dIDL_0 = sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ;
dMLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ;
if ( abs( vtUmv * vtV1) < EPS_SMALL) {
vtM = vtV1 ;
}
else {
Vector3d vtCirc = - dIDL * vtV2 - dIDO * vtV3 ;
Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ;
Vector3d vtCross = vtTan ^ vtMove ;
vtM = ( vtCross * vtMove > 0 ? vtCross : - vtCross) ;
vtM.Normalize() ;
}
}
}
//dMin = min( dPLim, dMLim) ;
//dMax = max( dPLim, dMLim) ;
if ( dMLim < dPLim) {
dMin = dMLim ;
dMax = dPLim ;
vtMin = vtM ;
vtMax = vtP ;
}
else {
dMin = dPLim ;
dMax = dMLim ;
vtMin = vtP ;
vtMax = vtM ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
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, bool bTapB, bool bTapT)
{
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) ;
double dMin, dMax;
Vector3d vtNmin, vtNmax ;
// 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 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLen, dRad, ptInt1, ptInt2,vtN1, vtN2, bTapB, bTapT)) {
//dMin = min( ptInt1.z, ptInt2.z) ;
//dMax = max( ptInt1.z, ptInt2.z) ;
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_Drilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT)
{
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 ;
bool bTapCylEn = bTapB ;
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() ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
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 ;
Vector3d vtN1, vtN2 ;
// Cilindro
if ( IntersLineCylinder( ptC - vtV1 * dL, Z_AX, ConusFrame, dLen, dMaxRad,
ptInt1, ptInt2, vtN1, vtN2, true, bTapCylEn)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtV1.z * dL ;
dMax = ptInt2.z + vtV1.z * dL ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtV1.z * dL ;
dMax = ptInt1.z + vtV1.z * dL ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Cono
if ( IntersLineConus( ptC , Z_AX, ConusFrame, dTan, dl, dL,
ptInt1, ptInt2, vtN1, vtN2, bTapT, true)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z /*+ vtV1.z * dL*/ ;
dMax = ptInt2.z /*+ vtV1.z * dL*/ ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z /*+ vtV1.z * dL*/ ;
dMax = ptInt1.z /*+ vtV1.z * dL*/ ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
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, bool bTapB, bool bTapT)
{
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() ;
// Variabili booleane per i tappi
Vector3d vtUmv = vtMove ; vtUmv.Normalize() ;
bool bCylSt = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ;
bool bCylEn = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ;
bool bElpsB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ;
bool bElpsT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ;
// Minima e massima quota z
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
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 ;
Vector3d vtN1, vtN2 ;
// Cilindro iniziale
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, ptInt1, ptInt2, vtN1, vtN2, bCylSt, bCylEn)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Cilindro finale: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 ( IntersLineCylinder( ptC - vtMove, Z_AX, CylFrame, dHei, dRad, ptInt1, ptInt2, vtN1, vtN2, bCylSt, bCylEn)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtMove.z ;
dMax = ptInt2.z + vtMove.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtMove.z ;
dMax = ptInt1.z + vtMove.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Poliedro interno
if ( IntersLineMyPolyhedron( ptC, Z_AX, CylFrame, dHei, dOrtLen, 2 * dRad, dLongLen, ptInt1, ptInt2, vtN1, vtN2)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Cilindro ellittico di punta
if ( IntersLineEllipticalCylinder( Z_AX, ptC, CylFrame, dSqRad,
dLongLen, dOrtLen, ptInt1, ptInt2, vtN1, vtN2, bElpsT, bElpsT)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// 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, vtN1, vtN2, bElpsB, bElpsB)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + dHei * vtV1.z ;
dMax = ptInt2.z + dHei * vtV1.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + dHei * vtV1.z ;
dMax = ptInt1.z + dHei * vtV1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT)
{
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) ;
vtNs.Normalize() ;
vtNd.Normalize() ;
vtIF.Normalize() ;
vtUD.Normalize() ;
// 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 ;
Vector3d vtUmv = vtMove ; vtUmv.Normalize() ;
// Variabili booleane per i tappi
bool bConeT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ;
bool bConeB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ;
bool bElpsB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ;
bool bElpsT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
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 ;
Vector3d vtN1, vtN2 ;
// Cono iniziale
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2, vtN1, vtN2, bConeT, bConeB)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Cono finale
if ( IntersLineConus( ptC - vtMove, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2, vtN1, vtN2, bConeT, bConeB)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtMove.z ;
dMax = ptInt2.z + vtMove.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtMove.z ;
dMax = ptInt1.z + vtMove.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// 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 ( abs( vtPoly * vtNs) > COS_ORTO_ANG_ZERO) {
if ( dLenY * ptPoly1.x >= dLenX * ptPoly1.y &&
dLenY * ( ptPoly1.x - dDeltaX) <= dLenX * ( ptPoly1.y - dDeltaY) &&
dDeltaX * ptPoly1.y >= dDeltaY * ptPoly1.x &&
dDeltaX * ( ptPoly1.y - dLenY) <= dDeltaY * ( ptPoly1.x - dLenX)) {
ptInt1 = ptPoly1 ;
vtN1 = - vtNs ;
++ nIntNum ;
}
}
// Intersezione con la seconda faccia
if ( abs( vtPoly * vtNd) > COS_ORTO_ANG_ZERO) {
if ( dLenY * ptPoly2.x >= dLenX * ptPoly2.y &&
dLenY * ( ptPoly2.x - dDeltaX) <= dLenX * ( ptPoly2.y - dDeltaY) &&
dDeltaX * ptPoly2.y >= dDeltaY * ptPoly2.x &&
dDeltaX * ( ptPoly2.y - dLenY) <= dDeltaY * ( ptPoly2.x - dLenX)) {
if ( nIntNum == 0) {
ptInt1 = ptPoly2 ;
vtN1 = - vtNd ;
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly2).SqLen() > dSqIndet) {
ptInt2 = ptPoly2 ;
vtN2 = - vtNd ;
++ nIntNum ;
}
}
}
// Intersezione con la terza faccia
if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) {
if ( nIntNum < 2 &&
ptPoly3.x >= 0 && ptPoly3.x <= dDeltaX &&
dDeltaX * abs( ptPoly3.z) < dDeltaX * dLenZ + dDeltaZ * ptPoly3.x) {
if ( nIntNum == 0) {
ptInt1 = ptPoly3 ;
vtN1 = - vtIF ;
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly3).SqLen() > dSqIndet) {
ptInt2 = ptPoly3 ;
vtN2 = - vtIF ;
++ nIntNum ;
}
}
}
// Intersezione con la quarta faccia
if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) {
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 ;
vtN1 = vtIF ;
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly4).SqLen() > dSqIndet) {
ptInt2 = ptPoly4 ;
vtN2 = vtIF ;
++ nIntNum ;
}
}
}
// Intersezione con la quinta faccia
if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) {
if ( nIntNum < 2 &&
ptPoly5.y >= 0 && ptPoly5.y <= dLenY &&
abs( ptPoly5.z) <= dLenZ) {
if ( nIntNum == 0) {
ptInt1 = ptPoly5 ;
vtN1 = - vtUD ;
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly5).SqLen() > dSqIndet) {
ptInt2 = ptPoly5 ;
vtN2 = - vtUD ;
++ nIntNum ;
}
}
}
// Intersezione con la sesta faccia
if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) {
if ( nIntNum < 2 &&
ptPoly6.y >= dDeltaY && ptPoly6.y <= dLenY + dDeltaY &&
abs( ptPoly6.z) <= dLenZ + dDeltaZ) {
if ( nIntNum == 0) {
ptInt1 = ptPoly6;
vtN1 = vtUD ;
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly6).SqLen() > dSqIndet) {
ptInt2 = ptPoly6;
vtN2 = vtUD ;
++ nIntNum ;
}
}
}
// Se il poliedro è attraversato taglio
if ( nIntNum == 2) {
// Riporto le intersezioni nel sistema griglia
ptInt1.ToGlob( PolyFrame) ;
ptInt2.ToGlob( PolyFrame) ;
vtN1.ToGlob( PolyFrame) ;
vtN2.ToGlob( PolyFrame) ;
//dMin = min( ptInt1.z, ptInt2.z) ;
//dMax = max( ptInt1.z, ptInt2.z) ;
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Traslazione ellisse di punta
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dl, ConusFrame, dSqMinRad,
dLongLen, dOrtLen, ptInt1, ptInt2, vtN1, vtN2, bElpsT, bElpsT)) {
if( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtV1.z * dl ;
dMax = ptInt2.z + vtV1.z * dl ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtV1.z * dl ;
dMax = ptInt1.z + vtV1.z * dl ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Traslazione ellisse di base
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dSqMaxRad,
dLongLen, dOrtLen, ptInt1, ptInt2, vtN1, vtN2, bElpsB, bElpsB)) {
if( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtV1.z * dL ;
dMax = ptInt2.z + vtV1.z * dL ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtV1.z * dL ;
dMax = ptInt1.z + vtV1.z * dL ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
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 ;
Vector3d vtN1, vtN2 ;
// Cono
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, ptInt1, ptInt2, vtN1, vtN2, bConeT, bConeB)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Traslazione ellisse
if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dSqMaxRad,
dLongLen, dOrtLen, ptInt1, ptInt2, vtN1, vtN2, bConeB, bConeB)) {
if( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z + vtV1.z * dL ;
dMax = ptInt2.z + vtV1.z * dL ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z + vtV1.z * dL ;
dMax = ptInt1.z + vtV1.z * dL ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
return true ;
}
}
// ---------- SFERA ----------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::CompBall_Milling( unsigned int nGrid, const Point3d & ptLs, const Point3d & ptLe, double dRad)
{
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 ;
Vector3d vtV = ptLe - ptLs ;
double dLengthPath = vtV.Len() ;
vtV.Normalize() ;
Vector3d vtW ;
// Costruisco sistema di riferimento
if ( vtV.x * vtV.x > 0.3)
vtW.Set( - ( vtV.y + vtV.z) / vtV.x, 1, 1) ;
else if ( vtV.y * vtV.y > 0.3)
vtW.Set( 1, - ( vtV.x + vtV.z) / vtV.y, 1) ;
else
vtW.Set( 1, 1, - ( vtV.x + vtV.y) / vtV.z) ;
Point3d ptOnY = ptLs + vtW ;
Frame3d CylFrame ; CylFrame.Set( ptLs, ptLe, ptOnY) ;
double dSqRad = dRad * dRad ;
double dMin, dMax ;
Vector3d vtNmin, vtNmax ;
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) ;
double dStSqDXY = SqDistXY( ptC, ptLs) ;
double dEnSqDXY = SqDistXY( ptC, ptLe) ;
// Prima sfera
if ( dStSqDXY < dSqRad) {
dMin = ptLs.z - sqrt( dSqRad - dStSqDXY) ;
dMax = ptLs.z + sqrt( dSqRad - dStSqDXY) ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
vtNmin = ptLs - ptIntMin ;
vtNmax = ptLs - ptIntMax ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Seconda sfera
if ( dEnSqDXY < dSqRad) {
dMin = ptLe.z - sqrt( dSqRad - dEnSqDXY) ;
dMax = ptLe.z + sqrt( dSqRad - dEnSqDXY) ;
Point3d ptIntMin( dX, dY, dMin) ;
Point3d ptIntMax( dX, dY, dMax) ;
vtNmin = ptLe - ptIntMin ;
vtNmax = ptLe - ptIntMax ;
vtNmin.Normalize() ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Cilindro
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, ptInt1, ptInt2, vtN1, vtN2, false, false)) {
if ( ptInt1.z < ptInt2.z) {
dMin = ptInt1.z ;
dMax = ptInt2.z ;
vtNmin = vtN1 ;
vtNmax = vtN2 ;
}
else {
dMin = ptInt2.z ;
dMax = ptInt1.z ;
vtNmin = vtN2 ;
vtNmax = vtN1 ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
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 ;
}