Files
EgtGeomKernel/VolZmapVolume.cpp
T
2022-01-05 15:46:40 +01:00

8096 lines
351 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2020
//----------------------------------------------------------------------------
// File : VolZmap.cpp Data : 05.10.20 Versione : 2.2j1
// Contenuto : Implementazione della classe Volume Zmap (tre griglie)
//
//
//
// Modifiche : 22.01.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "VolZmap.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSphere.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
#include "/EgtDev/Include/EgtPerfCounter.h"
#include <future>
using namespace std ;
// ------------------------- OPERAZIONI SU INTERVALLI --------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::SubtractIntervals( int nGrid, int nI, 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_ZERO)
return true ;
// Controllo che il numero di griglia sia entro i limiti
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo che gli indici nI, nJ siano entro i limiti
if ( nI < 0 || nI >= m_nNx[nGrid] ||
nJ < 0 || nJ >= m_nNy[nGrid])
return false ;
// Controllo che dMin < dMax
Vector3d vtNmi = vtNMin ;
Vector3d vtNma = vtNMax ;
if ( dMin > dMax) {
swap( dMin, dMax) ;
swap( vtNmi, vtNma) ;
}
// Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco)
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) ;
}
// Recupero dexel da modificare
int nPos = nJ * m_nNx[nGrid] + nI ;
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
// Ciclo sugli intervalli del dexel (ordinati in senso crescente)
bool bModified = false ;
for ( int i = 0 ; i < int( vDexel.size()) ; ++i) {
// Se interseca l'intervallo corrente
if ( dMin < vDexel[i].dMax - EPS_ZERO && dMax > vDexel[i].dMin + EPS_ZERO) {
bModified = true ;
// se devo limitarlo inferiormente
if ( dMin <= vDexel[i].dMin + EPS_ZERO && dMax < vDexel[i].dMax - EPS_ZERO) {
vDexel[i].dMin = dMax ;
vDexel[i].vtMinN = vtNma ;
vDexel[i].nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
}
// se devo limitarlo superiormente
else if ( dMin > vDexel[i].dMin + EPS_ZERO && dMax >= vDexel[i].dMax - EPS_ZERO) {
vDexel[i].dMax = dMin ;
vDexel[i].vtMaxN = vtNmi ;
vDexel[i].nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
}
// se devo dividerlo in due parti
else if ( dMin > vDexel[i].dMin + EPS_ZERO && dMax < vDexel[i].dMax - EPS_ZERO) {
// inserisco nuovo intervallo (parte superiore)
vDexel.insert( vDexel.begin() + i + 1,
{ dMax, vtNma, m_vTool[m_nCurrTool].GetCurrentToolNum(),
vDexel[i].dMax, vDexel[i].vtMaxN, vDexel[i].nToolMax,
vDexel[i].nCompo}) ;
// aggiorno il vecchio (parte inferiore)
vDexel[i].dMax = dMin ;
vDexel[i].vtMaxN = vtNmi ;
vDexel[i].nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
++ i ;
}
// altrimenti devo eliminarlo
else {
vDexel.erase( vDexel.begin() + i) ;
-- i ;
}
}
// se tutto minore dell'intervallo corrente, ho finito
else if ( dMax <= vDexel[i].dMin + EPS_ZERO)
break ;
// altrimenti tutto maggiore dell'intervallo corrente, passo al successivo
else // dMin >= vDexel[i].dMax - EPS_ZERO
;
}
// Se nessuna modifica, esco
if ( ! bModified)
return true ;
// Elimino residui di intervalli inutili
for ( int i = 0 ; i < int( vDexel.size()) ; ++ i) {
int nMaxN = int( floor( ( vDexel[i].dMax + 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ;
int nMinN = int( floor( ( vDexel[i].dMin - 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ;
if ( nMinN == nMaxN) {
vDexel.erase( vDexel.begin() + i) ;
-- i ;
}
}
// Imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// Imposto forma generica
m_nShape = GENERIC ;
// Imposto ricalcolo numero di componenti connesse
m_nConnectedCompoCount = - 1 ;
// Passo da indici di dexel a indici di voxel
nI /= m_nDexVoxRatio ;
nJ /= m_nDexVoxRatio ;
// Determino quali blocchi sono stati modificati
if ( nGrid == 0) {
// Voxel lungo X
int nXStop = 1 ;
int nXBlock[2] ;
nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
// Voxel lungo Y
int nYStop = 1 ;
int nYBlock[2] ;
nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
// Voxel lungo Z
int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ;
int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
for ( int tI = 0 ; tI < nXStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) {
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) {
int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 1) {
// Voxel lungo Y
int nYStop = 1 ;
int nYBlock[2] ;
nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
// Voxel lungo Z
int nZStop = 1 ;
int nZBlock[2] ;
nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Voxel lungo X
int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ;
int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
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] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 2) {
// Voxel lungo X
int nXStop = 1 ;
int nXBlock[2] ;
nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
// Voxel lungo Z
int nZStop = 1 ;
int nZBlock[2] ;
nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Voxel lungo Y
int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ;
int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
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] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AddIntervals( int nGrid, int nI, 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 indici nI, nJ siano entro i limiti
if ( nI < 0 && nI >= m_nNx[nGrid] &&
nJ < 0 && nJ >= m_nNy[nGrid])
return false ;
// Controllo che dMin < dMax
Vector3d vtNmi = vtNMin ;
Vector3d vtNma = vtNMax ;
if ( dMin > dMax) {
swap( dMin, dMax) ;
swap( vtNmi, vtNma) ;
}
// 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 ;
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
bool bModified = false ;
// Non esistono segmenti
if ( m_Values[nGrid][nPos].size() == 0) {
vDexel.emplace_back() ;
vDexel.back().dMin = dMin ;
vDexel.back().vtMinN = vtNmi ;
vDexel.back().nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
vDexel.back().dMax = dMax ;
vDexel.back().vtMaxN = vtNma ;
vDexel.back().nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
if ( dMax > m_dMaxZ[nGrid])
m_dMaxZ[nGrid] = dMax ;
if ( dMin < m_dMinZ[nGrid])
m_dMinZ[nGrid] = dMin ;
m_OGrMgr.Reset() ;
bModified = true ;
}
// Esiste almeno un segmento
else {
// Cerco l'ultimo intervallo a sinistra e l'ultimo intervallo a destra
// di quello da aggiungere, che non interferiscono con quest'ultimo.
auto itLastLeft = vDexel.end() ;
auto itFirstRight = vDexel.end() ;
for ( auto it = vDexel.begin() ; it != vDexel.end() ; ++ it) {
if ( dMin > it->dMax + EPS_SMALL)
itLastLeft = it ;
if ( dMax < it->dMin - EPS_SMALL && itFirstRight == vDexel.end())
itFirstRight = it ;
}
// Esistono intervalli a sinistra.
if ( itLastLeft != vDexel.end()) {
// Intervallo successivo all'ultimo a sinistra
auto itNextToLastLeft = itLastLeft ;
++ itNextToLastLeft ;
// Il successivo non esiste.
if ( itNextToLastLeft == vDexel.end()) {
// Aggiungo il nuovo semgento
vDexel.emplace_back() ;
vDexel.back().dMin = dMin ;
vDexel.back().dMax = dMax ;
vDexel.back().vtMinN = vtNmi ;
vDexel.back().vtMaxN = vtNma;
vDexel.back().nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
vDexel.back().nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//m_Values[nGrid][nPos].back().nCompo = ;
bModified = true ;
}
// Il successivo esiste.
else {
// Il successivo è il primo a destra.
if ( itNextToLastLeft == itFirstRight) {
// Inserisco nuovo segmento-
Data NewSegment ;
NewSegment.dMin = dMin ;
NewSegment.dMax = dMax ;
NewSegment.vtMinN = vtNmi ;
NewSegment.vtMaxN = vtNma ;
NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//NewSegment.nCompo = ;
vDexel.insert( itFirstRight, NewSegment) ;
bModified = true ;
}
else {
// Il successivo non esce a sinistra da quello da aggiungere.
if ( itNextToLastLeft->dMin > dMin + EPS_SMALL) {
itNextToLastLeft->dMin = dMin ;
itNextToLastLeft->vtMinN = vtNmi ;
itNextToLastLeft->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
}
// Cerco l'ultimo segmento che interferisce con quello da aggiungere.
auto itPrevToFirstRight = vDexel.end() ;
for ( auto it = itNextToLastLeft ; it != itFirstRight ; ++ it) {
itPrevToFirstRight = it ;
}
// L'ultimo che interferisce non esce a destra da quello da aggiungere.
if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) {
itNextToLastLeft->dMax = dMax ;
itNextToLastLeft->vtMaxN = vtNma ;
itNextToLastLeft->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//itNextToLastLeft->nCompo = ;
bModified = true ;
}
else {
itNextToLastLeft->dMax = itPrevToFirstRight->dMax ;
itNextToLastLeft->vtMaxN = itPrevToFirstRight->vtMaxN ;
itNextToLastLeft->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//itNextToLastLeft->nCompo = ;
bModified = true ;
}
auto itFirstToCancel = itNextToLastLeft ;
++ itFirstToCancel ;
vDexel.erase( itFirstToCancel, itFirstRight) ;
}
}
}
// Non esistono neanche a destra.
else if ( itFirstRight == m_Values[nGrid][nPos].end()) {
// Il primo intervallo non sporge a sinistra
if ( vDexel.begin()->dMin > dMin + EPS_SMALL) {
vDexel.begin()->dMin = dMin ;
vDexel.begin()->vtMinN = vtNmi ;
vDexel.begin()->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
// L'ultimo intervallo sporge a destra.
if ( m_Values[nGrid][nPos].back().dMax > dMax + EPS_SMALL) {
// Ci sono più segmenti, inglobo tutti nel primo.
if ( vDexel.back().dMax > vDexel.begin()->dMax + EPS_SMALL) {
vDexel.begin()->dMax = vDexel.back().dMax ;
vDexel.begin()->vtMaxN = vDexel.back().vtMaxN ;
vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
}
// L'ultimo intervallo non sporge a destra.
else {
vDexel.begin()->dMax = dMax ;
vDexel.begin()->vtMaxN = vtNma ;
vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
vDexel.erase( vDexel.begin() + 1, vDexel.end()) ;
}
// A destra esistono.
else {
// Tutti i segmenti sono a destra di qullo da aggiungere.
if ( itFirstRight == vDexel.begin()) {
// Inserisco nuovo segmento-
Data NewSegment ;
NewSegment.dMin = dMin ;
NewSegment.dMax = dMax ;
NewSegment.vtMinN = vtNmi ;
NewSegment.vtMaxN = vtNma ;
NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//NewSegment.nCompo = ;
vDexel.insert( vDexel.begin(), NewSegment) ;
bModified = true ;
}
else {
// Se il primo segmento non esce a sinistra da quello da aggiungere, cambio l'inizio.
if ( vDexel.begin()->dMin > dMin + EPS_SMALL) {
vDexel.begin()->dMin = dMin ;
vDexel.begin()->vtMinN = vtNmi ;
vDexel.begin()->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
// Cerco l'ultimo segmento che interferisce con quello da aggiungere.
auto itPrevToFirstRight = vDexel.begin() ;
for ( auto it = m_Values[nGrid][nPos].begin() ; it != itFirstRight ; ++ it) {
itPrevToFirstRight = it ;
}
// L'ultimo che interferisce non esce a destra da quello da aggiungere.
if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) {
vDexel.begin()->dMax = dMax ;
vDexel.begin()->vtMaxN = vtNma ;
vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
else {
vDexel.begin()->dMax = itPrevToFirstRight->dMax ;
vDexel.begin()->vtMaxN = itPrevToFirstRight->vtMaxN ;
vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
//vDexel.begin().nCompo = ;
bModified = true ;
}
auto itFirstToCancel = vDexel.begin() ;
++ itFirstToCancel ;
vDexel.erase( itFirstToCancel, itFirstRight) ;
}
}
}
// Se nessuna modifica, esco
if ( ! bModified)
return true ;
// Elimino residui di intervalli inutili
for ( int i = 0 ; i < int( vDexel.size()) ; ++ i) {
int nMaxN = int( floor( ( vDexel[i].dMax + 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ;
int nMinN = int( floor( ( vDexel[i].dMin - 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ;
if ( nMinN == nMaxN) {
vDexel.erase( vDexel.begin() + i) ;
-- i ;
}
}
// Imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// Imposto forma generica
m_nShape = GENERIC ;
// Imposto ricalcolo numero di componenti connesse
m_nConnectedCompoCount = - 1 ;
// Passo da indici di dexel a indici di voxel
nI /= m_nDexVoxRatio ;
nJ /= m_nDexVoxRatio ;
// Determino quali blocchi sono stati modificati
if ( nGrid == 0) {
// Voxel lungo X
int nXStop = 1 ;
int nXBlock[2] ;
nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
// Voxel lungo Y
int nYStop = 1 ;
int nYBlock[2] ;
nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
// Voxel lungo Z
int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ;
int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
for ( int tI = 0 ; tI < nXStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) {
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) {
int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 1) {
// Voxel lungo Y
int nYStop = 1 ;
int nYBlock[2] ;
nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
// Voxel lungo Z
int nZStop = 1 ;
int nZBlock[2] ;
nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Voxel lungo X
int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ;
int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
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] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 2) {
// Voxel lungo X
int nXStop = 1 ;
int nXBlock[2] ;
nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
// Voxel lungo Z
int nZStop = 1 ;
int nZBlock[2] ;
nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Voxel lungo Y
int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ;
int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ;
// Assegno flag ai voxel
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] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
return true ;
}
// ------------------------- LAVORAZIONI --------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs,
const Point3d& ptPe, const Vector3d& vtDe)
{
return MillingStep( ptPs, vtDs, Vector3d(), ptPe, vtDe, Vector3d()) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe)
{
// Se non definito l'utensile, non devo fare alcunch
if ( m_nCurrTool < 0 || m_vTool[m_nCurrTool].GetType() == Tool::UNDEF)
return true ;
// Controllo definizione vettori direzione
if ( vtDs.IsSmall() || vtDe.IsSmall())
return false ;
// Controllo sull'effettiva esistenza del movimento
if ( AreSamePointApprox( ptPs, ptPe) && AreSameVectorApprox( vtDs, vtDe))
return true ;
// Se utensile chisel o mortise, controllo definizione vettori ausiliari
if ( m_vTool[m_nCurrTool].GetType() == Tool::MORTISER || m_vTool[m_nCurrTool].GetType() == Tool::CHISEL) {
if ( vtAs.IsSmall() || vtAe.IsSmall())
return false ;
}
// Reset numero di parti
m_nConnectedCompoCount = - 1 ;
// Punti e vettori descriventi il moto nel sistema intrinseco dello Zmap
Point3d ptPLs = ptPs ;
ptPLs.ToLoc( m_MapFrame) ;
Point3d ptPLe = ptPe ;
ptPLe.ToLoc( m_MapFrame) ;
Vector3d vtDLs = vtDs ;
vtDLs.ToLoc( m_MapFrame) ;
vtDLs.Normalize() ;
Vector3d vtDLe = vtDe ;
vtDLe.ToLoc( m_MapFrame) ;
vtDLe.Normalize() ;
Vector3d vtALs = vtAs ;
vtALs.ToLoc( m_MapFrame) ;
vtALs.Normalize() ;
Vector3d vtALe = vtAe ;
vtALe.ToLoc( m_MapFrame) ;
vtALe.Normalize() ;
//static PerformanceCounter Counter ;
//{
//string sOut = "Draw=" + ToString( Counter.Stop(), 3) ;
//LOG_INFO( GetEGkLogger(), sOut.c_str())
//Counter.Start() ;
//}
// Se pura traslazione
bool bOk ;
if ( AreSameVectorApprox( vtDLs, vtDLe))
bOk = MillingTranslationStep( ptPLs, ptPLe, vtDLs, vtALs) ;
else
bOk = MillingGeneralMotionStep( ptPLs, vtDLs, vtALs, ptPLe, vtDLe, vtALe) ;
//{
//string sOut = "Calc=" + ToString( Counter.Stop(), 3) ;
//LOG_INFO( GetEGkLogger(), sOut.c_str())
//Counter.Start() ;
//}
return bOk ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe)
{
// Divido il movimento in tratti con direzione utensile costante
const double ANG_STEP = 0.5 ;
double dAngDeg ; vtDs.GetAngle( vtDe, dAngDeg) ;
int nStepCnt = int( abs( dAngDeg) / ANG_STEP) + 1 ;
bool bOk = true ;
Point3d ptSt = ptPs ;
for ( int i = 0 ; i <= nStepCnt && bOk ; ++ i) {
double dPosCoeff, dDirCoeff ;
if ( i < nStepCnt) {
dPosCoeff = ( i + 0.5) / nStepCnt ;
dDirCoeff = double( i) / nStepCnt ;
}
else {
dPosCoeff = 1 ;
dDirCoeff = 1 ;
}
Point3d ptEn = Media( ptPs, ptPe, dPosCoeff) ;
Vector3d vtD = Media( vtDs, vtDe, dDirCoeff) ; vtD.Normalize() ;
Vector3d vtA = Media( vtAs, vtAe, dDirCoeff) ; vtA.Normalize() ;
bOk = bOk && MillingTranslationStep( ptSt, ptEn, vtD, vtA) ;
// aggiorno prossimo inizio
ptSt = ptEn ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA)
{
Point3d ptLs[N_MAPS] ;
Point3d ptLe[N_MAPS] ;
Vector3d vtLs[N_MAPS] ;
Vector3d vtALs[N_MAPS] ;
InitializePointsAndVectors( ptPs, ptPe, vtD, vtA, ptLs, ptLe, vtLs, vtALs) ;
// Ciclo sulle mappe
vector< future<bool>> vRes ;
vRes.resize( m_nMapNum) ;
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
vRes[i] = async( launch::async, &VolZmap::SelectMotion, this, i, cref( ptLs[i]), cref( ptLe[i]), cref( vtLs[i]), cref( vtALs[i])) ;
}
bool bOk = true ;
int nTerminated = 0 ;
while ( nTerminated < m_nMapNum) {
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
bOk = vRes[i].get() && bOk ;
++ nTerminated ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs,
Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3])
{
// Punti posizione
ptLs[0] = ptPs ;
ptLe[0] = ptPe ;
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 ;
}
// Vettori asse utensile
vtLs[0] = vtDs ;
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 ;
}
// Vettori ausiliari
vtALs[0] = vtAs ;
if ( m_nMapNum > 1) {
vtALs[1].x = vtALs[0].y ; vtALs[1].y = vtALs[0].z ; vtALs[1].z = vtALs[0].x ;
vtALs[2].x = vtALs[0].z ; vtALs[2].y = vtALs[0].x ; vtALs[2].z = vtALs[0].y ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL)
{
// Versore utensile parallelo all'asse Z (coincide con spillone)
if ( vtL.SqLenXY() < EPS_ZERO * EPS_ZERO) {
Vector3d vtMove = ptLe - ptLs ;
// Foratura
if ( vtMove.SqLenXY() < EPS_SMALL * EPS_SMALL) {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
Chs_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
// Fresatura con vettore movimento perpendicolare all'utensile
else if ( abs( vtMove.z) < EPS_SMALL) {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_ZPerp( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_ZPerp( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::ADDITIVE :
// Chiama metodo
break ;
}
}
// Fresatura con vettore movimento generico rispetto all'utensile
else {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_ZMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_ZMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
}
// Versore utensile nel piano XY (perpendicolare allo spillone)
else if ( abs( vtL.z) < EPS_ZERO) {
Vector3d vtMove = ptLe - ptLs ;
Vector3d vtMLong = ( vtMove * vtL) * vtL ;
Vector3d vtMOrt = vtMove - vtMLong ;
double dSqLLong = vtMLong.SqLen() ;
double dSqLOrt = vtMOrt.SqLen() ;
// Foratura
if ( dSqLOrt < EPS_SMALL * EPS_SMALL) {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_XYDrilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_XYDrilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
// Fresatura con vettore movimento perpendicolare all'utensile
else if ( dSqLLong < EPS_SMALL * EPS_SMALL) {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_Milling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_XYPerp( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
// Usiamo la generica per via dell'intsabilit di Conus_XYPerp
//Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
Conus_Milling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::ADDITIVE :
// Chiama metodo
break ;
}
}
// Fresatura con vettore movimento generico rispetto all'utensile
else {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_Milling( nGrid, ptLs, ptLe, vtL);
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_XYMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_XYMilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
}
// Versore utensile con direzione generica
else {
Vector3d vtMove = ptLe - ptLs ;
Vector3d vtMLong = ( vtMove * vtL) * vtL ;
Vector3d vtMOrt = vtMove - vtMLong ;
double dSqLLong = vtMLong.SqLen() ;
double dSqLOrt = vtMOrt.SqLen() ;
// Foratura
if ( dSqLOrt < EPS_SMALL * EPS_SMALL) {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_Drilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_Drilling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
// Fresatura con vettore movimento generico rispetto all'utensile
else {
switch ( m_vTool[m_nCurrTool].GetType()) {
case Tool::GEN :
GenTool_Milling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CYLMILL :
case Tool::BALLMILL :
CylBall_Milling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::CONEMILL :
Conus_Milling( nGrid, ptLs, ptLe, vtL) ;
break ;
case Tool::MORTISER :
Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
case Tool::CHISEL :
// ammesso solo movimento perpendicolare all'asse utensile
if ( dSqLLong < EPS_SMALL * EPS_SMALL)
Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
break ;
}
}
}
return true ;
}
// ---------- VERSORE UTENSILE DERETTO COME Z --------------------------------
// ---------- Cilindro e sfera -----------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::CylBall_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Proiezione dei punti sul piano
Point3d ptSxy( ptS.x, ptS.y, 0) ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
// 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 ( int i = nStartI ; i <= nEndI ; ++ i) {
for( 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_vTool[m_nCurrTool].GetRadius() * EPS_SMALL) {
// utensile cilindrico
if ( m_vTool[m_nCurrTool].GetType() == Tool::CYLMILL)
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ;
// utensile sferico
else if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dSafeRad = m_vTool[m_nCurrTool].GetRadius() - 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, 0, 1) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for( 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_vTool[m_nCurrTool].GetType() == Tool::CYLMILL) {
// 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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
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( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dSafeRadius = m_vTool[m_nCurrTool].GetRadius() - EPS_SMALL ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
double dSafeSqRad = dSqRad - 2 * m_vTool[m_nCurrTool].GetRadius() * 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 dDeltaZ = dZMaxF - dZMaxI ;
// Vettori caratterizzanti il moto
Vector3d vtMove = ptF - ptI ;
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
double dLenXY = vtMoveXY.LenXY() ;
vtMove.Normalize() ;
// 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, 0, 1) ;
double dMin, dMax ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL)
CompBall_Milling( nGrid, ptIT, ptFT, m_vTool[m_nCurrTool].GetRadius()) ;
return true ;
}
// ---------- Coni -----------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Conus_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
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_vTool[m_nCurrTool].GetHeigth()),
max( ptE.z, ptE.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth())) ;
double dZMin = min( min( ptS.z, ptS.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth()),
min( ptE.z, ptE.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth())) ;
// Parametri geometrici per
// determinare il vettore normale
double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ;
// Trapano
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetTipHeigth() * ( 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_vTool[m_nCurrTool].GetTipHeigth() * ( 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 ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetTipHeigth() * ( 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_vTool[m_nCurrTool].GetTipHeigth() * ( 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( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
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_vTool[m_nCurrTool].GetHeigth() ;
// Lunghezza cono
double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ;
// Punta a trapano
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
Vector3d vtV = vtToolDir ;
Point3d ptVS = ptS - vtToolDir * ( dStemHeigth + dL) ;
Point3d ptVE = ptE - vtToolDir * ( dStemHeigth + dL) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for( 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)) {
double dMin = min( dBaseZ, dTipZ) ;
double 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) ;
double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else if ( dP1 <= dLen) {
double dr = abs( dP2) ;
double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else {
double dr = sqrt( dSqLenE) ;
double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
}
}
// Coda di rondine
else {
Vector3d vtV = - vtToolDir ;
Point3d ptVS = ptS - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ;
Point3d ptVE = ptE - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for( 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)) {
double dMin = min( dBaseZ, dTipZ) ;
double 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) ;
double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else if ( dP1 <= dLen) {
double dr = abs( dP2) ;
Point3d ptVtemp = ptVS + vtV1 * dP1 ;
double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
else {
double dr = sqrt( dSqLenE) ;
double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ;
double 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_vTool[m_nCurrTool].GetTipHeigth() * 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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
double dStemH = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
CompCyl_ZMilling( nGrid, ptS, ptE, vtToolDir, dStemH, m_vTool[m_nCurrTool].GetRadius()) ;
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
Point3d ptSC = ptS - vtToolDir * dStemH ;
Point3d ptEC = ptE - vtToolDir * dStemH ;
CompConus_ZMilling( nGrid, ptSC, ptEC, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
}
else {
Point3d ptSC = ptS - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() ;
Point3d ptEC = ptE - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() ;
CompConus_ZMilling( nGrid, ptSC, ptEC, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius()) ;
}
return true ;
}
// --------- Mortasatrice -----------------------------------------------------
// ----------------------------------------------------------------------------
bool
VolZmap::Mrt_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Proiezione della traiettoria sul piano dei movimenti possibili
Vector3d vtMoveOnP = ( ptE - ptS) * vtToolDir * vtToolDir ;
Point3d ptEOnP = ptS + vtMoveOnP ;
// Scompongo la mortasatrice in solidi semplici
// Parallelepipedo di base
double dLenX = m_vTool[m_nCurrTool].GetMrtChsWidth() ;
double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ;
double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ;
CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ;
// Se la punta di tipo bull-nose
if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) {
// Parallelepipedo di punta
Point3d ptTipS = ptS - dLenZ * vtToolDir ;
Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ;
dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ;
dLenZ = m_vTool[m_nCurrTool].GetCornRadius() ;
CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux) ;
Vector3d vtVOnP = vtToolDir ^ vtAux ;
// Cilindri
Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
// se la punta di tipo sfera
else {
// Cilindro
Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
Point3d ptCylE = ptEOnP - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
return true ;
}
// --------- Chisel ----------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Chs_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
CompPar_ZDrilling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(),
ptS, ptE, vtToolDir, vtAux) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Chs_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Proiezione della traiettoria sul piano dei moti possibili
Point3d ptSp = ptS ;
Vector3d vtMoveOnP = ( ptE - ptS) - ( ptE - ptS) * vtToolDir * vtToolDir ;
Point3d ptEp = ptS + vtMoveOnP ;
CompPar_ZMilling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(),
ptSp, ptEp, vtToolDir, vtAux) ;
return true ;
}
// --------- Utensile generico ------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::GenTool_ZDrilling( 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 ;
// Vettore delle normali agli archi
const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ;
// Poinch l'asse utensile parallelo all'asse Z, definisco un sistema di
// riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ.
Frame3d frNormFrame ;
frNormFrame.Set( ORIG, X_AX, - Z_AX, Y_AX) ;
// Ciclo sulle curve
const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ;
int i = - 1 ;
const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ;
while ( pCurve != nullptr) {
double dHeight = 0 ;
double dSignedHeight = 0 ;
// Se segmento
if ( pCurve->GetType() == CRV_LINE) {
// Recupero gli estremi
const ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptStart = pLine->GetStart() ;
Point3d ptEnd = pLine->GetEnd() ;
int nNormNum = pLine->GetTempProp() ;
Vector3d vtNormSt, vtNormEn ;
if ( nNormNum != 0) {
vtNormSt = vArcNorm[nNormNum - 1] ;
vtNormEn = vArcNorm[nNormNum] ;
vtNormSt.ToLoc( frNormFrame) ;
vtNormEn.ToLoc( frNormFrame) ;
}
// Ne determino l'altezza
dSignedHeight = ptStart.y - ptEnd.y ;
dHeight = abs( dSignedHeight) ;
// Cilindro o cono
if ( dHeight > EPS_SMALL) {
// Se X costante, un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
if ( dRadius > 10 * EPS_SMALL && m_vTool[m_nCurrTool].GetCuttingFlag())
CompCyl_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
}
// Se X crescente, un cono con vettore equiverso a quello dell'utensile
else if ( ptStart.x > ptEnd.x) {
double dMaxRad = ptStart.x ;
double dMinRad = ptEnd.x ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormSt, vtNormEn) ;
else {
Point3d ptIn = ptI ;
Point3d ptFn = ptIn + vtMove ;
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormEn, vtNormSt) ;
}
}
}
// Se X decrescente, 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 * dSignedHeight ;
Point3d ptFn = ptIn + vtMove ;
vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormEn, vtNormSt) ;
else {
vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;
SurfConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormSt, vtNormEn) ;
}
}
}
}
// Corona circolare
else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) {
if ( ptStart.x < ptEnd.x) {
SurfCircCrown_ZDrilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ;
}
else {
SurfCircCrown_ZDrilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ;
}
}
}
// se altrimenti arco
else if ( pCurve->GetType() == CRV_ARC) {
// Recupero estremi, centro e raggio
const ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
Point3d ptCen = pArc->GetCenter() ;
double dRadius = pArc->GetRadius() ;
// Determino le posizioni iniziale e finale del centro della sfera
Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ;
Point3d ptCenE = ptCenS + vtMove ;
// Eseguo l'asportazione del materiale
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ;
else if ( pCurve->GetTempProp( 1) == 1) {
double dStH = ptStart.y - ptCen.y ;
double dEnH = ptEnd.y - ptCen.y ;
// Tagliente esterno
if ( dEnH < dStH) {
if ( dEnH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ;
}
else if ( dStH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ;
}
}
// Tagliente interno
else {
if ( dEnH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
else if ( dStH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
}
dSignedHeight = ptStart.y - ptEnd.y ;
}
// aggiorno l'altezza
//dHeight = abs( ptStart.y - ptEnd.y) ;
}
// Determino le posizioni iniziale e finale del componente successivo
ptI = ptI - vtToolDir * dSignedHeight ;
ptF = ptI + vtMove ;
// Passo alla curva successiva del profilo
pCurve = ToolProfile.GetCurve( ++ i) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GenTool_ZMilling( 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 ;
// Vettore delle normali agli archi
const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ;
// Poinch l'asse utensile parallelo all'asse Z, definisco un sistema di
// riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ.
Frame3d frNormFrame;
frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ;
// Ciclo sulle curve del profilo utensile
const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ;
int i = - 1 ;
const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ;
while ( pCurve != nullptr) {
double dHeight = 0 ;
double dSignedHeight = 0 ;
// Se segmento
if ( pCurve->GetType() == CRV_LINE) {
// Recupero gli estremi
const ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptStart = pLine->GetStart() ;
Point3d ptEnd = pLine->GetEnd() ;
int nNormNum = pLine->GetTempProp() ;
Vector3d vtNormSt, vtNormEn ;
if ( nNormNum != 0) {
vtNormSt = vArcNorm[nNormNum - 1] ;
vtNormEn = vArcNorm[nNormNum] ;
vtNormSt.ToLoc( frNormFrame) ;
vtNormEn.ToLoc( frNormFrame) ;
}
// Ne determino l'altezza
dSignedHeight = ptStart.y - ptEnd.y ;
dHeight = abs( dSignedHeight) ;
if ( dHeight > EPS_SMALL) {
// Se X costante, un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
if ( dRadius > 10 * EPS_SMALL) {
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, true) ;
else {
SurfCyl_ZMilling( nGrid, ptI, ptF, - vtToolDir, dHeight, dRadius, false) ;
}
}
}
}
// Se X crescente, un cono con vettore equiverso a quello dell'utensile
else if ( ptStart.x > ptEnd.x) {
double dMaxRad = ptStart.x ;
double dMinRad = ptEnd.x ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormSt, vtNormEn) ;
else {
Point3d ptIn = ptI ;
Point3d ptFn = ptIn + vtMove ;
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormEn, vtNormSt) ;
}
}
}
// Se X decrescente, 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 * dSignedHeight ;
Point3d ptFn = ptIn + vtMove ;
vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormEn, vtNormSt) ;
else {
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormSt, vtNormEn) ;
}
}
}
}
else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) {
if ( ptStart.x < ptEnd.x) {
SurfCircCrown_ZMilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ;
}
else {
SurfCircCrown_ZMilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ;
}
}
}
// se altrimenti arco
else if ( pCurve->GetType() == CRV_ARC) {
// Recupero estremi, centro e raggio
const ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
Point3d ptCen = pArc->GetCenter() ;
double dRadius = pArc->GetRadius() ;
// Determino le posizioni iniziale e finale del centro della sfera
Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ;
Point3d ptCenE = ptCenS + vtMove ;
// Eseguo l'asportazione del materiale
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ;
else if ( pCurve->GetTempProp( 1) == 1) {
double dStH = ptStart.y - ptCen.y ;
double dEnH = ptEnd.y - ptCen.y ;
// Tagliente esterno
if ( dEnH < dStH) {
if ( dEnH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ;
}
else if ( dStH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ;
}
}
// Tagliente interno
else {
if ( dEnH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
else if ( dStH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
}
dSignedHeight = ptStart.y - ptEnd.y ;
}
// aggiorno l'altezza
//dHeight = abs( ptStart.y - ptEnd.y) ;
}
// Determino le posizioni iniziale e finale del componente successivo
ptI = ptI - vtToolDir * dSignedHeight ;
ptF = ptI + vtMove ;
// Passo alla curva successiva del profilo
pCurve = ToolProfile.GetCurve( ++ i) ;
}
return true ;
}
// ---------- VERSORE UTENSILE NEL PIANO XY ----------------------------------
// --------- Cilindro e sfera ------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::CylBall_XYDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile e quota Z del movimento
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
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, 0, 1) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius()) {
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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL)
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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d & vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
double dSafeSqRad = dSqRad - 2 * m_vTool[m_nCurrTool].GetRadius() * EPS_SMALL ;
// Studio simmetrie del problema
Point3d ptI = ( ptS.z <= ptE.z ? ptS : ptE) ;
Point3d ptF = ( ptS.z <= ptE.z ? ptE : ptS) ;
// elimino eventuale piccolo errore di perpendicolarit del movimento rispetto all'utensile
Vector3d vtErr = 0.5 * ( ( ptF - ptI) * vtToolDir) * vtToolDir ;
ptI += vtErr ;
ptF -= vtErr ;
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 dLenXY = vtMove.LenXY() ;
vtMove.Normalize() ;
// Sistema di riferimento ad hoc
Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ;
vtV1.Normalize() ;
Vector3d vtV2 = vtV1 ;
vtV2.Rotate( Z_AX, 0, 1) ;
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, 0, 1) ;
Point3d ptUp = ptI + m_vTool[m_nCurrTool].GetRadius() * ( vtP.z > 0 ? vtP : - vtP) ;
Point3d ptDw = ptI + m_vTool[m_nCurrTool].GetRadius() * ( 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_vTool[m_nCurrTool].GetRadius() * 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 dInfZ, dSupZ ;
if ( dLenXY < EPS_SMALL) {
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius() + EPS_SMALL &&
dP2 < m_vTool[m_nCurrTool].GetRadius() - 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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
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 ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius() && dP2 < dLenXY + m_vTool[m_nCurrTool].GetRadius()) {
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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
if ( ( ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + dP2 * dP2 < dSqRad ||
( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + ( dP2 - dLenXY) * ( dP2 - dLenXY) < dSqRad ||
( dP2 > 0 && dP2 < dLenXY && dP1 < m_vTool[m_nCurrTool].GetHeigth())) && ( 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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
if ( m_vTool[m_nCurrTool].GetType() == Tool::CYLMILL)
return CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, m_vTool[m_nCurrTool].GetHeigth(), m_vTool[m_nCurrTool].GetRadius(), false, false) ;
else if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
double dHei = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, m_vTool[m_nCurrTool].GetRadius(), false, false) ;
CompBall_Milling( nGrid, ptS - dHei * vtToolDir, ptE - dHei * vtToolDir, m_vTool[m_nCurrTool].GetRadius()) ;
return true ;
}
else
return false ;
}
// --------- Coni ------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Conus_XYDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dDeltaRad = dMaxRad - dMinRad ;
// Geometria del moto
double dLenXY = ( ptE - ptS).LenXY() ;
Point3d ptI = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) ;
double dMatStemLen = ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dLenXY : dStemHeigth) ;
double dSqTipRad = m_vTool[m_nCurrTool].GetTipRadius() * m_vTool[m_nCurrTool].GetTipRadius() ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
// Determinazione del vertice del cono
double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ;
Point3d ptV ; // Vertice
Vector3d vtV ; // Vettore riferimento con origine nel vertice
if ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius()) {
vtV = vtToolDir ;
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * ( dStemHeigth + dL) ;
}
else {
vtV = - vtToolDir ;
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ;
}
// Sistema di riferimento sul piano
Vector3d vtV1 = - vtToolDir ;
Vector3d vtV2 = vtV1 ;
vtV2.Rotate( Z_AX, 0, 1) ;
// Proiezione di ptI sul piano
Point3d ptIxy( ptI.x, ptI.y, 0) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius() + ( dX1 - dMatStemLen) * ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) / m_vTool[m_nCurrTool].GetTipHeigth() ;
if ( dX1 > EPS_SMALL && dX1 < dMatStemLen && abs( dX2) < m_vTool[m_nCurrTool].GetRadius()) {
double dH = sqrt( dSqRad - dX2 * dX2) ;
double dMin = ptI.z - dH ;
double dMax = ptI.z + dH ;
Point3d ptIntMin( dX, dY, dMin) ;
Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ;
}
else if ( dX1 >= dMatStemLen &&
dX1 < dMatStemLen + m_vTool[m_nCurrTool].GetTipHeigth() - 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) ;
Vector3d vtUmin = ( ptIntMin - ptV) - ( ptIntMin - ptV) * vtV * vtV ;
vtUmin.Normalize() ;
Vector3d vtNmin = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmin ;
vtNmin.Normalize() ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtUmax = ( ptIntMax - ptV) - ( ptIntMax - ptV) * vtV * vtV ;
vtUmax.Normalize() ;
Vector3d vtNmax = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmax ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
if ( m_vTool[m_nCurrTool].GetTipRadius() >= m_vTool[m_nCurrTool].GetRadius()) {
if ( dX1 > dMatStemLen + m_vTool[m_nCurrTool].GetTipHeigth() - 2 * EPS_SMALL &&
dX1 < dMatStemLen + m_vTool[m_nCurrTool].GetTipHeigth() + 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) ;
Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_XYPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Parametri geometrici dell'utensile
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ;
double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ;
double dDeltaRad = dMaxRad - dMinRad ;
// Studio delle simmetrie del moto
Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ;
Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ;
// elimino eventuale piccolo errore di perpendicolarit del movimento rispetto all'utensile
Vector3d vtErr = 0.5 * ( ( ptF - ptI) * vtToolDir) * vtToolDir ;
ptI += vtErr ;
ptF -= vtErr ;
Point3d ptIxy( ptI.x, ptI.y, 0) ;
Point3d ptFxy( ptF.x, ptF.y, 0) ;
// Cinematica del moto
Vector3d vtMove = ptF - ptI ;
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_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ;
Vector3d vtV = ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? vtToolDir : - vtToolDir) ;
Point3d ptVI = ptI - ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dL : m_vTool[m_nCurrTool].GetHeigth() - dL) * vtToolDir ;
Point3d ptVF = ptF - ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dL : m_vTool[m_nCurrTool].GetHeigth() - dL) * vtToolDir ;
// Movimento verticale
if ( dLengthPathXY < EPS_SMALL) {
// Riferimento sul piano
Vector3d vtV1 = - vtToolDir ;
Vector3d vtV2( - vtV1.y, vtV1.x, 0) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius() + EPS_SMALL && dP2 < m_vTool[m_nCurrTool].GetRadius() - EPS_SMALL) {
double dMin = dZI - sqrt( dSqRad - dP2 * dP2) ;
double dMax = dZF + sqrt( dSqRad - dP2 * dP2) ;
Point3d ptIntMin( dX, dY, dMin) ;
Vector3d vtNmin = - ( ptIntMin - ptI) + ( ptIntMin - ptI) * vtV1 * vtV1 ;
vtNmin.Normalize() ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtNmax = - ( ptIntMax - ptF) + ( ptIntMax - ptF) * vtV1 * vtV1 ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Parte conica
else if ( dP1 > dStemHeigth && dP1 < m_vTool[m_nCurrTool].GetHeigth() - EPS_SMALL && abs( dP2) < m_vTool[m_nCurrTool].GetRadius() +
( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() - EPS_SMALL) {
double dr = dP2 ;
double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ;
double dMin = dZI - sqrt( dMr * dMr - dr * dr) ;
double dMax = dZF + sqrt( dMr * dMr - dr * dr) ;
Point3d ptIntMin( dX, dY, dMin) ;
Vector3d vtUmin = ( ptIntMin - ptVI) - ( ptIntMin - ptVI) * vtV * vtV ;
vtUmin.Normalize() ;
Vector3d vtNmin = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmin ;
vtNmin.Normalize() ;
Point3d ptIntMax( dX, dY, dMax) ;
Vector3d vtUmax = ( ptIntMax - ptVF) - ( ptIntMax - ptVF) * vtV * vtV ;
vtUmax.Normalize() ;
Vector3d vtNmax = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmax ;
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_vTool[m_nCurrTool].GetRadius() * vtCross ;
Point3d ptDw = ptI - vtToolDir * dStemHeigth - m_vTool[m_nCurrTool].GetRadius() * vtCross ;
double dSmallLength = m_vTool[m_nCurrTool].GetRadius() * vtCross.LenXY() ;
// Punti di tangenza in corrispondenza della punta
Point3d ptTipUp = ptI - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() + m_vTool[m_nCurrTool].GetTipRadius() * vtCross ;
Point3d ptTipDw = ptI - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipRadius() * vtCross ;
Vector3d vtUpTan = ptTipUp - ptUp ;
Vector3d vtDwTan = ptTipDw - ptDw ;
Vector3d vtUpTanXY( vtUpTan.x, vtUpTan.y, 0) ;
double dDeltaSmallAbs = abs( vtUpTanXY * vtV2) ;
double dDeltaSmall = ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? 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 ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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_vTool[m_nCurrTool].GetRadius() && dP2 < dLengthPathXY + m_vTool[m_nCurrTool].GetRadius()) {
// 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_vTool[m_nCurrTool].GetHeigth() - EPS_SMALL &&
dP2 > - m_vTool[m_nCurrTool].GetRadius() - ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() &&
dP2 < m_vTool[m_nCurrTool].GetRadius() + dLengthPathXY +
( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) {
// Massimi
if ( dP2 < - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) {
double dr = dP2 ;
double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ;
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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmax.Normalize() ;
}
else if ( dP2 < dLengthPathXY - dSmallLength +
dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) {
dMax = ( dDotUp - dX * vtUpCross.x - dY * vtUpCross.y) / vtUpCross.z ;
vtNmax = vtUpCross ;
}
else {
double dr = dP2 - dLengthPathXY ;
double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ;
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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmax.Normalize() ;
}
// Minimi
if ( dP2 < dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) {
double dr = dP2 ;
double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ;
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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmin.Normalize() ;
}
else if ( dP2 < dLengthPathXY + dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) {
dMin = ( dDotDw - dX * vtDwCross.x - dY * vtDwCross.y) / vtDwCross.z ;
vtNmin = vtDwCross ;
}
else {
double dr = dP2 - dLengthPathXY ;
double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ;
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_vTool[m_nCurrTool].GetTipHeigth() * vtU ;
vtNmin.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_XYMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ;
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
Point3d ptSTip = ptS - dStemHeigth * vtToolDir ;
Point3d ptETip = ptE - dStemHeigth * vtToolDir ;
CompConus_Milling( nGrid, ptSTip, ptETip, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ;
}
else {
Point3d ptSTip = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
Point3d ptETip = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
CompConus_Milling( nGrid, ptSTip, ptETip, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ;
}
return true ;
}
// ---------- VERSORE UTENSILE CON ORIENTAZIONE GENERICA ---------------------
// ---------- Cilindro e sfera -----------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::CylBall_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Altezza cilindro
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
// Sottraggo cilindro
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, false) ;
// Se sfera la sottraggo
if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
CompBall_Milling( nGrid, ptSBall, ptEBall, m_vTool[m_nCurrTool].GetRadius()) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CylBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
// Altezza cilindro
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
// Sottraggo cilindro
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, false) ;
// Se sfera la sottraggo
if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) {
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
CompBall_Milling( nGrid, ptSBall, ptEBall, m_vTool[m_nCurrTool].GetRadius()) ;
}
return true ;
}
// ---------- Coni -----------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ;
// Trapano
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
Point3d ptSCone = ptS - dStemHeigth * vtToolDir ;
Point3d ptECone = ptE - dStemHeigth * vtToolDir ;
CompConus_Drilling( nGrid, ptSCone, ptECone, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ;
}
else {
Point3d ptSCone = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
Point3d ptECone = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
CompConus_Drilling( nGrid, ptSCone, ptECone, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
{
double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ;
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ;
// Trapano
if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) {
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
CompConus_Milling( nGrid, ptSBall, ptEBall, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(),
m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ;
}
else {
Point3d ptSBall = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
Point3d ptEBall = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ;
CompConus_Milling( nGrid, ptSBall, ptEBall, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(),
m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ;
}
return true ;
}
// ---------- Mortasatrice ---------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Proiezione della traiettoria sul piano dei movimenti possibili
Point3d ptEOnP = ptS + ( ptE - ptS) * vtToolDir * vtToolDir ;
// Scompongo la mortasatrice in solidi semplici
// Parallelepipedo di base
double dLenX = m_vTool[m_nCurrTool].GetMrtChsWidth() ;
double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ;
double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ;
CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ;
// Se la punta di tipo bull-nose
if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) {
// Parallelepipedo di punta
Point3d ptTipS = ptS - dLenZ * vtToolDir ;
Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ;
dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ;
dLenZ = m_vTool[m_nCurrTool].GetCornRadius() ;
CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux) ;
Vector3d vtVOnP = vtToolDir ^ vtAux ;
// Cilindri
Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ;
CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
// se la punta di tipo sfera
else {
// Cilindro
Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
Point3d ptCylE = ptEOnP - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Scompongo la mortasatrice in solidi semplici
// Parallelepipedo di base
double dLenX = m_vTool[m_nCurrTool].GetMrtChsWidth() ;
double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ;
double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ;
Point3d ptBasePS = ptS - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
Point3d ptBasePE = ptE - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ;
CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptBasePS, ptBasePE, vtAux, vtToolDir) ;
// Se la punta di tipo bull-nose
if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) {
// Parallelepipedo di punta
Point3d ptTipPS = ptBasePS - 0.5 * dLenZ * vtToolDir ;
Point3d ptTipPE = ptBasePE - 0.5 * dLenZ * vtToolDir ;
dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ;
dLenZ = m_vTool[m_nCurrTool].GetCornRadius() ;
ptTipPS -= 0.5 * dLenZ * vtToolDir ;
ptTipPE -= 0.5 * dLenZ * vtToolDir ;
CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptTipPS, ptTipPE, vtAux, vtToolDir) ;
// Cilindri
// Vettore nel piano
Vector3d vtVOnP = vtToolDir ^ vtAux ;
if ( vtVOnP * ( ptE - ptS) < 0)
vtVOnP *= -1 ;
Point3d ptSminus = ptTipPS + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ;
Point3d ptEminus = ptTipPE + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ;
CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
Point3d ptSplus = ptTipPS + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ;
Point3d ptEplus = ptTipPE + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ;
CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
// se la punta di tipo sfera
else {
// Cilindro
Point3d ptCylS = ptBasePS - 0.5 * dLenZ * vtToolDir ;
Point3d ptCylE = ptBasePE - 0.5 * dLenZ * vtToolDir ;
CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ;
}
return true ;
}
// ---------- Chisel ---------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Proiezione della traiettoria sulla variet del movimento
Point3d ptProjE = ptS + ( ptE - ptS) * vtToolDir * vtToolDir ;
CompPar_Drilling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
{
// Proiezione della traiettoria sul piano dei movimenti possibili
Vector3d vtMoveOnP = ( ptE - ptS) - ( ptE - ptS) * vtToolDir * vtToolDir ;
Point3d ptProjE = ptS + vtMoveOnP ;
CompPar_Milling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ;
return true ;
}
// ---------- Utensile generico ----------------------------------------------
//----------------------------------------------------------------------------
//bool
//VolZmap::GenTool_Drilling( 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 ;
// // Vettore delle normali agli archi
// const VCT3DVECTOR& vArcNorm = m_Tool.GetArcNormalVec() ;
// // Poinch l'asse utensile parallelo all'asse Z, definisco un sistema di
// // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ.
// Frame3d frNormFrame ;
// frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ;
// // Ciclo sulle curve del profilo
// const CurveComposite& ToolProfile = m_Tool.GetApproxOutline() ;
// int i = - 1 ;
// const ICurve* pPrevCurve = nullptr ;
// const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ;
// while ( pCurve != nullptr) {
//
// double dHeight = 0 ;
//
// // Se segmento
// if ( pCurve->GetType() == CRV_LINE) {
// // Recupero gli estremi
// const ICurveLine* pLine = GetCurveLine( pCurve) ;
// Point3d ptStart = pLine->GetStart() ;
// Point3d ptEnd = pLine->GetEnd() ;
// int nNormNum = pLine->GetTempProp();
// Vector3d vtNormSt, vtNormEn;
// if ( nNormNum != 0) {
// vtNormSt = vArcNorm[nNormNum - 1] ;
// vtNormEn = vArcNorm[nNormNum] ;
// vtNormSt.ToLoc(frNormFrame);
// vtNormEn.ToLoc(frNormFrame);
// }
// // Ne determino l'altezza
// dHeight = abs( ptStart.y - ptEnd.y) ;
// if ( dHeight > EPS_SMALL) {
// // Verifiche curva precedente per eventuale tappo sopra
// bool bTapT = false ;
// if ( pPrevCurve != nullptr && pPrevCurve->GetType() == CRV_LINE) {
// const ICurveLine* pOthLine = GetCurveLine( pPrevCurve) ;
// Point3d ptOthStart = pOthLine->GetStart() ;
// Point3d ptOthEnd = pOthLine->GetEnd() ;
// if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x < ptOthEnd.x)
// bTapT = true ;
// }
// // Verifiche curva successiva per eventuale tappo sotto
// bool bTapB = false ;
// const ICurve* pNextCurve = ToolProfile.GetCurve( ++ i) ;
// if ( pNextCurve != nullptr && pNextCurve->GetType() == CRV_LINE) {
// const ICurveLine* pOthLine = GetCurveLine( pNextCurve) ;
// Point3d ptOthStart = pOthLine->GetStart() ;
// Point3d ptOthEnd = pOthLine->GetEnd() ;
// if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x > ptOthEnd.x)
// bTapB = true ;
// }
// // Se X costante, un cilindro
// if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
// double dRadius = ptStart.x ;
// if ( dRadius > 10 * EPS_SMALL)
// CompCyl_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ;
// }
// // Se X crescente, 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, vtNormSt, vtNormEn) ;
// }
// // Se X decrescente, 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 ;
// vtNormEn.z *= -1 ;
// vtNormSt.z *= -1 ;
// CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ;
// }
// // Passo alla curva successiva
// pPrevCurve = pCurve ;
// pCurve = pNextCurve ;
// }
// else {
// // Passo alla curva successiva
// pPrevCurve = pCurve ;
// pCurve = ToolProfile.GetCurve( ++ i) ;
// }
// }
//
// // Se arco
// else if ( pCurve->GetType() == CRV_ARC) {
// // Recupero estremi, centro e raggio
// const ICurveArc* pArc = GetCurveArc( pCurve) ;
// Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
// Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
// Point3d ptCen = pArc->GetCenter() ;
// double dRadius = pArc->GetRadius() ;
// // Determino le posizioni iniziale e finale del centro della sfera
// Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ;
// Point3d ptCenE = ptCenS + vtMove ;
// // Eseguo l'asportazione del materiale
// CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ;
// // aggiorno l'altezza
// dHeight = abs( ptStart.y - ptEnd.y) ;
// // Passo alla curva successiva
// pPrevCurve = pCurve ;
// pCurve = ToolProfile.GetCurve( ++ i) ;
// }
//
// // Determino le posizioni iniziale e finale del componente successivo
// ptI = ptI - vtToolDir * dHeight ;
// ptF = ptI + vtMove ;
// }
//
// return true ;
//}
bool
VolZmap::GenTool_Drilling( 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 ;
// Vettore delle normali agli archi
const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ;
// Poinch l'asse utensile parallelo all'asse Z, definisco un sistema di
// riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ.
Frame3d frNormFrame ;
frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ;
// Ciclo sulle curve del profilo
const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ;
int i = - 1 ;
const ICurve* pPrevCurve = nullptr ;
const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ;
while ( pCurve != nullptr) {
double dHeight = 0 ;
double dSignedHeight = 0 ;
// Se segmento
if ( pCurve->GetType() == CRV_LINE) {
// Recupero gli estremi
const ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptStart = pLine->GetStart() ;
Point3d ptEnd = pLine->GetEnd() ;
int nNormNum = pLine->GetTempProp();
Vector3d vtNormSt, vtNormEn;
if ( nNormNum != 0) {
vtNormSt = vArcNorm[nNormNum - 1] ;
vtNormEn = vArcNorm[nNormNum] ;
vtNormSt.ToLoc(frNormFrame);
vtNormEn.ToLoc(frNormFrame);
}
// Ne determino l'altezza
dSignedHeight = ptStart.y - ptEnd.y ;
dHeight = abs( dSignedHeight) ;
if ( dHeight > EPS_SMALL) {
// Verifiche curva precedente per eventuale tappo sopra
bool bTapT = false ;
if ( pPrevCurve != nullptr && pPrevCurve->GetType() == CRV_LINE) {
const ICurveLine* pOthLine = GetCurveLine( pPrevCurve) ;
Point3d ptOthStart = pOthLine->GetStart() ;
Point3d ptOthEnd = pOthLine->GetEnd() ;
if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x < ptOthEnd.x)
bTapT = true ;
}
// Verifiche curva successiva per eventuale tappo sotto
bool bTapB = false ;
int j = i ;
const ICurve* pNextCurve = ToolProfile.GetCurve( ++ j) ;
if ( pNextCurve != nullptr && pNextCurve->GetType() == CRV_LINE) {
const ICurveLine* pOthLine = GetCurveLine( pNextCurve) ;
Point3d ptOthStart = pOthLine->GetStart() ;
Point3d ptOthEnd = pOthLine->GetEnd() ;
if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x > ptOthEnd.x)
bTapB = true ;
}
// Se X costante, un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
if ( dRadius > 10 * EPS_SMALL && m_vTool[m_nCurrTool].GetCuttingFlag())
CompCyl_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ;
}
// Se X crescente, un cono con vettore equiverso a quello dell'utensile
else if ( ptStart.x > ptEnd.x) {
double dMaxRad = ptStart.x ;
double dMinRad = ptEnd.x ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT, vtNormSt, vtNormEn) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapB, bTapT, vtNormSt, vtNormEn) ;
else {
Point3d ptIn = ptI /*- vtToolDir * dSignedHeight*/ ;
Point3d ptFn = ptIn + vtMove ;
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapT, bTapB, vtNormEn, vtNormSt) ;
}
}
}
// Se X decrescente, 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 * dSignedHeight ;
Point3d ptFn = ptIn + vtMove ;
vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapT, bTapB, vtNormEn, vtNormSt) ;
else {
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapB, bTapT, vtNormSt, vtNormEn) ;
}
}
}
}
else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) {
if ( ptStart.x < ptEnd.x) {
SurfCircCrown_Drilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ;
}
else {
SurfCircCrown_Drilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ;
}
}
}
// Se arco
else if ( pCurve->GetType() == CRV_ARC) {
// Recupero estremi, centro e raggio
const ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
Point3d ptCen = pArc->GetCenter() ;
double dRadius = pArc->GetRadius() ;
// Determino le posizioni iniziale e finale del centro della sfera
Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ;
Point3d ptCenE = ptCenS + vtMove ;
// Eseguo l'asportazione del materiale
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ;
else if ( pCurve->GetTempProp( 1) == 1) {
double dStH = ptStart.y - ptCen.y ;
double dEnH = ptEnd.y - ptCen.y ;
// Tagliente esterno
if ( dEnH < dStH) {
if ( dEnH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ;
}
else if ( dStH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ;
}
}
// Tagliente interno
else {
if ( dEnH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
else if ( dStH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
}
dSignedHeight = ptStart.y - ptEnd.y ;
}
// aggiorno l'altezza
//dHeight = abs( ptStart.y - ptEnd.y) ;
}
// Determino le posizioni iniziale e finale del componente successivo
ptI = ptI - vtToolDir * dSignedHeight ;
ptF = ptI + vtMove ;
// Passo alla curva successiva
pPrevCurve = pCurve ;
pCurve = ToolProfile.GetCurve( ++ i) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GenTool_Milling( 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 ;
// Vettore delle normali agli archi
const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ;
// Poinch l'asse utensile parallelo all'asse Z, definisco un sistema di
// riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ.
Frame3d frNormFrame ;
frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ;
// Ciclo sulle curve del profilo
const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ;
int i = - 1 ;
const ICurve* pPrevCurve = nullptr ;
const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ;
while ( pCurve != nullptr) {
double dHeight = 0 ;
double dSignedHeight = 0 ;
// Se segmento
if ( pCurve->GetType() == CRV_LINE) {
// Recupero gli estremi
const ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptStart = pLine->GetStart() ;
Point3d ptEnd = pLine->GetEnd() ;
int nNormNum = pLine->GetTempProp();
Vector3d vtNormSt, vtNormEn;
if ( nNormNum != 0) {
vtNormSt = vArcNorm[nNormNum - 1] ;
vtNormEn = vArcNorm[nNormNum] ;
vtNormSt.ToLoc(frNormFrame);
vtNormEn.ToLoc(frNormFrame);
}
// Ne determino l'altezza
dSignedHeight = ptStart.y - ptEnd.y ;
dHeight = abs( dSignedHeight) ;
if ( dHeight > EPS_SMALL) {
// verifiche curva precedente per eventuale tappo sopra
bool bTapT = true ;
if ( pPrevCurve != nullptr && pPrevCurve->GetType() == CRV_LINE) {
const ICurveLine* pOthLine = GetCurveLine( pPrevCurve) ;
Point3d ptOthStart = pOthLine->GetStart() ;
Point3d ptOthEnd = pOthLine->GetEnd() ;
if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x < ptOthEnd.x)
bTapT = false ;
}
// verifiche curva successiva per eventuale tappo sotto
bool bTapB = false ;
int j = i ;
const ICurve* pNextCurve = ToolProfile.GetCurve( ++ j) ;
if ( pNextCurve != nullptr && pNextCurve->GetType() == CRV_LINE) {
const ICurveLine* pOthLine = GetCurveLine( pNextCurve) ;
Point3d ptOthStart = pOthLine->GetStart() ;
Point3d ptOthEnd = pOthLine->GetEnd() ;
if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x > ptOthEnd.x)
bTapB = false ;
}
// Se X costante, un cilindro
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
if ( dRadius > 10 * EPS_SMALL) {
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, true, bTapB, bTapT) ;
else
SurfCyl_Milling( nGrid, ptI, ptF, - vtToolDir, dHeight, dRadius, false, bTapB, bTapT) ;
}
}
}
// Se X crescente, un cono con vettore equiverso a quello dell'utensile
else if ( ptStart.x > ptEnd.x) {
double dMaxRad = ptStart.x ;
double dMinRad = ptEnd.x ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT, vtNormSt, vtNormEn) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapB, bTapT, vtNormSt, vtNormEn) ;
else {
Point3d ptIn = ptI /*- vtToolDir * dSignedHeight*/ ;
Point3d ptFn = ptIn + vtMove ;
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapT, bTapB, vtNormEn, vtNormSt) ;
}
}
}
// Se X decrescente, 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 * dSignedHeight ;
Point3d ptFn = ptIn + vtMove ;
vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ;
else if ( pCurve->GetTempProp( 1) == 1) {
if ( ptStart.y > ptEnd.y)
SurfConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapT, bTapB, vtNormEn, vtNormSt) ;
else {
/*vtNormEn.z *= -1 ;
vtNormSt.z *= -1 ;*/
SurfConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapB, bTapT, vtNormSt, vtNormEn) ;
}
}
}
}
else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) {
if ( ptStart.x < ptEnd.x) {
SurfCircCrown_Milling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ;
}
else {
SurfCircCrown_Milling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ;
}
}
}
// Se arco
else if ( pCurve->GetType() == CRV_ARC) {
// Recupero estremi, centro e raggio
const ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
Point3d ptCen = pArc->GetCenter() ;
double dRadius = pArc->GetRadius() ;
// Determino le posizioni iniziale e finale del centro della sfera
Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ;
Point3d ptCenE = ptCenS + vtMove ;
// Eseguo l'asportazione del materiale
if ( m_vTool[m_nCurrTool].GetCuttingFlag())
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ;
else if ( pCurve->GetTempProp( 1) == 1) {
double dStH = ptStart.y - ptCen.y ;
double dEnH = ptEnd.y - ptCen.y ;
// Tagliente esterno
if ( dEnH < dStH) {
if ( dEnH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ;
}
else if ( dStH > 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ;
}
}
// Tagliente interno
else {
if ( dEnH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
else if ( dStH < 0) {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ;
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ;
}
else {
SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ;
}
}
dSignedHeight = ptStart.y - ptEnd.y ;
}
// aggiorno l'altezza
//dHeight = abs( ptStart.y - ptEnd.y) ;
}
// Determino le posizioni iniziale e finale del componente successivo
ptI = ptI - vtToolDir * dSignedHeight ;
ptF = ptI + vtMove ;
// Passo alla curva successiva
pPrevCurve = pCurve ;
pCurve = ToolProfile.GetCurve( ++ i) ;
}
return true ;
}
// ------------------------- SOLIDI ELEMENTARI -----------------------------------------------------------------------------
// Asse di simmetria diretto come l'asse Z: FORATURA
//----------------------------------------------------------------------------
bool
VolZmap::CompCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad)
{
// Verifica sull'interferenza con lo Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Proiezione dei punti sul piano
Point3d ptSxy( ptS.x, ptS.y, 0) ;
// Parametri geometrici dell'utensile
double dSafeSqRad = dRad * dRad - 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( ptE.z, ptTStemE.z)) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 < dSafeSqRad)
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, -Z_AX) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
// Verifica sull'interferenza con lo Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
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 dSafeSqMaxRad = dSqMaxRad - 2 * dMaxRad * EPS_SMALL ; // Questa variabile sperimentale: serve per evitare il taglio di un dexel dalla parte cilindrica del volume spazzato dalla traslazione del cono.
double dDeltaR = dMaxRad - dMinRad ; // Per tornare alla versione precedente basta sostituire dSafeSqMaxRad con dSqMaxRad. Per risolvere il problema in modo forse pi sicuro, ma
// computazionalmente pi pesante sottrarre prima il cilindro con dSafeSqMaxRad e dopo il cono con dSqMaxRad.
// 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 ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 < dSafeSqMaxRad) { // dSafeSqMaxRad sperimentale
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() ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtMin = dDeltaR * vtToolDir - dHei * vtU ;
vtMin.Normalize() ;
}
else {
Vector3d vtOriginalN = ( ( dDeltaR - dr + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dr - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN.Normalize() ;
vtMin = - vtOriginalN.z * vtToolDir - vtOriginalN.x * 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() ;
if ( vtArcNormMinR.IsSmall() || vtArcNormMaxR.IsSmall()) {
vtMax = dDeltaR * vtToolDir - dHei * vtU ;
vtMax.Normalize() ;
}
else {
Vector3d vtOriginalN = ( ( dDeltaR - dr + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dr - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN.Normalize() ;
vtMax = - vtOriginalN.z * vtToolDir - vtOriginalN.x * vtU ;
vtMax.Normalize() ;
}
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompPar_ZDrilling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux)
{
Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ;
Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ;
dLenX -= ( 2 * EPS_SMALL) ;
dLenY -= ( 2 * EPS_SMALL) ;
dLenZ -= ( 2 * EPS_SMALL) ;
// Controllo sull'interferenza utensile-solido
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Costruisco un sistema di riferimento nel piano
Point3d ptOXY( ptMyS.x, ptMyS.y, 0) ;
Vector3d vtV1 = vtToolDir ^ vtAux ;
Vector3d vtV2 = vtAux ;
// Quote estreme del volume asportato
double dMinZ = min( min( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), min( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ;
double dMaxZ = max( max( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), max( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 vtR = ptC - ptOXY ;
double dR1 = vtR * vtV1 ;
double dR2 = vtR * vtV2 ;
if ( abs( dR1) < 0.5 * dLenX && abs( dR2) < 0.5 * dLenY)
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ;
}
}
return true ;
}
// Asse di simmetria diretto come l'asse Z: FRESATURA
//----------------------------------------------------------------------------
bool
VolZmap::CompCyl_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad)
{
// Verifica sull'interferenza con lo Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
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 dDeltaZ = dZMaxF - dZMaxI ;
// Vettori caratterizzanti il moto
Vector3d vtMove = ptF - ptI ;
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
double dLenXY = vtMoveXY.LenXY() ;
vtMove.Normalize() ;
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, 0, 1) ;
double dMin, dMax ;
Vector3d vtMin, vtMax ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ;
Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ;
Point3d ptIxy( ptI.x, ptI.y, 0) ;
Point3d ptFxy( ptF.x, ptF.y, 0) ;
Vector3d vtMove = ptF - ptI ;
Vector3d vtMLong = ( vtMove * vtToolDir) * vtToolDir ;
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) ;
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 = 0, dMax = 0, dPLim = 0, dMLim = 0 ;
Vector3d vtMin, vtMax, vtP, vtM ;
Vector3d vtUmv = vtMove ;
vtUmv.Normalize() ;
Point3d ptInt ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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) ;
vtCI.Normalize() ;
vtCF.Normalize() ;
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() ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
else {
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCI - vtArcNormMaxR.z * vtV1 ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCI - vtArcNormMinR.z * vtV1 ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtM = ( ( dDeltaR - sqrt( dSqDI) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt(dSqDI) - dMinRad) / dDeltaR) * vtOrigMaxR ;
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() ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
else {
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCI - vtArcNormMaxR.z * vtV1 ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCI - vtArcNormMinR.z * vtV1 ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtM = ( ( dDeltaR - sqrt( dSqDI) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt( dSqDI) - dMinRad) / dDeltaR) * vtOrigMaxR ;
vtM.Normalize() ;
}
}
else if ( dSqDI >= dMinRad * dMinRad && dIVarCos >= dCos && dFVarCos < dCos && abs( dIDO) < dMaxRad * dSin) {
if ( dIDO > - dMaxRad * dSin && dIDO <= - dMinRad * dSin) {
dMLim = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtM = - vtNd ;
}
else {
double dLatMin = dMinRad * dSin ;
double dDeltaLat = dDeltaR * dSin ;
Vector3d vtRadial = dCos * vtV2 - dSin * vtV3 ;
vtRadial.Normalize() ;
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * vtV1 ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * vtV1 ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtM = ( ( dDeltaLat - abs( dIDO) + dLatMin) / dDeltaLat) * vtOrigMinR + ( ( abs( dIDO) - dLatMin) / dDeltaLat) * vtOrigMaxR ;
vtM.Normalize() ;
}
}
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 ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtM = - vtNs ;
}
else {
double dLatMin = dMinRad * dSin ;
double dDeltaLat = dDeltaR * dSin ;
Vector3d vtRadial = dCos * vtV2 + dSin * vtV3 ;
vtRadial.Normalize() ;
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * vtV1 ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * vtV1 ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtM = ( ( dDeltaLat - dIDO + dLatMin) / dDeltaLat) * vtOrigMinR + ( ( dIDO - dLatMin) / dDeltaLat) * vtOrigMaxR ;
vtM.Normalize() ;
}
}
}
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() ;
if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) {
vtM = dDeltaR * vtToolDir - dHei * vtU ;
vtM.Normalize() ;
}
else {
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCF - vtArcNormMaxR.z * vtV1 ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCF - vtArcNormMinR.z * vtV1 ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtM = ( ( dDeltaR - sqrt( dSqDF) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt( dSqDF) - dMinRad) / dDeltaR) * vtOrigMaxR ;
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() ;
}
}
}
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 ;
}
//----------------------------------------------------------------------------
bool // E' in realt MillingPerp
VolZmap::CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux)
{
Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ;
Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ;
dLenX -= ( 2 * EPS_SMALL) ;
dLenY -= ( 2 * EPS_SMALL) ;
dLenZ -= ( 2 * EPS_SMALL) ;
// Controllo sull'interferenza utensile-solido
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Quote estreme Z
double dMinZ = min( min( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), min( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ;
double dMaxZ = max( max( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), max( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ;
// Vettore di movimento
Vector3d vtMove = ptMyE - ptMyS ;
// Sistemi di riferimento del solido nella posizione iniziale e finale
Vector3d vtV2 = vtAux ;
Vector3d vtV1 = vtV2 ^ vtToolDir ;
vtV1.Normalize() ;
Point3d ptSXY( ptMyS.x, ptMyS.y, 0) ;
Point3d ptEXY( ptMyE.x, ptMyE.y, 0) ;
// Studio del volume asportato durante il moto
Frame3d MotionFrame ;
Vector3d vtDiagA = dLenX * vtV1 + dLenY * vtV2 ;
Vector3d vtDiagB = dLenX * vtV1 - dLenY * vtV2 ;
Vector3d vtW1 = ( abs( vtDiagA * vtMove) <= abs( vtDiagB * vtMove) ? vtDiagA : vtDiagB) ;
Point3d ptOrigXY = ptSXY - vtW1 / 2 ;
double dLenW1 = vtW1.Len() ;
vtW1 /= dLenW1 ;
double dDeltaW1 = vtMove * vtW1 ;
Vector3d vtW2 = vtMove - dDeltaW1 * vtW1 ;
double dLenW2 = vtW2.Len() ;
vtW2 /= dLenW2 ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 vtRS = ptC - ptSXY ;
Vector3d vtRE = ptC - ptEXY ;
double dRS1 = vtRS * vtV1 ;
double dRS2 = vtRS * vtV2 ;
double dRE1 = vtRE * vtV1 ;
double dRE2 = vtRE * vtV2 ;
// Asportazione materiale nella posizione iniziale
if ( abs( dRS1) < 0.5 * dLenX && abs( dRS2) < 0.5 * dLenY)
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ;
// Asportazione materiale nella posizione finale
if ( abs( dRE1) < 0.5 * dLenX && abs( dRE2) < 0.5 * dLenY)
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ;
// Asportazione materiale nel moto
Vector3d vtR = ptC - ptOrigXY ;
double dR1 = vtR * vtW1 ;
double dR2 = vtR * vtW2 ;
if ( dR2 > 0 && dR2 < dLenW2 &&
dR1 * dLenW2 > dDeltaW1 * dR2 &&
dR1 * dLenW2 < dLenW1 * dLenW2 + dDeltaW1 * dR2)
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ;
}
}
return true ;
}
// Asse di simmetria con orientazione generica: FORATURA
//----------------------------------------------------------------------------
bool
VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT)
{
// Verifico che il cilindro con il suo movimento intersechi la griglia
int nStartI, nEndI, nStartJ, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
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) ;
// Altezza cilindro totale altezza + moto
double dH = ( ptF - ptI).Len() ;
// Sistema di riferimento del cilindro
Frame3d CylFrame ; CylFrame.Set( ptF, vtToolDir) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Apertura del cono
double dDeltaR = dMaxRad - dMinRad ;
double dTan = dDeltaR / dHei ;
double dConeMaxH = ( ( dMaxRad * dHei) / dDeltaR) ;
double dConeMinH = dConeMaxH - dHei ;
Point3d ptVertex = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) - vtToolDir * dConeMaxH ;
// Sistemi di riferimento del cono e del cilindro
Frame3d ConusFrame ; ConusFrame.Set( ptVertex, vtToolDir) ;
Frame3d CylFrame = ConusFrame ; CylFrame.Translate( vtToolDir * dConeMaxH) ;
// L'altezza del cilindro il movimento
double dH = ( ptE - ptS).Len() ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Cono
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dConeMinH, dConeMaxH, bTapB, true,
ptInt1, vtN1, ptInt2, vtN2)) {
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
if ( ! AreSameOrOppositeVectorEpsilon(vtN1, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL1 = ptInt1 - ptVertex ;
vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ;
double dL1 = vtL1.Len() ;
vtL1 /= dL1 ;
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN1.Normalize() ;
vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ;
}
if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL2 = ptInt2 - ptVertex ;
vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ;
double dL2 = vtL2.Len() ;
vtL2 /= dL2 ;
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN2.Normalize() ;
vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ;
}
}
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompPar_Drilling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux)
{
Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ;
Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ;
dLenX -= ( 2 * EPS_SMALL) ;
dLenY -= ( 2 * EPS_SMALL) ;
dLenZ -= ( 2 * EPS_SMALL) ;
// Controllo sull'interferenza utensile-solido
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Costruzione di un sistema di riferimento per il volume
// asportato dal solido nelle posizioni iniziale e finale.
Vector3d vtV1 = vtToolDir ;
Vector3d vtV2 = vtAux ^ vtV1 ;
Vector3d vtV3 = vtAux ;
double dLenMove = ( ptMyE - ptMyS).Len() ;
Point3d ptO = ptMyS - ( ( ptMyE - ptMyS) * vtV1 > 0 ? dLenZ : dLenZ + dLenMove) * vtV1 - ( 0.5 * dLenX) * vtV2 ;
Frame3d ParaFrame ; ParaFrame.Set( ptO, vtV2, vtV3, vtV1) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ + dLenMove, 0, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
// Asse di simmetria con orientazione generica: FRESATURA
//----------------------------------------------------------------------------
bool
VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, double dHei, double dRad, bool bTapB, bool bTapT)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
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 ;
// 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, vtV2, vtV3, vtV1) ;
// Parametri geometrici di moto e cilindro
double dLongLen = vtMoveLong.Len() ;
double dOrtLen = vtMoveOrt.Len() ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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
CylFrame.ChangeOrig( ptITip) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// 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.
CylFrame.ChangeOrig( ptITip + vtMove) ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Poliedro interno
CylFrame.ChangeOrig( ptITip) ;
if ( IntersLineMyPolyhedron( ptC, Z_AX, CylFrame, dOrtLen, 2 * dRad, dHei,
dLongLen, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Se movimento non ortogonale all'asse cilindro ellittico di punta
if ( dLongLen > EPS_SMALL) {
CylFrame.ChangeOrig( ptITip) ;
if ( IntersLineEllipticalCylinder( ptC, Z_AX, CylFrame, dRad, dLongLen, dOrtLen,
bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// 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.
CylFrame.ChangeOrig( ptITip + dHei * vtV1) ;
if ( IntersLineEllipticalCylinder( ptC, Z_AX, CylFrame, dRad, dLongLen, dOrtLen,
true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
// Verifico interferenza
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Geometria del cono
double dDeltaR = dMaxRad - dMinRad ;
// Studio simmetrie
Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ;
Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ;
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, vtV2, vtV3, vtV1) ;
// 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) ;
// 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 ( riferiti al sistema di riferimento) :
// Sx, Dx
Vector3d vtNs( - dTan, dCos, dSin) ;
vtNs.Normalize() ;
Vector3d vtNd( - dTan, dCos, - dSin) ;
vtNd.Normalize() ;
// Iniziale e finale
Vector3d vtIF( - dDeltaY, dDeltaX, 0) ;
vtIF.Normalize() ;
// Up e Down
Vector3d vtUD( - dLenY, dLenX, 0) ;
vtUD.Normalize() ;
// Punti dei piani (sempre espressi nel sistema PolyFrame)
Point3d ptFacet135( 0, 0, dLenZ) ;
Point3d ptFacet246( dLenX + dDeltaX, dLenY + dDeltaY, - dLenZ - dDeltaZ) ;
Vector3d vtUmv = vtMove ; vtUmv.Normalize() ;
if ( dRatio * dTan <= 1) {
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 ;
// Cono iniziale
ConusFrame.ChangeOrig( ptV) ;
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL1 = ptInt1 - ptV ;
vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ;
double dL1 = vtL1.Len() ;
vtL1 /= dL1 ;
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR;
vtOriginalN1.Normalize() ;
vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ;
vtN1.Normalize() ;
}
if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL2 = ptInt2 - ptV ;
vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ;
double dL2 = vtL2.Len() ;
vtL2 /= dL2 ;
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN2.Normalize() ;
vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ;
vtN2.Normalize() ;
}
}
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Cono finale
ConusFrame.ChangeOrig( ptV + vtMove) ;
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL1 = ptInt1 - ptV - vtMove ;
vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ;
double dL1 = vtL1.Len() ;
vtL1 /= dL1 ;
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN1.Normalize() ;
vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ;
vtN1.Normalize() ;
}
if ( ! AreSameOrOppositeVectorEpsilon(vtN2, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL2 = ptInt2 - ptV - vtMove ;
vtL2 -= (vtL2 * vtToolDir) * vtToolDir;
double dL2 = vtL2.Len() ;
vtL2 /= dL2 ;
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN2.Normalize() ;
vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ;
vtN2.Normalize() ;
}
}
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// 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 ;
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
Vector3d vtRadial( 0, dMinRad * dCos, dMinRad * dSin) ;
vtRadial.Normalize() ;
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtN1 = ( ( dDeltaZ - ptInt1.z + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( ptInt1.z - dLenZ) / dDeltaZ) * vtOrigMaxR ;
vtN1.Normalize() ;
}
++ 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 ;
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
Vector3d vtRadial( 0, dMinRad * dCos, - dMinRad * dSin) ;
vtRadial.Normalize() ;
Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ;
Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtN1 = ( ( dDeltaZ - abs( ptInt1.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt1.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ;
vtN1.Normalize() ;
}
++ nIntNum ;
}
else if ( ( ptInt1 - ptPoly2).SqLen() > SQ_EPS_SMALL) {
ptInt2 = ptPoly2 ;
vtN2 = - vtNd ;
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
Vector3d vtRadial( 0, dMinRad * dCos, -dMinRad * dSin) ;
vtRadial.Normalize() ;
Vector3d vtOrigMaxR = -vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ;
Vector3d vtOrigMinR = -vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ;
vtOrigMaxR.Normalize() ;
vtOrigMinR.Normalize() ;
vtN2 = ( ( dDeltaZ - abs( ptInt2.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt2.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ;
vtN2.Normalize() ;
}
++ 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() > SQ_EPS_SMALL) {
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() > SQ_EPS_SMALL) {
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() > SQ_EPS_SMALL) {
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() > SQ_EPS_SMALL) {
ptInt2 = ptPoly6;
vtN2 = vtUD ;
++ nIntNum ;
}
}
}
// Se il poliedro attraversato taglio
if ( nIntNum == 2) {
// Riporto le intersezioni nel sistema griglia
ptInt1.ToGlob( PolyFrame) ;
vtN1.ToGlob( PolyFrame) ;
ptInt2.ToGlob( PolyFrame) ;
vtN2.ToGlob( PolyFrame) ;
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Se movimento non ortogonale all'asse sottraggo i cilindri ellittici
if ( dLongLen > EPS_SMALL) {
// Traslazione ellisse di punta
ConusFrame.ChangeOrig( ptV + vtV1 * dl) ;
if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMinRad, dLongLen, dOrtLen,
bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Traslazione ellisse di base
ConusFrame.ChangeOrig( ptV + vtV1 * dL) ;
if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMaxRad, dLongLen, dOrtLen,
true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
}
return true ;
}
else {
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 ;
// Cono
ConusFrame.ChangeOrig( ptV) ;
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) {
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL1 = ptInt1 - ptV ;
vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ;
double dL1 = vtL1.Len() ;
vtL1 /= dL1 ;
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN1.Normalize() ;
vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ;
vtN1.Normalize() ;
}
if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) {
Vector3d vtL2 = ptInt2 - ptV ;
vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ;
double dL2 = vtL2.Len() ;
vtL2 /= dL2 ;
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
vtOriginalN2.Normalize() ;
vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ;
vtN2.Normalize() ;
}
}
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Traslazione ellisse
ConusFrame.ChangeOrig( ptV + vtV1 * dL) ;
if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMaxRad, dLongLen, dOrtLen,
true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
}
//----------------------------------------------------------------------------
bool
VolZmap::CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, const Vector3d& vtAux)
{
Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ;
Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ;
dLenX -= ( 2 * EPS_SMALL) ;
dLenY -= ( 2 * EPS_SMALL) ;
dLenZ -= ( 2 * EPS_SMALL) ;
// Controllo sull'interferenza utensile-solido
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore di movimento
Vector3d vtMove = ptMyE - ptMyS ;
// Sistema di riferimento del solido nella posizione iniziale (con vtMove derivo quello finale)
Frame3d ParaFrame ;
Vector3d vtV3 = vtToolDir ;
Vector3d vtV1 = vtAux ^ vtV3 ;
Vector3d vtV2 = vtV3 ^ vtV1 ;
ParaFrame.Set( ORIG, vtV1, vtV2, vtV3) ;
Point3d ptV = ptMyS - dLenZ * ParaFrame.VersZ() - ( 0.5 * dLenX) * ParaFrame.VersX() ;
ParaFrame.ChangeOrig( ptV) ;
// Studio del volume asportato durante il moto
Frame3d MotionFrame ;
Vector3d vtDiagA = dLenX * ParaFrame.VersX() + dLenY * ParaFrame.VersY() ;
Vector3d vtDiagB = dLenX * ParaFrame.VersX() - dLenY * ParaFrame.VersY() ;
Vector3d vtW3 = ( abs( vtDiagA * vtMove) <= abs( vtDiagB * vtMove) ? vtDiagA : vtDiagB) ;
Point3d ptOrig = ptMyS - vtW3 / 2 - vtToolDir * ( dLenZ / 2) ;
double dLenW3 = vtW3.Len() ;
vtW3 /= dLenW3 ;
double dDeltaW3 = vtMove * vtW3 ;
Vector3d vtW1 = vtMove - dDeltaW3 * vtW3 ;
double dLenW1 = vtW1.Len() ;
vtW1 /= dLenW1 ;
Vector3d vtW2 = vtW3 ^ vtW1 ;
MotionFrame.Set( ptOrig, vtW1, vtW2, vtW3) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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 ;
// Solido nella posizione iniziale
ParaFrame.ChangeOrig( ptV) ;
if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Solido nella posizione finale
ParaFrame.ChangeOrig( ptV + vtMove) ;
if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
// Volume spazzato nel moto
if ( IntersLineMyPolyhedron( ptC, Z_AX, MotionFrame, dLenW1, dLenZ, dLenW3, dDeltaW3, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
// ---------- SFERA ----------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe, double dRad)
{
// Verifico interferisca
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptLs, ptLe, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore modivemnto
Vector3d vtV = ptLe - ptLs ;
double dLengthPath = vtV.Len() ;
if ( dLengthPath > EPS_ZERO)
vtV /= dLengthPath ;
// Riferimento per cilindro inviluppo della sfera lungo il movimento
Frame3d CylFrame ;
CylFrame.Set( ptLs, vtV) ;
double dSqRad = dRad * dRad ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( 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) ;
// Sfera in posizione start
double dStSqDXY = SqDistXY( ptC, ptLs) ;
if ( dStSqDXY < dSqRad) {
double dMin = ptLs.z - sqrt( dSqRad - dStSqDXY) ;
Vector3d vtNmin = ptLs - Point3d( dX, dY, dMin) ;
vtNmin.Normalize() ;
double dMax = ptLs.z + sqrt( dSqRad - dStSqDXY) ;
Vector3d vtNmax = ptLs - Point3d( dX, dY, dMax) ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Sfera in posizione end
double dEnSqDXY = SqDistXY( ptC, ptLe) ;
if ( dEnSqDXY < dSqRad) {
double dMin = ptLe.z - sqrt( dSqRad - dEnSqDXY) ;
Vector3d vtNmin = ptLe - Point3d( dX, dY, dMin) ;
vtNmin.Normalize() ;
double dMax = ptLe.z + sqrt( dSqRad - dEnSqDXY) ;
Vector3d vtNmax = ptLe - Point3d( dX, dY, dMax) ;
vtNmax.Normalize() ;
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ;
}
// Cilindro inviluppo della sfera
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ;
}
}
}
return true ;
}
// Superfici laterali
// Superfici ausiliarie
//----------------------------------------------------------------------------
// Calcola l'intersezione di una retta, descritta da punto iniziale ptLineP e versore della direzione
// vtLineDir, e la superficie definita da una corona circolare nello spazio, descritta dal centro delle
// circonferenze di frontiera, dal versore del loro asse di simmetria rotazionale e dai loro raggi.
// Il versore normale alla superficie coincide con quello dell'asse di simmetria e quello vtN
// dell'intersezione opposto ad'esso.
int
VolZmap::IntersLineCircCrown( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dMaxRad, double dMinRad,
Point3d& ptInt, Vector3d& vtN) const
{
// Definisco il versore normale al piano e il piano stesso.
Plane3d plMyPlane ;
Vector3d vtPlaneN = vtAx ;
if ( ! vtPlaneN.Normalize() || ! plMyPlane.Set( ptCen, vtPlaneN))
return 0 ;
// Quadrati dei raggi
double dSqMinRad = dMinRad * dMinRad ;
double dSqMaxRad = dMaxRad * dMaxRad ;
// Se la corona circolare defenera in un disco (dMinRad < EPS), forzo dSqSafeMinRad a - 1
// in modo da tagliare i dexel giacenti sul suo asse di simmetria.
if ( dMinRad < EPS_SMALL)
dSqMinRad = - 1 ;
// Intersezione retta piano
int nIntType = IntersLinePlane( ptLineP, vtLineDir, 1000, plMyPlane, ptInt, false) ;
if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) {
// Se il punto d'intersezione sta nella corona
double dSqIntCenDist = ( ptInt - ptCen) * ( ptInt - ptCen) ;
if ( dSqIntCenDist > dSqMinRad && dSqIntCenDist < dSqMaxRad) {
vtN = - vtAx ;
return 1 ;
}
}
return 0 ;
}
//----------------------------------------------------------------------------
// Calcola l'intersezione di una retta, descritta da punto iniziale ptLineP e versore della
// direzione vtLineDir, e la superficie definita da un parallelogramma nello spazio, descritto da un punto
// ptParOrig e i vettori che da esso spiccano.
// Se bExtNorm true la normale alla superficie ha lo stesso verso di vtSeg2 ^ vtSeg1, altrimenti
// quello opposto.
int
VolZmap::IntersLineParallelogram( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptParOrig, const Vector3d& vtSeg1, const Vector3d& vtSeg2,
bool bExtNorm, Point3d& ptInt, Vector3d& vtN) const
{
// Definisco il versore normale al piano e il piano stesso.
Plane3d plMyPlane ;
Vector3d vtPlaneN = vtSeg2 ^ vtSeg1 ;
if ( ! vtPlaneN.Normalize() || ! plMyPlane.Set( ptParOrig, vtPlaneN))
return 0 ;
// Intersezione retta piano
int nIntType = IntersLinePlane( ptLineP, vtLineDir, 1000, plMyPlane, ptInt, false) ;
if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) {
// Creo un sistema di riferimento per stabilire se l'intersezione avviene in un
// punto del piano interno alla superficie o meno.
Vector3d vtUnit2 = vtSeg2 ;
double dLen2 = vtUnit2.Len() ;
vtUnit2 /= dLen2 ;
Vector3d vtPerpToUnit2 = vtPlaneN ^ vtUnit2 ;
double dSegProjPerpLen1 = vtSeg1 * vtPerpToUnit2 ;
double dSegProjLongLen1 = vtSeg1 * vtUnit2 ;
Vector3d vtIntV = ptInt - ptParOrig ;
double dIntPerp = vtIntV * vtPerpToUnit2 ;
double dIntLong = vtIntV * vtUnit2 ;
if ( dIntPerp > 0 - EPS_SMALL && dIntPerp < dSegProjPerpLen1 + EPS_SMALL &&
( dIntLong + EPS_SMALL) * dSegProjPerpLen1 > dIntPerp * dSegProjLongLen1 &&
( dIntLong - dLen2 - EPS_SMALL) * dSegProjPerpLen1 < dIntPerp * dSegProjLongLen1) {
vtN = bExtNorm ? vtPlaneN : - vtPlaneN ;
return 1 ;
}
/*if ( dIntPerp >= 0 && dIntPerp <= dSegProjPerpLen1 &&
( dIntLong) * dSegProjPerpLen1 >= dIntPerp * dSegProjLongLen1 &&
( dIntLong - dLen2) * dSegProjPerpLen1 <= dIntPerp * dSegProjLongLen1) {
vtN = bExtNorm ? vtPlaneN : - vtPlaneN ;
return 1 ;
}*/
// Oppure crei polyline e chiami la funzione per testare se
// un punto interno o meno a una polyline chiusa e piana.
}
return 0 ;
}
//----------------------------------------------------------------------------
// Calcola le intersezioni di una retta con la superficie ottenuta dal taglio di un cilindro, inteso come la sola superficie
// laterale, con un numero arbitrario di piani.
// Nel taglio del cilindro si esclude la parte che sta nel semispazio verso cui punta la normale al piano.
// Il cilindro descritto dal centro della base ptBaseCen, dal versore vtAx del suo asse di simmetria, dal raggio dRad,
// dall'altezza dH e da un flag bInOut che indica se il campo delle normali al cilindro volge verso l'asse di simmetria o meno.
// I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono
// retta e cilindro.
// Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale
// della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione.
// La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2).
int
VolZmap::IntersLineCylinderCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptBaseCen, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Se il raggio non sufficientemente grande, non devo fare alcunch.
if ( dRad < EPS_SMALL)
return 0 ;
// Definisco il sistema di riferimento S; se non possibile, c' un errore.
Frame3d frFrameS ;
if ( ! frFrameS.Set( ptBaseCen, vtAx))
return 0 ;
// Se l'altezza negativa, cambio sistema di riferimento.
if ( dH < 0) {
frFrameS.Translate( dH * frFrameS.VersZ()) ;
dH *= - 1 ;
}
// Porto la linea nel riferimento del cilindro
Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ;
Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ;
// Se la retta parallela all'asse, non ci sono intersezioni.
if ( vtV.SqLenXY() < EPS_ZERO * EPS_ZERO)
return 0 ;
// Determino le intersezioni con la superficie cilindrica
DBLVECTOR vdCoef( 3) ;
double dSqRad = dRad * dRad ;
vdCoef[0] = ptP.x * ptP.x + ptP.y * ptP.y - dSqRad ;
vdCoef[1] = 2 * ( ptP.x * vtV.x + ptP.y * vtV.y) ;
vdCoef[2] = vtV.x * vtV.x + vtV.y * vtV.y ;
DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ;
// Se non ho trovato soluzioni, ho terminato.
if ( nRoot == 0)
return nRoot ;
// Punti di intersezione e versori alla superficie in corrispondenza di essi
ptInt1 = ptP + vdRoots[0] * vtV ;
vtN1.Set( ptInt1.x, ptInt1.y, 0) ; vtN1.Normalize() ;
if ( nRoot == 2) {
ptInt2 = ptP + vdRoots[1] * vtV ;
vtN2.Set( ptInt2.x, ptInt2.y, 0) ; vtN2.Normalize() ;
}
if ( ! bInOut) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z.
if ( ptInt1.z < 0 || ptInt1.z > dH) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
if ( nRoot > 0 && ( ptInt2.z < 0 || ptInt2.z > dH)) {
-- nRoot ;
}
// Esprimo punti e vettori nel sistema in cui immerso S.
if ( nRoot > 0) {
ptInt1.ToGlob( frFrameS) ;
vtN1.ToGlob( frFrameS) ;
if ( nRoot == 2) {
ptInt2.ToGlob( frFrameS) ;
vtN2.ToGlob( frFrameS) ;
}
}
// Elimino le intersezioni sul cono che non fanno parte della superficie.
bool bSecIntToTest = nRoot > 1 ;
for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) {
if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/ DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
if ( /*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) {
bSecIntToTest = false ;
-- nRoot ;
}
}
return nRoot ;
}
//----------------------------------------------------------------------------
// Calcola le intersezioni di una retta con una superficie di traslazione di una circonferenza di un vettore vtSweptVec
// tagliata da un numero arbitrario di piani.
// Nel taglio della superficie di traslazione si esclude la parte che sta nel semispazio verso cui punta la normale al piano.
// La circonferenza descritta dal centro ptCen, dal versore vtAx del suo asse di simmetria rotazionale e dal raggio dRad.
// Il flag bInOut indica se la proiezione sul piano della circonferenza del campo delle normail alla superficie volge verso il
// centro di quest'ultima o meno.
// I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono
// retta e la superficie di traslazione.
// Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale
// della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione.
// La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2).
int
VolZmap::IntersLineCircSweptSurfCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dRad, const Vector3d& vtSweptVec, bool bInOut,
const vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Se il raggio non sufficientemente grande, non devo fare alcunch.
if ( dRad < EPS_SMALL)
return 0 ;
// Studio delle simmetrie
Point3d ptMyCen = ptCen ;
Vector3d vtMySweptVec = vtSweptVec ;
if ( vtSweptVec * vtAx < 0) {
ptMyCen += vtSweptVec ;
vtMySweptVec *= - 1 ;
}
// Calcolo le lunghezze del moto nella direzione dell'asse di simmetria rotazionale e
// in quella ortogonale.
double dLongVecLen = vtMySweptVec * vtAx ;
double dOrtVecLen = sqrt( max( vtMySweptVec.SqLen() - dLongVecLen * dLongVecLen, 0.)) ;
// Definisco il sistema di riferimento S; se non possibile, c' un errore.
Vector3d vtV1 = vtMySweptVec - dLongVecLen * vtAx ;
Frame3d frFrameS ;
if ( ! vtV1.Normalize()) {
if ( ! frFrameS.Set( ptMyCen, vtAx))
return 0 ;
}
else if ( ! frFrameS.Set( ptMyCen, vtV1, vtAx ^ vtV1, vtAx))
return 0 ;
// Se la suerficie degenera in un piano, non bisogna tagliare
if ( abs( dLongVecLen) < /*EPS_SMALL*/EPS_ZERO)
return 0 ;
// Porto la linea nel riferimento S
Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ;
Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ;
// Asse cilindro ellittico
Vector3d vtSurfAx( dOrtVecLen, 0, dLongVecLen) ;
vtSurfAx.Normalize() ;
// Retta parallela a quella del moto
if ( AreSameOrOppositeVectorExact( vtV, vtSurfAx))
return 0 ;
// Quadrato del raggio, coefficiente angolare della retta di movimento nel
// piano ZX del sistema di riferimento del movimento e suo quadrato
double dSqRad = dRad * dRad ;
double dSqLongLen = dLongVecLen * dLongVecLen ;
double dSqOrtLen = dOrtVecLen * dOrtVecLen ;
// Setto i coeficienti dell'equazione d'intersezione della
// retta con la superficie di traslazione della circonferenza.
DBLVECTOR vdCoef(3) ;
vdCoef[0] = dSqLongLen * ( ptP.x * ptP.x + ptP.y * ptP.y) + dSqOrtLen * ptP.z * ptP.z
- 2 * dLongVecLen * dOrtVecLen * ptP.x * ptP.z - dSqLongLen * dSqRad ;
vdCoef[1] = 2 * dSqLongLen * ( ptP.x * vtV.x + ptP.y * vtV.y) + 2 * dSqOrtLen * ptP.z * vtV.z
- 2 * dLongVecLen * dOrtVecLen * ( ptP.x * vtV.z + ptP.z * vtV.x) ;
vdCoef[2] = dSqLongLen * ( vtV.x * vtV.x + vtV.y * vtV.y) + dSqOrtLen * vtV.z * vtV.z
- 2 * dLongVecLen * dOrtVecLen * vtV.x * vtV.z ;
// Numero di soluzioni
DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ;
// L'equazione ammette o due soluzioni (eventualmente
// coincidenti) oppure nessuna o infinite se la la retta
// appartiene alla superficie
// Se numero di soluzioni diverso da due le eventuali intersezioni sono gi state trovate
if ( nRoot != 2)
return 0 ;
// Punti di intersezione e versori alla superficie in corrispondenza di essi
ptInt1 = ptP + vdRoots[0] * vtV ;
ptInt2 = ptP + vdRoots[1] * vtV ;
vtN1.Set( dSqLongLen * ptInt1.x - dLongVecLen * dOrtVecLen * ptInt1.z, dSqLongLen * ptInt1.y, dSqOrtLen * ptInt1.z - dLongVecLen * dOrtVecLen * ptInt1.x) ;
vtN1.Normalize( EPS_ZERO) ;
vtN2.Set( dSqLongLen * ptInt2.x - dLongVecLen * dOrtVecLen * ptInt2.z, dSqLongLen * ptInt2.y, dSqOrtLen * ptInt2.z - dLongVecLen * dOrtVecLen * ptInt2.x) ;
vtN2.Normalize( EPS_ZERO) ;
if ( ! bInOut) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Elimino le soluzioni cha non stanno sulla superficie di traslazione, ovvero le intersezioni fuori dai limiti in Z.
if ( ptInt1.z < 0 || ptInt1.z > dLongVecLen) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
if ( ptInt2.z < 0 || ptInt2.z > dLongVecLen) {
-- nRoot ;
}
// Esprimo punti e vettori nel sistema in cui immerso S.
if ( nRoot > 0) {
ptInt1.ToGlob( frFrameS) ;
vtN1.ToGlob( frFrameS) ;
if ( nRoot == 2) {
ptInt2.ToGlob( frFrameS) ;
vtN2.ToGlob( frFrameS) ;
}
}
// Escludo le soluzioni che non stanno dalla parte ammissibile rispetto al piano.
bool bSecIntToTest = nRoot > 1 ;
for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) {
//double dDist1 = DistPointPlane(ptInt1, vPlanesVec[n]);
if ( DistPointPlane( ptInt1, vPlanesVec[n]) > 0 + EPS_SMALL/*DistPointPlane( ptInt1, vPlanesVec[n]) >= 0*/) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
//double dDist2 = DistPointPlane(ptInt2, vPlanesVec[n]);
if ( bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0 + EPS_SMALL/*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0*/) {
bSecIntToTest = false ;
-- nRoot ;
}
}
return nRoot ;
}
//----------------------------------------------------------------------------
// Calcola le intersezioni di una retta con la superficie ottenuta dal taglio di un cono, inteso come la sola superficie
// laterale, con un numero arbitrario di piani.
// Nel taglio del cono si esclude la parte che sta nel semispazio verso cui punta la normale al piano.
// Il cono descritto dal vertice ptVert, dal versore vtAx del suo asse di simmetria, dal raggio dRad, dall'altezza dH
// e da un flag bInOut che indica se il campo delle normali al cono volge verso l'asse di simmetria o meno.
// I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono
// retta e cono.
// Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale
// della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione.
// La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2).
int
VolZmap::IntersLineConeCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptVert, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Definisco il sistema di riferimento S; se non possibile, c' un errore.
Frame3d frFrameS ;
if ( ! frFrameS.Set( ptVert, vtAx))
return 0 ;
// Porto la linea nel riferimento del cilindro
Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ;
Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ;
// Tangente dell'angolo di semi-apertura
double dTan = dRad / dH ;
// Determino le intersezioni con la superficie laterale del cono
DBLVECTOR vdCoef( 3) ;
double dSqTan = dTan * dTan ;
vdCoef[0] = dSqTan * ptP.z * ptP.z - ptP.x * ptP.x - ptP.y * ptP.y ;
vdCoef[1] = 2 * ( dSqTan * ptP.z * vtV.z - ptP.x * vtV.x - ptP.y * vtV.y) ;
vdCoef[2] = dSqTan * vtV.z * vtV.z - vtV.x * vtV.x - vtV.y * vtV.y ;
DBLVECTOR vdRoots ;
int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ;
// Se non ho trovato soluzioni, ovvero si stata trovata una soluzione di tangenza, ho terminato.
if ( nRoot == 0 || ( nRoot == 1 && abs( vtV.z) < EPS_ZERO))
return 0 ;
// Intersezioni
ptInt1 = ptP + vdRoots[0] * vtV ;
vtN1 = Vector3d( ptInt1.x, ptInt1.y, - dSqTan * ptInt1.z) ;
vtN1.Normalize() ;
if ( nRoot == 2) {
ptInt2 = ptP + vdRoots[1] * vtV ;
vtN2 = Vector3d( ptInt2.x, ptInt2.y, - dSqTan * ptInt2.z) ;
vtN2.Normalize() ;
}
if ( ! bInOut) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Elimino le intersezioni che non fanno parte del cono.
if ( ptInt1.z < 0 || ptInt1.z > dH) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
if ( nRoot > 0 && ( ptInt2.z < 0 || ptInt2.z > dH))
-- nRoot ;
// Esprimo punti e vettori nel sistema in cui immerso S.
if ( nRoot > 0) {
ptInt1.ToGlob( frFrameS) ;
vtN1.ToGlob( frFrameS) ;
if ( nRoot == 2) {
ptInt2.ToGlob( frFrameS) ;
vtN2.ToGlob( frFrameS) ;
}
}
// Elimino le intersezioni sul cono che non fanno parte della superficie.
bool bSecIntToTest = nRoot > 1 ;
for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) {
if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nRoot ;
}
if ( /*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) {
bSecIntToTest = false ;
-- nRoot ;
}
}
return nRoot ;
}
//----------------------------------------------------------------------------
// Calcola le intersezioni di una retta con una superficie sferica tagliata da un numero arbitrario di piani.
// Nel taglio della sfera si esclude la parte che sta nel semispazio verso cui punta la normale al piano.
// Il cono descritto dal vertice ptVert, dal versore vtAx del suo asse di simmetria, dal raggio dRad, dall'altezza dH
// e da un flag bInOut che indica se il campo delle normali volge verso l'interno della sfera o meno.
// I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono
// retta e cono.
// Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale
// della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione.
// La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2).
int
VolZmap::IntersLineSphereCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCen, double dRad, bool bInOut,
const vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Intersezione fra retta e sfera
int nSol = IntersLineSphere( ptLineP, vtLineD, ptCen, dRad, ptInt1, ptInt2) ;
// Non ci sono soluzioni.
if ( nSol == ILST_NO)
return nSol ;
// Calcolo le normali
vtN1 = ( ptInt1 - ptCen) ; vtN1.Normalize() ;
vtN2 = ( ptInt2 - ptCen) ; vtN2.Normalize() ;
if ( ! bInOut) {
vtN1 *= - 1 ;
vtN2 *= - 1 ;
}
// Escludo le soluzioni fuori dalla parte ammissibile.
bool bSecIntToTest = nSol > 1 ;
for ( int n = 0 ; n < int( vPlanesVec.size()) && nSol != 0 ; ++ n) {
if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) {
ptInt1 = ptInt2 ;
vtN1 = vtN2 ;
-- nSol ;
}
if ( /*bSecIntToTest && nSol > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nSol > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) {
bSecIntToTest = false ;
-- nSol ;
}
}
return nSol ;
}
//----------------------------------------------------------------------------
// Il vettore normale alla superficie deve essere passato gi normalizzato.
int
VolZmap::IntersLineCatTongue( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCenSt, const Point3d& ptCenEn, const Vector3d& vtNorm, double dRad,
Point3d& ptInt, Vector3d& vtN) const
{
// Definisco il piano.
Plane3d plPlane ;
if ( ! plPlane.Set( ptCenSt, vtNorm))
return 0 ;
// Intersezione retta piano
int nIntType = IntersLinePlane( ptLineP, vtLineD, 1000, plPlane, ptInt, false) ;
if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) {
// Creo un sistema di riferimento per stabilire se l'intersezione avviene in un
// punto del piano interno alla superficie o meno.
Vector3d vtLong = ptCenEn - ptCenSt ;
double dLongLen = vtLong.Len() ;
vtLong /= dLongLen ;
Vector3d vtTrasv = vtNorm ^ vtLong ;
// Determino se l'intersezione sulla superficie
Vector3d vtIntV = ptInt - ptCenSt ;
double dIntLong = vtIntV * vtLong ;
double dIntTrasv = vtIntV * vtTrasv ;
double dInfLongLim = sqrt( max( dRad * dRad - dIntTrasv * dIntTrasv, 0.)) ;
double dSupLongLim = dLongLen + dInfLongLim ;
if ( abs( dIntTrasv) < dRad && dIntLong > dInfLongLim && dIntLong < dSupLongLim) {
vtN = - vtNorm ;
return 1 ;
}
}
return 0 ;
}
// Filtro per le intersezioni
typedef vector<pair<double, Vector3d>> DexelSurfIntersVector ;
//----------------------------------------------------------------------------
bool
IntersectionsFilter( const Vector3d& vtDexDir, const DexelSurfIntersVector& vOrigineIntersVec, DexelSurfIntersVector& vFilteredIntersVec)
{
// Tolleranze
double dDotEps = EPS_ZERO ;
double dLenEps = EPS_SMALL ;
// Separo gli ingressi dalle uscite.
DexelSurfIntersVector vEntrancesVec, vExitsVec, vIndefVec ;
for ( int n = 0 ; n < int( vOrigineIntersVec.size()) ; ++ n) {
if ( vOrigineIntersVec[n].second * vtDexDir < - dDotEps) {
vExitsVec.emplace_back( vOrigineIntersVec[n]) ;
}
else if ( vOrigineIntersVec[n].second * vtDexDir > dDotEps) {
vEntrancesVec.emplace_back( vOrigineIntersVec[n]) ;
}
else {
vIndefVec.emplace_back( vOrigineIntersVec[n]) ;
}
}
// Riordino le entrate e le uscite in funzione del parametro lungo la retta in corrispondenza del quale occorrono.
sort( vEntrancesVec.begin(), vEntrancesVec.end(), [] ( pair<double, Vector3d> Int1, pair<double, Vector3d> Int2)
{ return Int1.first < Int2.first ; }) ;
sort( vExitsVec.begin(), vExitsVec.end(), [] ( pair<double, Vector3d> Int1, pair<double, Vector3d> Int2)
{ return Int1.first < Int2.first ; }) ;
if ( int( vEntrancesVec.size()) == 2 &&
int( vExitsVec.size()) == 2 &&
abs( vEntrancesVec[0].first - vExitsVec[0].first) < dLenEps &&
abs( vEntrancesVec[1].first - vExitsVec[1].first) < dLenEps)
return true ;
// Modo 1
for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) {
for ( int m = 0 ; m < int( vExitsVec.size()) ; ++ m) {
if ( vExitsVec[m].first > vEntrancesVec[n].first) {
if ( n == 0 || ( int( vFilteredIntersVec.size()) > 0 && vEntrancesVec[n].first > vFilteredIntersVec.back().first)) {
vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ;
vFilteredIntersVec.emplace_back( vExitsVec[m]) ;
break ;
}
}
}
}
// Modo 2
// Media e deviazione standard delle entrate
//double dEntrancesAvarage = 0 ;
//double dEntrancesStdDev = 0 ;
//if ( int( vEntrancesVec.size()) != 0) {
// for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) {
// dEntrancesAvarage += vEntrancesVec[n].first ;
// }
// dEntrancesAvarage /= int( vEntrancesVec.size()) ;
// for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) {
// dEntrancesStdDev += ( vEntrancesVec[n].first - dEntrancesAvarage) * ( vEntrancesVec[n].first - dEntrancesAvarage) ;
// }
// dEntrancesStdDev = sqrt( dEntrancesStdDev / int( vEntrancesVec.size())) ;
//}
//
//// Media e deviazione standard delle uscite
//double dExitsAvarage = 0 ;
//double dExitsStdDev = 0 ;
//if ( int( vExitsVec.size()) != 0) {
// for ( int n = 0 ; n < int( vExitsVec.size()) ; ++ n) {
// dExitsAvarage += vExitsVec[n].first ;
// }
// dExitsAvarage /= int( vExitsVec.size()) ;
// for ( int n = 0 ; n < int( vExitsVec.size()) ; ++ n) {
// dExitsStdDev += ( vExitsVec[n].first - dExitsAvarage) * ( vExitsVec[n].first - dExitsAvarage) ;
// }
// dExitsStdDev = sqrt( dExitsStdDev / int( vExitsVec.size())) ;
//}
//
//// Deve esserci almeno un entrata e un uscita
//if ( int( vEntrancesVec.size()) != 0 && int( vExitsVec.size()) != 0) {
// // Caso di un solo gruppo per le entrate
// if ( dEntrancesStdDev < dLenEps) {
// // Caso di un solo gruppo per le uscite
// if ( dExitsStdDev < dLenEps) {
// if ( vExitsVec.back().first > vEntrancesVec[0].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// }
// // Caso di due gruppi per le uscite
// else {
// // Cerco ultima uscita del primo gruppo
// int n ;
// for ( n = int( vExitsVec.size()) - 1 ; n >= 0 ; -- n) {
// if ( vExitsVec[n].first < dExitsAvarage)
// break ;
// }
// // Aggiungo ingressi e uscite filtrati.
// if ( vExitsVec[n].first > vEntrancesVec[0].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec[n]) ;
// }
// else if ( vExitsVec.back().first > vEntrancesVec[0].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// }
// }
// // Caso di due gruppi per le entrate
// else {
// // Cerco prima entrata del secondo gruppo
// int n ;
// for ( n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) {
// if ( vEntrancesVec[n].first > dEntrancesAvarage)
// break ;
// }
// // Caso di un solo gruppo per le uscite
// if ( dExitsStdDev < dLenEps) {
// // Aggiungo ingressi e uscite filtrati.
// if ( vExitsVec.back().first > vEntrancesVec[n].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// else if ( vExitsVec.back().first > vEntrancesVec[0].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// }
// // Caso di due gruppi per le uscite
// else {
// // Cerco ultima uscita del primo gruppo
// int m ;
// for ( m = int( vExitsVec.size()) - 1 ; m >= 0 ; -- m) {
// if ( vExitsVec[m].first < dExitsAvarage)
// break ;
// }
// // Aggiungo ingressi e uscite ai filtri.
// if ( vExitsVec[m].first > vEntrancesVec[0].first) {
// if ( vExitsVec[m].first > vEntrancesVec[n].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// else if ( vExitsVec.back().first > vEntrancesVec[n].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec[m]) ;
// vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// else {
// vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ;
// vFilteredIntersVec.emplace_back( vExitsVec[m]) ;
// }
// }
// else {
// if ( vExitsVec.back().first > vEntrancesVec[n].first) {
// vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ;
// vFilteredIntersVec.emplace_back( vExitsVec.back()) ;
// }
// }
// }
// }
//}
return true ;
}
// Corona circolare
//----------------------------------------------------------------------------
bool
VolZmap::SurfCircCrown_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMaxRad, 1, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Se il movimento in direzione opposta a quella ove la corona pu tagliare, non devo fare nulla.
if ( vtAx.z * ( ptE - ptS).z < EPS_ZERO)
return true ;
// Raggi di sicurezza per evitare di tagliare i dexel a filo del bordo dela regione interessata dal taglio.
double dSqSafeMinRad = dMinRad * dMinRad + 2 * dMinRad * EPS_SMALL ;
double dSqSafeMaxRad = dMaxRad * dMaxRad - 2 * dMaxRad * EPS_SMALL ;
// Se la corona circolare defenera in un disco (dMinRad < EPS), forzo dSqSafeMinRad a - 1
// in modo da tagliare i dexel giacenti sul suo asse di simmetria.
if ( dMinRad < EPS_SMALL)
dSqSafeMinRad = - 1 ;
Point3d ptSXY( ptS.x, ptS.y, 0) ;
// Ciclo sui dexel.
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
Vector3d vtR = ptC - ptSXY ;
double dSqLenR = vtR * vtR ;
if ( dSqLenR > dSqSafeMinRad && dSqLenR < dSqSafeMaxRad) {
double dMinZ = min( ptS.z, ptE.z) ;
double dMaxZ = max( ptS.z, ptE.z) ;
Vector3d vtMinN, vtMaxN ;
if ( ptE.z < ptS.z) {
vtMinN.z = 1 ;
vtMaxN.z = -1 ;
}
else {
vtMinN.z = 1 ;
vtMaxN.z = - 1 ;
}
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfCircCrown_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, 1, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Se il movimento in direzione opposta a quella ove la corona pu tagliare, non devo fare nulla.
double dMotProjOnAx = vtAx * ( ptE - ptS) ;
if ( dMotProjOnAx < EPS_ZERO)
return true ;
// Vettore di piani fittizio
vector<Plane3d> vEmptyPlaneVec ;
// Ciclo sui dexel.
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con cilindro esterno
int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, dMotProjOnAx, false, vEmptyPlaneVec,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro interno in caso di corona circolare propria (la funzione esegue
// l'intersezione solo se il cilindro ha un raggio sensibilmente maggiore di zero)
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMinRad, dMotProjOnAx, true, vEmptyPlaneVec,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con corona in posizione inziale
nIntNum = IntersLineCircCrown( ptC, Z_AX, ptS, - vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Intersezione con corona in posizione inziale
nIntNum = IntersLineCircCrown( ptC, Z_AX, ptE, vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfCircCrown_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad)
{
return SurfCircCrown_Milling( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfCircCrown_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMaxRad, 1, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Se il movimento in direzione opposta a quella ove la corona pu tagliare, non devo fare nulla.
Vector3d vtDisp = ( ptE - ptS) ;
double dMotProjOnAx = vtAx * vtDisp ;
if ( dMotProjOnAx < EPS_ZERO)
return true ;
// Vettore di piani fittizio
vector<Plane3d> vEmptyPlaneVec ;
// Ciclo sui dexel.
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con cilindro ellittico esterno
int nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, false,
vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro interno in caso di corona circolare propria (la funzione esegue
// l'intersezione solo se il cilindro ha un raggio sensibilmente maggiore di zero)
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMinRad, vtDisp, true,
vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con corona in posizione inziale
nIntNum = IntersLineCircCrown( ptC, Z_AX, ptS, - vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Intersezione con corona in posizione inziale
nIntNum = IntersLineCircCrown( ptC, Z_AX, ptE, vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
// Cilindro
//----------------------------------------------------------------------------
//bool
//VolZmap::SurfCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
// double dHei, double dRad, bool bTapB, bool bTapT)
//{
// return true ;
//}
//
////----------------------------------------------------------------------------
//bool
//VolZmap::SurfCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
// double dHei, double dRad, bool bTapB, bool bTapT)
//{
// return true ;
//}
//----------------------------------------------------------------------------
bool
VolZmap::SurfCyl_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dHei, double dRad, bool bOuterCutter)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento
Vector3d vtDisp = ptE - ptS ;
// Dimensioni del moto nella direzione utensile e ortogonale e quote iniziali e finali
double dDispZ = vtDisp * vtAx ;
double dDispXY = sqrt( max( vtDisp.SqLen() - dDispZ * dDispZ, 0.)) ;
double dStartTopZ = ptS.z ;
double dStartBotZ = ( ptS - dHei * vtAx).z ;
// Sistema di riferimento del moto
Vector3d vtV3 = vtAx ;
Vector3d vtV1 = vtDisp - dDispZ * vtV3 ; vtV1.Normalize() ;
Vector3d vtV2 = vtV3 ^ vtV1 ;
Point3d ptSxy( ptS.x, ptS.y, 0) ;
// Caso moto perpendicolare
if ( abs( dDispZ) < EPS_SMALL) {
// Ciclo sui dexel.
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
double dProj1 = ( ptC - ptSxy) * vtV1 ;
double dProj2 = ( ptC - ptSxy) * vtV2 ;
double dCirc1 = ( bOuterCutter ? 1 : - 1) * sqrt( max( dRad * dRad - dProj2 * dProj2, 0.)) ;
if ( abs( dProj2) < dRad && dProj1 > dCirc1 && dProj1 < dDispXY + dCirc1) {
// Quote minima e massima rispetto al sistema griglia e versori normali associati
double dMin = vtAx.z > 0 ? dStartBotZ : dStartTopZ ;
double dMax = vtAx.z > 0 ? dStartTopZ : dStartBotZ ;
Vector3d vtMin = Z_AX ;
Vector3d vtMax = - Z_AX ;
// Taglio dei dexel
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
return true ;
}
// Ciclo sui dexel.
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
double dProj1 = ( ptC - ptSxy) * vtV1 ;
double dProj2 = ( ptC - ptSxy) * vtV2 ;
double dCirc1 = ( bOuterCutter ? 1 : - 1) * sqrt( max( dRad * dRad - dProj2 * dProj2, 0.)) ;
if ( abs( dProj2) < dRad && dProj1 > dCirc1 && dProj1 < dDispXY + dCirc1) {
// Quote inferiore e superiore rispetto alla direzione del versore utensile
double dInfZ = dStartBotZ + ( dProj1 - dCirc1) * dDispZ * vtAx.z / dDispXY ;
double dSupZ = dStartTopZ + ( dProj1 - dCirc1) * dDispZ * vtAx.z / dDispXY ;
// Calcolo dei versori normali associati
Vector3d vtRad = dCirc1 * vtV1 + dProj2 * vtV2 ;
Vector3d vtTan( - vtRad.y, vtRad.x, 0) ;
Vector3d vtCross = vtTan ^ vtDisp ;
vtCross.Normalize() ;
// Quote minima e massima rispetto al sistema griglia e versori normali associati
double dMin = vtAx.z > 0 ? dInfZ : dSupZ ;
double dMax = vtAx.z > 0 ? dSupZ : dInfZ ;
Vector3d vtMin = bOuterCutter ? - vtCross : vtCross ;
Vector3d vtMax = bOuterCutter ? vtCross : - vtCross ;
// Taglio dei dexel
SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtAx, double dHei, double dRad, bool bOuterCutter, bool bTapB, bool bTapT)
{
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento
Vector3d vtDisp = ptE - ptS ;
// Versore della componente del moto ortogonale all'asse dell'utensile
double dDispZ = vtDisp * vtAx ;
Vector3d vtOrtDisp = vtDisp - dDispZ * vtAx ;
double dOrtDispLen = vtOrtDisp.Len() ;
vtOrtDisp /= dOrtDispLen ;
// Versore direzione del moto
Vector3d vtDispDir = vtDisp ;
vtDispDir.Normalize() ;
// Versore laterale
Vector3d vtLat = vtAx ^ vtOrtDisp ;
// Deduzione dei punti per la definizione dei piani laterali
Point3d ptPlanePlus = ptS - dHei * vtAx + dRad * vtLat ;
Point3d ptPlaneMinus = ptS - dHei * vtAx - dRad * vtLat ;
// Moto ortogonale all'asse del cilindro
double dObCoef = dDispZ / dOrtDispLen ;
double dMyLength = dObCoef * dRad / sqrt( 1 + dObCoef * dObCoef) ;
if ( abs( dDispZ) < 2 * EPS_SMALL && dMyLength < 2 * EPS_SMALL) {
Point3d ptMyE = ptS + dOrtDispLen * vtOrtDisp ;
// Definisco i piani utilizzati per tagliare le superfici elementari.
// Piano per cilindro in posizione iniziale
vector<Plane3d> vCutCylPlaneVecSt ;
vCutCylPlaneVecSt.emplace_back() ;
vCutCylPlaneVecSt.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ;
// Piano per cilindro in posizione finale
vector<Plane3d> vCutCylPlaneVecEn ;
vCutCylPlaneVecEn.emplace_back() ;
vCutCylPlaneVecEn.back().Set( ptMyE, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0.) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con cilindro in posizione iniziale
int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, - dHei, bOuterCutter, vCutCylPlaneVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro in posizione finale
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, vtAx, dRad, - dHei, ! bOuterCutter, vCutCylPlaneVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con lingua di gatto superiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, bOuterCutter ? ptS : ptMyE, bOuterCutter ? ptMyE : ptS,
vtAx, dRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Intersezione con lingua di gatto inferiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx,
- vtAx, dRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano + (con normale + vtLat)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlus, dHei * vtAx, vtDisp,
true, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano - (con normale - vtLat)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinus, dHei * vtAx, vtDisp,
false, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
// Definisco i piani utilizzati per tagliare le superfici elementari.
// Piano per cilindro in posizione iniziale
vector<Plane3d> vCutCylPlaneVecSt ;
vCutCylPlaneVecSt.emplace_back() ;
vCutCylPlaneVecSt.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ;
// Piano per cilindro in posizione finale
vector<Plane3d> vCutCylPlaneVecEn ;
vCutCylPlaneVecEn.emplace_back() ;
vCutCylPlaneVecEn.back().Set( ptE, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ;
// Piano per cilindro ellittico superiore
vector<Plane3d> vCutEllipCylPlaneVecUp ;
if ( dDispZ > 0) {
vCutEllipCylPlaneVecUp.emplace_back() ;
vCutEllipCylPlaneVecUp.back().Set( ptS, ( bOuterCutter ? 1 : - 1) * vtDispDir ^ vtLat) ;
}
else {
vCutEllipCylPlaneVecUp.emplace_back() ;
vCutEllipCylPlaneVecUp.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtDispDir ^ vtLat) ;
}
// Piani per cilindro ellittico inferiore
vector<Plane3d> vCutEllipCylPlaneVecDw ;
if ( dDispZ > 0) {
vCutEllipCylPlaneVecDw.emplace_back() ;
vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx, ( bOuterCutter ? 1 : - 1) * vtDispDir ^ vtLat) ;
}
else {
vCutEllipCylPlaneVecDw.emplace_back() ;
vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx, ( bOuterCutter ? - 1 : 1) * vtDispDir ^ vtLat) ;
}
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0.) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con cilindro in posizione iniziale
int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, - dHei, bOuterCutter, vCutCylPlaneVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro in posizione finale
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, vtAx, dRad, - dHei, ! bOuterCutter, vCutCylPlaneVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, vtDisp, bOuterCutter == dDispZ > 0, vCutEllipCylPlaneVecUp,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
if ( vCutEllipCylPlaneVecUp.size() == 1) {
if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) {
//double dLL1 = (ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN();
//double dLL2 = (ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN();
if ( ( ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ;
else if ( ( ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ;
}
}
}
}
// Intersezione con cilindro ellittico inferiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dRad, vtDisp, bOuterCutter != dDispZ > 0, vCutEllipCylPlaneVecDw,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
if ( vCutEllipCylPlaneVecDw.size() == 1) {
if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) {
//double dLL1 = (ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN();
//double dLL2 = (ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN();
if ( ( ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ;
else if ( ( ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ;
}
}
}
}
// Piano + (con normale + vtLat)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlus, dHei * vtAx, vtDisp,
true, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano - (con normale - vtLat)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinus, dHei * vtAx, vtDisp,
false, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
// Cono
//----------------------------------------------------------------------------
bool
VolZmap::SurfConus_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
// Verifica sull'interferenza con lo Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Raggi di sicurezza per evitare di tagliare i dexel a filo del bordo dela regione interessata dal taglio.
double dSqSafeMinRad = dMinRad * dMinRad + 2 * dMinRad * EPS_SMALL ;
double dSqSafeMaxRad = dMaxRad * dMaxRad - 2 * dMaxRad * EPS_SMALL ;
// Se il movimento nella direzione ove il cono non taglia, ho finito.
if ( vtAx.z * ( ptE.z - ptS.z) > 0 == bOuterCutter)
return true ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
double dSqR = ( dX - ptS.x) * ( dX - ptS.x) + ( dY - ptS.y) * ( dY - ptS.y) ;
if ( dSqR < dSqSafeMinRad || dSqR > dSqSafeMaxRad)
continue ;
if ( vtAx.z > 0) {
double dr = sqrt( dSqR) ;
// Quote Z
double dMinZ = min( ptS.z, ptE.z) - dHei + ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ;
double dMaxZ = max( ptS.z, ptE.z) - dHei + ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ;
// Normali
Vector3d vtMinN, vtMaxN ;
if ( bOuterCutter) {
double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ;
Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ;
Point3d ptIntMinP( dX, dY, dMinZ) ;
Vector3d vtIntMinV = ptIntMinP - ptVertE ;
double dCompLong = vtIntMinV * vtAx ;
Vector3d vtIntMinLongV = dCompLong * vtAx ;
Vector3d vtIntMinOrtV = vtIntMinV - vtIntMinLongV ;
double dCompOrt = vtIntMinOrtV.Len() ;
vtIntMinOrtV /= dCompOrt ;
vtMinN = - dCompLong * vtIntMinOrtV + dCompOrt * vtAx ;
vtMinN.Normalize() ;
vtMaxN = - vtMinN ;
}
else {
double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ;
Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ;
Point3d ptIntMaxP( dX, dY, dMaxZ) ;
Vector3d vtIntMaxV = ptIntMaxP - ptVertE ;
double dCompLong = vtIntMaxV * vtAx ;
Vector3d vtIntMaxLongV = dCompLong * vtAx ;
Vector3d vtIntMaxOrtV = vtIntMaxV - vtIntMaxLongV ;
double dCompOrt = vtIntMaxOrtV.Len() ;
vtIntMaxOrtV /= dCompOrt ;
vtMaxN = dCompLong * vtIntMaxOrtV - dCompOrt * vtAx ;
vtMaxN.Normalize() ;
vtMinN = - vtMaxN ;
}
// Taglio dei dexel
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ;
}
else {
double dr = sqrt( dSqR) ;
// Quote Z
double dMinZ = min( ptS.z, ptE.z) + dHei - ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ;
double dMaxZ = max( ptS.z, ptE.z) + dHei - ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ;
// Normali
Vector3d vtMinN, vtMaxN;
if ( bOuterCutter) {
double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ;
Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ;
Point3d ptIntMaxP( dX, dY, dMaxZ) ;
Vector3d vtIntMaxV = ptIntMaxP - ptVertE ;
double dCompLong = vtIntMaxV * vtAx ;
Vector3d vtIntMaxLongV = dCompLong * vtAx ;
Vector3d vtIntMaxOrtV = vtIntMaxV - vtIntMaxLongV ;
double dCompOrt = vtIntMaxOrtV.Len() ;
vtIntMaxOrtV /= dCompOrt ;
vtMaxN = - dCompLong * vtIntMaxOrtV + dCompOrt * vtAx ;
vtMaxN.Normalize() ;
vtMinN = - vtMaxN ;
}
else {
double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ;
Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ;
Point3d ptIntMinP( dX, dY, dMinZ) ;
Vector3d vtIntMinV = ptIntMinP - ptVertE ;
double dCompLong = vtIntMinV * vtAx ;
Vector3d vtIntMinLongV = dCompLong * vtAx ;
Vector3d vtIntMinOrtV = vtIntMinV - vtIntMinLongV ;
double dCompOrt = vtIntMinOrtV.Len() ;
vtIntMinOrtV /= dCompOrt ;
vtMinN = dCompLong * vtIntMinOrtV - dCompOrt * vtAx ;
vtMinN.Normalize() ;
vtMaxN = - vtMinN ;
}
// Taglio dei dexel
SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento e sua componente lungo l'asse del cono
Vector3d vtDisp = ptE - ptS ;
double dDispLong = vtAx * vtDisp ;
// Se lo spostamento in direzione opposta a quella ove il cono taglia, ho finito.
bool bToolVecAndDispAreOpposite = dDispLong < 0 ;
if ( bToolVecAndDispAreOpposite != bOuterCutter)
return true ;
// Vertici cono iniziale e finale
double dDeltaHei = ( dMinRad * dHei) / ( dMaxRad - dMinRad) ;
Point3d ptVs = ptS - ( dHei + dDeltaHei) * vtAx ;
Point3d ptVe = ptE - ( dHei + dDeltaHei) * vtAx ;
// Piani per tagliare le superfici elementari.
vector<Plane3d> vCutConePlaneVecSt ; vCutConePlaneVecSt.emplace_back() ;
vCutConePlaneVecSt.back().Set( ptS - dHei * vtAx, - vtAx) ;
vector<Plane3d> vCutConePlaneVecEn ; vCutConePlaneVecEn.emplace_back() ;
vCutConePlaneVecEn.back().Set( ptE - dHei * vtAx, - vtAx) ;
vector<Plane3d> vEmptyPlaneVec ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con il cono in posizione iniziale
int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVs, vtAx, dMaxRad, dHei + dDeltaHei, /*!*/ bToolVecAndDispAreOpposite,
vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cono in posizione finale
nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVe, vtAx, dMaxRad, dHei + dDeltaHei, ! bToolVecAndDispAreOpposite,
vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cilindro esterno
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, dDispLong, false,
vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cilindro interno
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, dDispLong, true,
vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfConus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
return SurfConus_Milling( nGrid, ptS, ptE, vtAx, dHei, dMaxRad, dMinRad, bOuterCutter, true, true, vtArcNormMaxR, vtArcNormMinR) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SurfConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
{
// Verifico interferenza
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento
Vector3d vtDisp = ptE - ptS ;
// Spostamento nella direzione utensile e in quella ortogonale
double dDispProjOnAxDir = vtDisp * vtAx ;
Vector3d vtDispLong = dDispProjOnAxDir * vtAx ;
Vector3d vtDispOrt = vtDisp - vtDispLong ;
// Terna di riferimento del movimento
Vector3d vtV1 = vtDispOrt ; vtV1.Normalize() ;
Vector3d vtV2 = vtAx ^ vtV1 ;
Vector3d vtV3 = vtAx ;
// Parametri geometrici descriventi il cono e il moto
double dDeltaHei = dMinRad * dHei / ( dMaxRad - dMinRad) ;
double dTanAlpha = dMaxRad / ( dHei + dDeltaHei) ;
double dCosTheta = Clamp( ( dTanAlpha * vtDisp * vtV3) / ( vtDisp * vtV1), -1., 1.) ;
double dSinTheta = sqrt( max( 1 - dCosTheta * dCosTheta, 0.)) ;
double dLim = abs( dCosTheta) ;
// Se il movimento non compatibile con il verso delle normali, ho finito.
if ( dLim > 1 - EPS_ZERO && ( bOuterCutter == dDispProjOnAxDir > 0))
return true ;
// Vertici del cono nelle posizioni iniziale e finale
Point3d ptVertSt = ptS - ( dHei + dDeltaHei) * vtAx ;
Point3d ptVertEn = ptE - ( dHei + dDeltaHei) * vtAx ;
// Vettori radiali per definire i piani
Vector3d vtRadPlus = dCosTheta * vtV1 + dSinTheta * vtV2 ;
Vector3d vtRadMinus = dCosTheta * vtV1 - dSinTheta * vtV2 ;
// Piani per tagliare le superfici elementari.
// Piani per cono in posizione iniziale
vector<Plane3d> vCutConePlaneVecSt ;
vCutConePlaneVecSt.emplace_back() ;
vCutConePlaneVecSt.back().Set( ptS - dHei * vtAx, - vtAx) ;
// Piani per cono in posizione finale
vector<Plane3d> vCutConePlaneVecEn ;
vCutConePlaneVecEn.emplace_back() ;
vCutConePlaneVecEn.back().Set( ptE - dHei * vtAx, - vtAx) ;
// Piani per cilindro ellittico superiore
vector<Plane3d> vCutEllipCylPlaneVecUp ;
// Piani per cilindro ellittico inferiore
vector<Plane3d> vCutEllipCylPlaneVecDw ;
// Caso di limete oltrepassato
if ( dLim > 1 - EPS_ZERO) {
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con il cono in posizione iniziale
int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter,
vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cono in posizione finale
nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter,
vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico esterno
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, false, vCutEllipCylPlaneVecUp,
ptInt1, vtN1, ptInt2, vtN2);
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico interno
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, vtDisp, true, vCutEllipCylPlaneVecDw,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
else {
// Vettore normale ai piani per il nuovo taglio dei coni.
Vector3d vtConePlaneNorm = ( ptS + dMaxRad * vtRadPlus - ptVertSt) ^ ( ptS + dMaxRad * vtRadMinus - ptVertSt) ; vtConePlaneNorm.Normalize() ;
if ( bOuterCutter)
vtConePlaneNorm *= - 1 ;
// Aggiorno vettore di piani per tagliare il cono in posizione iniziale.
vCutConePlaneVecSt.emplace_back() ;
vCutConePlaneVecSt.back().Set( ptVertSt, vtConePlaneNorm) ;
// Aggiorno vettore di piani per tagliare il cono in posizione finale.
vCutConePlaneVecEn.emplace_back() ;
vCutConePlaneVecEn.back().Set( ptVertEn, vtConePlaneNorm) ;
// Punti e normali dei piani laterali
Point3d ptPlanePlusP = ptS - dHei * vtAx + dMinRad * vtRadPlus ;
Point3d ptPlaneMinusP = ptS - dHei * vtAx + dMinRad * vtRadMinus ;
Vector3d vtPlanePlusN = ptS + dMaxRad * vtRadPlus - ptPlanePlusP ;
Vector3d vtPlaneMinusN = ptS + dMaxRad * vtRadMinus - ptPlaneMinusP ;
// Moto ortogonale all'asse del cono
double dObCoef = dDispProjOnAxDir / vtDispOrt.Len() ;
double dMyLengthMax = dObCoef * dMaxRad / sqrt( 1 + dObCoef * dObCoef) ;
double dMyLengthMin = dObCoef * dMinRad / sqrt( 1 + dObCoef * dObCoef) ;
if ( abs( dDispProjOnAxDir) < 2 * EPS_SMALL && min( dMyLengthMax, dMyLengthMin) < 2 * EPS_SMALL) {
Point3d ptMyE = ptS + vtDispOrt ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con il cono in posizione iniziale
int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter,
vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cono in posizione finale
nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter,
vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con lingua di gatto superiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, bOuterCutter ? ptS : ptMyE, bOuterCutter ? ptMyE : ptS,
vtAx, dMaxRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Intersezione con lingua di gatto inferiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx,
- vtAx, dMinRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano + (con normale + vtAx ^ vtOrtDisp)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlusP, vtPlanePlusN, vtDisp,
true, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano - (con normale - vtAx ^ vtOrtDisp)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinusP, vtPlaneMinusN, vtDisp,
false, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
return true ;
}
// Aggiorno il vettore dei piani per tagliare il cilindro ellittico superiore.
Vector3d vtEllipCylPlaneNormUp = vtDisp ^ vtV2 ; vtEllipCylPlaneNormUp.Normalize() ;
if ( bOuterCutter != dDispProjOnAxDir > 0)
vtEllipCylPlaneNormUp *= - 1 ;
vCutEllipCylPlaneVecUp.emplace_back() ;
vCutEllipCylPlaneVecUp.back().Set( ptS + dMaxRad * dCosTheta * vtV1, vtEllipCylPlaneNormUp) ;
// Aggiorno il vettore dei piani per tagliare il cilindro ellittico inferiore.
Vector3d vtEllipCylPlaneNormDw = vtEllipCylPlaneNormUp ;
vCutEllipCylPlaneVecDw.emplace_back() ;
vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx + dMinRad * dCosTheta * vtV1, vtEllipCylPlaneNormDw) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec;
DexelSurfIntersVector vIntersConusStart, vIntersConusEnd, vIntersEllipSup, vIntersEllipInf, vIntersPlanePlus, vIntersPlaneMinus;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con il cono in posizione iniziale
int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter,
vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con il cono in posizione finale
nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter,
vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, bOuterCutter == dDispProjOnAxDir > 0, vCutEllipCylPlaneVecUp,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
if ( vCutEllipCylPlaneVecUp.size() == 1) {
if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) {
//double dLL1 = (ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN();
//double dLL2 = (ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN();
if ( ( ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ;
else if ( ( ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ;
}
}
}
}
// Intersezione con cilindro ellittico inferiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, vtDisp, bOuterCutter != dDispProjOnAxDir > 0, vCutEllipCylPlaneVecDw,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
if ( vCutEllipCylPlaneVecDw.size() == 1) {
if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) {
//double dLL1 = (ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN();
//double dLL2 = (ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN();
if ( ( ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ;
else if ( ( ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.)
vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ;
}
}
}
}
// Piano + (con normale + vtAx ^ vtOrtDisp)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlusP, vtPlanePlusN, vtDisp,
true, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Piano - (con normale - vtAx ^ vtOrtDisp)
nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinusP, vtPlaneMinusN, vtDisp,
false, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
return true ;
}
// Parte di calotta sferica
//----------------------------------------------------------------------------
bool
VolZmap::SurfSphericalShellPart_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dInfH, double dSupH, bool bOuterCutter)
{
// Se la superficie una calotta sferica, chiamo la routine apposita.
if ( dInfH > dRad - EPS_SMALL)
return SurfSphericalShell_Milling( nGrid, ptS, ptE, vtAx, dRad, dSupH, bOuterCutter) ;
// Verifico interferisca
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento
Vector3d vtDisp = ptE - ptS ;
Vector3d vtDispVers = vtDisp ;
double dDispLen = vtDispVers.Len() ;
vtDispVers /= dDispLen ;
// Prodotto scalare fra versore del movimento e asse della calotta sferica
double dAxDispDot = vtDispVers * vtAx ;
// Raggi dei cilindri ellittici
double dInfRad = sqrt( max( dRad * dRad - dInfH * dInfH, 0.)) ;
double dSupRad = sqrt( max( dRad * dRad - dSupH * dSupH, 0.)) ;
// Coseni limite
double dCosInf = dInfRad / dRad ;
double dCosSup = dSupRad / dRad ;
// Vettore dei piani di taglio della sfera in posizione iniziale
vector<Plane3d> vSphereCutPlanesVecSt ;
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS - dSupH * vtAx, vtAx) ;
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS - dInfH * vtAx, - vtAx) ;
// Vettore dei piani di taglio della sfera in posizione finale
vector<Plane3d> vSphereCutPlanesVecEn ;
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE - dSupH * vtAx, vtAx) ;
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE - dInfH * vtAx, - vtAx) ;
if ( abs( dAxDispDot) > dCosSup - EPS_ZERO) {
if ( bOuterCutter == dAxDispDot > 0)
return true ;
// Vettori dei piani di taglio del cilindro ellittico superiore e inferiore
vector<Plane3d> vEllipCylCutPlanesVecSup ;
vector<Plane3d> vEllipCylCutPlanesVecInf ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con sfera in posizione iniziale
int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con sfera in posizione finale
nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, false,
vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico inferiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, true,
vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
else if ( abs( dAxDispDot) >= dCosInf) {
// Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale.
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Aggiorno il vettore dei piani di taglio della sfera in posizione finale.
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Versore della componente del moto perpendicolare all'asse
Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ;
double dOrtDispLen = vtOrtDispVers.Len() ;
vtOrtDispVers /= dOrtDispLen ;
// Vettore dei piani di taglio del cilindro ellittico superiore
Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ;
vtPlaneN.Normalize() ;
if ( bOuterCutter != dAxDispDot > 0)
vtPlaneN *= - 1 ;
double dC = vtDispVers * vtAx ;
double dS = sqrt( max( 1 - dC * dC, 0.)) ;
Point3d ptPlaneP = ptS - dSupH * vtAx + ( dC * dSupH / dS) * vtOrtDispVers ;
vector<Plane3d> vEllipCylCutPlanesVecSup ;
vEllipCylCutPlanesVecSup.emplace_back() ;
vEllipCylCutPlanesVecSup.back().Set( ptPlaneP, vtPlaneN) ;
// Vettore dei piani di taglio del cilindro ellittico inferiore
vector<Plane3d> vEllipCylCutPlanesVecInf ;
// Vettore dei piani di taglio del cilindro
vector<Plane3d> vCylCutPlanesVec ;
vCylCutPlanesVec.emplace_back() ;
vCylCutPlanesVec.back().Set( ptPlaneP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con sfera in posizione iniziale
int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con sfera in posizione finale
nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0,
vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico inferiore, se necessario
if ( bOuterCutter != dAxDispDot > 0) {
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, true,
vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
}
// Intersezione con cilindro esterno
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false,
vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
else {
// Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale.
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Aggiorno il vettore dei piani di taglio della sfera in posizione finale.
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Versore della componente del moto perpendicolare all'asse
Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ;
double dOrtDispLen = vtOrtDispVers.Len() ;
vtOrtDispVers /= dOrtDispLen ;
// Determinazione dei piani di taglio dei cilindri ellittici
Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ;
vtPlaneN.Normalize() ;
if ( bOuterCutter != dAxDispDot > 0)
vtPlaneN *= - 1 ;
double dC = vtDispVers * vtAx ;
double dS = sqrt( max( 1 - dC * dC, 0.)) ;
Point3d ptPlaneSupP = ptS - dSupH * vtAx + ( dC * dSupH / dS) * vtOrtDispVers ;
Point3d ptPlaneInfP = ptS - dInfH * vtAx + ( dC * dInfH / dS) * vtOrtDispVers ;
// Vettore dei piani di taglio del cilindro ellittico superiore
vector<Plane3d> vEllipCylCutPlanesVecSup ;
vEllipCylCutPlanesVecSup.emplace_back() ;
vEllipCylCutPlanesVecSup.back().Set( ptPlaneSupP, vtPlaneN) ;
// Vettore dei piani di taglio del cilindro ellittico inferiore
vector<Plane3d> vEllipCylCutPlanesVecInf ;
vEllipCylCutPlanesVecInf.emplace_back() ;
vEllipCylCutPlanesVecInf.back().Set( ptPlaneInfP, vtPlaneN) ;
// Vettore dei piani di taglio del cilindro
vector<Plane3d> vCylCutPlanesVec ;
vCylCutPlanesVec.emplace_back() ;
vCylCutPlanesVec.back().Set( ptPlaneSupP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ;
vCylCutPlanesVec.emplace_back() ;
vCylCutPlanesVec.back().Set( ptPlaneInfP, bOuterCutter == dAxDispDot > 0 ? - vtPlaneN : vtPlaneN) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con sfera in posizione iniziale
int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con sfera in posizione finale
nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
//// Se il movimento non ortogonale all'asse interseco con i cilindri ellittici.
//double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ;
//double dMyLengthSup = dObCoef * dSupRad / sqrt( 1 + dObCoef * dObCoef) ;
//double dMyLengthInf = dObCoef * dInfRad / sqrt( 1 + dObCoef * dObCoef) ;
//if ( abs( dDispLen * dAxDispDot) > EPS_SMALL && min( dMyLengthSup, dMyLengthInf) > 2 * EPS_SMALL) {
// // Intersezione con cilindro ellittico superiore
// nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0,
// vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ;
// if ( nIntNum >= 1) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt1.z ;
// vParAndNormIntersVec.back().second = vtN1 ;
// if ( nIntNum == 2) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt2.z ;
// vParAndNormIntersVec.back().second = vtN2 ;
// }
// }
//
// // Intersezione con cilindro ellittico inferiore
// nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, bOuterCutter != dAxDispDot > 0,
// vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ;
// if ( nIntNum >= 1) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt1.z ;
// vParAndNormIntersVec.back().second = vtN1 ;
// if ( nIntNum == 2) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt2.z ;
// vParAndNormIntersVec.back().second = vtN2 ;
// }
// }
//}
//// Altrimenti interseco con le lingue di gatto.
//else {
// Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ;
// // Intersezione con lingua la gatto superiore
// nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dSupH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dSupH * vtAx,
// vtAx, dSupRad, ptInt1, vtN1) ;
// if ( nIntNum == 1) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt1.z ;
// vParAndNormIntersVec.back().second = vtN1 ;
// }
// // Intersezione con la lingua di gatto inferiore
// nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dInfH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dInfH * vtAx,
// - vtAx, dInfRad, ptInt1, vtN1) ;
// if ( nIntNum == 1) {
// vParAndNormIntersVec.emplace_back() ;
// vParAndNormIntersVec.back().first = ptInt1.z ;
// vParAndNormIntersVec.back().second = vtN1 ;
// }
//}
// Se il movimento ortogonale all'asse interseco con le lingue di gatto.
double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ;
double dMyLengthSup = dObCoef * dSupRad / sqrt( 1 + dObCoef * dObCoef) ;
double dMyLengthInf = dObCoef * dInfRad / sqrt( 1 + dObCoef * dObCoef) ;
if ( abs( dDispLen * dAxDispDot) < 2 * EPS_SMALL && min( dMyLengthSup, dMyLengthInf) < 2 * EPS_SMALL) {
Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ;
// Intersezione con lingua la gatto superiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dSupH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dSupH * vtAx,
vtAx, dSupRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
// Intersezione con la lingua di gatto inferiore
nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dInfH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dInfH * vtAx,
- vtAx, dInfRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
}
// Altrimenti interseco con i cilindri ellittici.
else {
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0,
vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico inferiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, bOuterCutter != dAxDispDot > 0,
vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
}
// Intersezione con cilindro esterno
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false,
vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
return true ;
}
// Calotta sferica
//----------------------------------------------------------------------------
bool
VolZmap::SurfSphericalShell_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dHei, bool bOuterCutter)
{
// Verifico interferisca
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ))
return true ;
// Vettore spostamento
Vector3d vtDisp = ptE - ptS ;
Vector3d vtDispVers = vtDisp ;
double dDispLen = vtDispVers.Len() ;
vtDispVers /= dDispLen ;
// Prodotto scalare fra versore del movimento e asse della calotta sferica
double dAxDispDot = vtDispVers * vtAx ;
// Raggio del cilindro ellittico
double dBaseRad = sqrt( max( dRad * dRad - dHei * dHei, 0.)) ;
// Coseni limite
double dCosLim = dBaseRad / dRad ;
// Vettore dei piani di taglio della sfera in posizione iniziale
vector<Plane3d> vSphereCutPlanesVecSt ;
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS - dHei * vtAx, vtAx) ;
// Vettore dei piani di taglio della sfera in posizione finale
vector<Plane3d> vSphereCutPlanesVecEn ;
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE - dHei * vtAx, vtAx) ;
if ( abs( dAxDispDot) > dCosLim - EPS_ZERO) {
if ( bOuterCutter == dAxDispDot > 0)
return true ;
// Vettore dei piani di taglio del cilindro ellittico
vector<Plane3d> vEllipCylCutPlanesVec ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con sfera in posizione iniziale
int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con sfera in posizione finale
nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con cilindro ellittico superiore
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dBaseRad, vtDisp, false,
vEllipCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
else {
// Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale.
vSphereCutPlanesVecSt.emplace_back() ;
vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Aggiorno il vettore dei piani di taglio della sfera in posizione finale.
vSphereCutPlanesVecEn.emplace_back() ;
vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ;
// Versore della componente del moto perpendicolare all'asse
Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ;
double dOrtDispLen = vtOrtDispVers.Len() ;
vtOrtDispVers /= dOrtDispLen ;
// Vettore dei piani di taglio del cilindro ellittico superiore
Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ;
vtPlaneN.Normalize() ;
if ( bOuterCutter != dAxDispDot > 0)
vtPlaneN *= - 1 ;
double dC = vtDispVers * vtAx ;
double dS = sqrt( max( 1 - dC * dC, 0.)) ;
Point3d ptPlaneP = ptS - dHei * vtAx + ( dC * dHei / dS) * vtOrtDispVers ;
vector<Plane3d> vEllipCylCutPlanesVec ;
vEllipCylCutPlanesVec.emplace_back() ;
vEllipCylCutPlanesVec.back().Set( ptPlaneP, vtPlaneN) ;
// Vettore dei piani di taglio del cilindro
vector<Plane3d> vCylCutPlanesVec ;
vCylCutPlanesVec.emplace_back() ;
vCylCutPlanesVec.back().Set( ptPlaneP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
DexelSurfIntersVector vParAndNormIntersVec ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
// Intersezione con sfera in posizione iniziale
int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con sfera in posizione finale
nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn,
ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Intersezione con lingua di gatto se il movimento perpendicolare all'asse di simmetria
double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ;
double dMyLength = dObCoef * dRad / sqrt( 1 + dObCoef * dObCoef) ;
if ( abs( dDispLen * dAxDispDot) < 2 * EPS_SMALL && dMyLength < 2 * EPS_SMALL) {
Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ;
nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx,
vtAx, dBaseRad, ptInt1, vtN1) ;
if ( nIntNum == 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
}
}
// Intersezione con cilindro ellittico se il movimento generico
else {
nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dBaseRad, vtDisp, bOuterCutter == dAxDispDot > 0,
vEllipCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
}
// Intersezione con cilindro esterno
nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false,
vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ;
if ( nIntNum >= 1) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt1.z ;
vParAndNormIntersVec.back().second = vtN1 ;
if ( nIntNum == 2) {
vParAndNormIntersVec.emplace_back() ;
vParAndNormIntersVec.back().first = ptInt2.z ;
vParAndNormIntersVec.back().second = vtN2 ;
}
}
// Filtro le intersezioni trovate.
DexelSurfIntersVector vFilteredIntersVec ;
IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ;
// Sottraggo gli intervalli.
for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) {
SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first,
vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ;
}
}
}
}
return true ;
}
// ------------------------- Utensili additivi ---------------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx/*, double dHei, double dRad, double dCornerRad*/)
{
// Dimensioni lineari dell'utensile
double dHei = m_vTool[m_nCurrTool].GetHeigth() ;
double dRad = m_vTool[m_nCurrTool].GetRadius() ;
double dCornerRad = m_vTool[m_nCurrTool].GetCornRadius() ;
// Verifica sull'interferenza utensile Zmap
int nStartI, nStartJ, nEndI, nEndJ ;
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
return true ;
Vector3d vtV1 = ptE - ptS ;
double dLen1 = vtV1.Len() ;
vtV1 / dLen1 ;
Vector3d vtV2 = Z_AX ^ vtV1 ;
if ( dCornerRad < EPS_SMALL) {
if ( nGrid == 0) {
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ;
Vector3d vtEnC = vtStC - dLen1 * vtV1 ;
double dX1 = vtStC * vtV1 ;
double dX2 = vtStC * vtV2 ;
if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) ||
vtStC.SqLen() < dRad * dRad ||
vtEnC.SqLen() < dRad * dRad) {
AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, - Z_AX, Z_AX) ;
}
}
}
}
else {
Frame3d CylFrame, PolyFrame ;
CylFrame.Set( ptS - dHei * vtAx, vtAx) ;
PolyFrame.Set( ptS - dHei * vtAx, vtV1, vtAx ^ vtV1, vtAx) ;
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Point3d ptC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ;
Point3d ptInt1, ptInt2 ;
Vector3d vtN1, vtN2 ;
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2) ;
}
if ( IntersLineMyPolyhedron( ptC - dLen1 * vtV1, Z_AX, PolyFrame, dLen1, dRad, dHei, 0,
ptInt1, vtN1, ptInt2, vtN2)) {
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2) ;
}
}
}
}
}
else {
;
}
return true ;
/*
if ( nGrid == 0) {
Vector3d vtV1 = ptE - ptS ;
double dLen1 = vtV1.Len() ;
vtV1 / dLen1 ;
Vector3d vtV2 = Z_AX ^ vtV1 ;
double dSqareCornerRadProj = dCornerRad * dCornerRad - 0.25 * dHei * dHei ;
if ( dSqareCornerRadProj > 0) {
double dCylRad = dRad - dCornerRad + sqrt( dSquareCornerRadProj) ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ;
Vector3d vtEnC = vtStC - dLen1 * vtV1 ;
double dX1 = vtC * vtV1 ;
double dX2 = vtC * vtV2 ;
if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dCylRad) ||
vtStC.SqLen() < dCylRad * dCylRad ||
vtEnC.SqLen() < dCylRad * dCylRad) {
AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, Z_AX, - Z_AX) ;
}
else if ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) {
double dr = dCornerRad - ( dRad - abs( dX2)) ;
double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ;
Vector3d vtMinN = ( dX2 > 0 ? - dr : dr) * vtV2 + Vector3d( 0, 0, dDeltaH) ;
Vector3d vtMaxN = ( dX2 > 0 ? - dr : dr) * vtV2 - Vector3d( 0, 0, dDeltaH) ;
vtMinN.Normalize() ;
vtMaxN.Normalize() ;
AddIntervals( nGrid, i, j, ptS.z - 0.5 * dHei - dDeltaH, ptS.z - 0.5 * dHei + dDeltaH, vtMinN, vtMaxN) ;
}
else if ( vtStC.SqLen() < dRad * dRad || vtEnC.SqLen() < dRad * dRad) {
Vector3d vtR = dX1 > 0 ? vtEnC : vtStC ;
double dLenR = vtR.Len() ;
vtR /= dLenR ;
double dr = dCornerRad - ( dRad - dLenR) ;
double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ;
Vector3d vtMinN = - dr * vtR + Vector3d( 0, 0, dDeltaH) ;
Vector3d vtMaxN = - dr * vtR - Vector3d( 0, 0, dDeltaH) ;
vtMinN.Normalize() ;
vtMaxN.Normalize() ;
AddIntervals( nGrid, i, j, ptS.z - 0.5 * dHei - dDeltaH, ptS.z - 0.5 * dHei + dDeltaH, vtMinN, vtMaxN) ;
}
}
}
}
else {
double dCylRad = dRad - dCornerRad ;
// Ciclo sui punti
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ;
Vector3d vtEnC = vtStC - dLen1 * vtV1 ;
double dX1 = vtC * vtV1 ;
double dX2 = vtC * vtV2 ;
if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dCylRad) ||
vtStC.SqLen() < dCylRad * dCylRad ||
vtEnC.SqLen() < dCylRad * dCylRad) {
AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, Z_AX, - Z_AX) ;
}
else if ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) {
double dr = abs( dX2) - dCylRad ;
double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ;
Vector3d vtMinN = ( dX2 > 0 ? - dr : dr) * vtV2 + Vector3d( 0, 0, dDeltaH) ;
Vector3d vtMaxN = ( dX2 > 0 ? - dr : dr) * vtV2 - Vector3d( 0, 0, dDeltaH) ;
vtMinN.Normalize() ;
vtMaxN.Normalize() ;
AddIntervals( nGrid, i, j, ptS.z - dHei + dCornerRad - dDeltaH, ptS.z - dCornerRad + dDeltaH, vtMinN, vtMaxN) ;
}
else if ( vtStC.SqLen() < dRad * dRad || vtEnC.SqLen() < dRad * dRad) {
Vector3d vtR = dX1 > 0 ? vtEnC : vtStC ;
double dLenR = vtR.Len() ;
vtR /= dLenR ;
double dr = dLenR - dCylRad) ;
double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ;
Vector3d vtMinN = - dr * vtR + Vector3d( 0, 0, dDeltaH) ;
Vector3d vtMaxN = - dr * vtR - Vector3d( 0, 0, dDeltaH) ;
vtMinN.Normalize() ;
vtMaxN.Normalize() ;
AddIntervals( nGrid, i, j, ptS.z - dHei + dCornerRad - dDeltaH, ptS.z - dCornerRad + dDeltaH, vtMinN, vtMaxN) ;
}
}
}
}
}
else {
;
}
*/
}
// ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
inline BBox3d
GetCylMoveBBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, double dRad, double dH)
{
// Determinazione delle posizioni della punta del componente nelle posizioni iniziale e finale
Point3d ptP1T = ptP1 - dH * vtV ;
Point3d ptP2T = ptP2 - dH * vtV ;
// Calcolo del box del movimento dell'asse
BBox3d b3Box ;
b3Box.Add( ptP1) ;
b3Box.Add( ptP1T) ;
b3Box.Add( ptP2) ;
b3Box.Add( ptP2T) ;
// Aggiungo ingombro raggio
if ( AreSameOrOppositeVectorApprox( vtV, X_AX))
b3Box.Expand( 0, dRad, dRad) ;
else if ( AreSameOrOppositeVectorApprox( vtV, Y_AX))
b3Box.Expand( dRad, 0, dRad) ;
else if ( AreSameOrOppositeVectorApprox( vtV, Z_AX))
b3Box.Expand( dRad, dRad, 0) ;
else {
double dExpandX = dRad * sqrt( 1 - vtV.x * vtV.x) ;
double dExpandY = dRad * sqrt( 1 - vtV.y * vtV.y) ;
double dExpandZ = dRad * sqrt( 1 - vtV.z * vtV.z) ;
b3Box.Expand( dExpandX, dExpandY, dExpandZ) ;
}
// Restituisco il box calcolato
return b3Box ;
}
//----------------------------------------------------------------------------
inline BBox3d
GetSphereMoveBBox( const Point3d& ptP1, const Point3d& ptP2, double dRad)
{
// Calcolo del box del movimento del centro
BBox3d b3Box ;
b3Box.Add( ptP1) ;
b3Box.Add( ptP2) ;
// Aggiungo ingombro raggio
b3Box.Expand( dRad) ;
// Restituisco il box calcolato
return b3Box ;
}
//----------------------------------------------------------------------------
inline bool
VolZmap::TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
int& nStI, int& nStJ, int& nEnI, int& nEnJ)
{
return TestCompoBBox( nGrid, ptP1, ptP2, vtV, m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetHeigth(),
nStI, nStJ, nEnI, nEnJ) ;
}
//----------------------------------------------------------------------------
inline bool
VolZmap::TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
double dRad, double dTipRad, double dHei,
int& nStI, int& nStJ, int& nEnI, int& nEnJ)
{
// I punti e i vettori devono essere nel sistema di riferimento opportuno
// Controllo sull'ammissibilit del numero di griglia
if ( nGrid < 0 || nGrid > 2)
return false ;
// BBox dello Zmap
BBox3d b3Zmap( 0, 0, m_dMinZ[nGrid], m_nNx[nGrid] * m_dStep, m_nNy[nGrid] * m_dStep, m_dMaxZ[nGrid]) ;
// BBox dell'utensile nel suo movimento
double dMaxRad = max( dRad, dTipRad) ;
BBox3d b3Box = ( vtV.IsSmall() ? GetSphereMoveBBox( ptP1, ptP2, dRad) : GetCylMoveBBox( ptP1, ptP2, vtV, dMaxRad, dHei)) ;
// Verifica dell'interferenza dell'utensile con lo Zmap
if ( ! b3Zmap.FindIntersection( b3Box, b3Box))
return false ;
// Limiti su indici
nStI = max( 0, int( b3Box.GetMin().x / m_dStep)) ;
nEnI = min( m_nNx[nGrid] - 1, int( b3Box.GetMax().x / m_dStep)) ;
nStJ = max( 0, int( b3Box.GetMin().y / m_dStep)) ;
nEnJ = min( m_nNy[nGrid] - 1, int( b3Box.GetMax().y / m_dStep)) ;
return true ;
}
//----------------------------------------------------------------------------
inline bool
VolZmap::TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
double dLenX, double dLenY, double dLenZ,
int& nStI, int& nStJ, int& nEnI, int& nEnJ)
{
// I punti e i vettori devono essere nel sistema di riferimento opportuno
// Determino le posizioni iniziale e
// finale della punta dell'utensile.
Point3d ptSTip = ptS - vtD * dLenZ ;
Point3d ptETip = ptE - vtD * dLenZ ;
double dSemiDiag = sqrt( dLenX * dLenX + dLenY * dLenY) / 2 ;
// Determinazione dei limiti del pi piccolo parallelepipedo contenente il movimento
double dMinX = min( min( ptS.x, ptSTip.x), min( ptE.x, ptETip.x)) - dSemiDiag ;
double dMinY = min( min( ptS.y, ptSTip.y), min( ptE.y, ptETip.y)) - dSemiDiag ;
double dMinZ = min( min( ptS.z, ptSTip.z), min( ptE.z, ptETip.z)) - dSemiDiag ;
double dMaxX = max( max( ptS.x, ptSTip.x), max( ptE.x, ptETip.x)) + dSemiDiag ;
double dMaxY = max( max( ptS.y, ptSTip.y), max( ptE.y, ptETip.y)) + dSemiDiag ;
double dMaxZ = max( max( ptS.z, ptSTip.z), max( ptE.z, ptETip.z)) + dSemiDiag ;
int nMaxNx = m_nNx[nGrid] ;
int nMaxNy = m_nNy[nGrid] ;
double dMaxXValue = nMaxNx * m_dStep ;
double dMaxYValue = nMaxNy * m_dStep ;
double dMinZValue = m_dMinZ[nGrid] ;
double dMaxZValue = m_dMaxZ[nGrid] ;
// 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<int> ( dMinX / m_dStep)) ;
nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : static_cast<int> ( dMaxX / m_dStep)) ;
nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast<int> ( dMinY / m_dStep)) ;
nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : static_cast<int> ( dMaxY / m_dStep)) ;
return true ;
}