5b68e33d1f
- correzione al VM 5 assi.
7632 lines
325 KiB
C++
7632 lines
325 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 "CurveBezier.h"
|
|
#include "SurfBezier.h"
|
|
#include "VolZmap.h"
|
|
#include "GeoConst.h"
|
|
#include "IntersLineBox.h"
|
|
#include "/EgtDev/Include/EGkIntervals.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EGkSurfBezier.h"
|
|
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
|
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include "/EgtDev/Include/EgtPerfCounter.h"
|
|
#include <future>
|
|
#include <numeric>
|
|
|
|
#define SAVETRIMMINGTOOL 0
|
|
|
|
#if SAVETRIMMINGTOOL
|
|
std::vector<IGeoObj*> vGeo ;
|
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
|
#endif
|
|
|
|
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,
|
|
int nToolNum, bool bSkipSwap)
|
|
{
|
|
// 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 ( ! bSkipSwap && nGrid == 1) {
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
}
|
|
else if ( ! bSkipSwap && 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 = nToolNum ;
|
|
}
|
|
// 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 = nToolNum ;
|
|
}
|
|
// 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, nToolNum,
|
|
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 = nToolNum ;
|
|
++ 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,
|
|
int nToolNum, bool bSkipSwap)
|
|
{
|
|
// 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) ;
|
|
}
|
|
|
|
// Restringo minimo e massimo entro i limiti della mappa
|
|
if ( dMin < m_dMinZ[nGrid]) {
|
|
dMin = m_dMinZ[nGrid] ;
|
|
if ( ! bSkipSwap)
|
|
vtNmi = - Z_AX ;
|
|
}
|
|
else if ( dMin > m_dMaxZ[nGrid]) {
|
|
dMin = m_dMaxZ[nGrid] ;
|
|
if ( ! bSkipSwap)
|
|
vtNmi = - Z_AX ;
|
|
}
|
|
if ( dMax < m_dMinZ[nGrid]) {
|
|
dMax = m_dMinZ[nGrid] ;
|
|
if ( ! bSkipSwap)
|
|
vtNma = Z_AX ;
|
|
}
|
|
else if ( dMax > m_dMaxZ[nGrid]) {
|
|
dMax = m_dMaxZ[nGrid] ;
|
|
if ( ! bSkipSwap)
|
|
vtNma = Z_AX ;
|
|
}
|
|
|
|
// Controllo che dMin e dMax non siano quasi coincidenti
|
|
if ( abs( dMax - dMin) < EPS_SMALL)
|
|
return true ;
|
|
|
|
// Riporto le coordinate cicliche nell'ordine di partenza
|
|
if ( !bSkipSwap && nGrid == 1) {
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
}
|
|
else if ( !bSkipSwap && nGrid == 2) {
|
|
swap( vtNmi.y, vtNmi.z) ;
|
|
swap( vtNmi.x, vtNmi.z) ;
|
|
swap( vtNma.y, vtNma.z) ;
|
|
swap( vtNma.x, vtNma.z) ;
|
|
}
|
|
|
|
// Calcolo nPos
|
|
int nPos = nJ * m_nNx[nGrid] + nI ;
|
|
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
|
|
|
|
bool bModified = false ;
|
|
|
|
// Non esistono segmenti
|
|
if ( vDexel.empty()) {
|
|
|
|
vDexel.emplace_back() ;
|
|
vDexel.back().dMin = dMin ;
|
|
vDexel.back().vtMinN = vtNmi ;
|
|
vDexel.back().nToolMin = nToolNum ;
|
|
vDexel.back().dMax = dMax ;
|
|
vDexel.back().vtMaxN = vtNma ;
|
|
vDexel.back().nToolMax = nToolNum ;
|
|
|
|
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 = nToolNum ;
|
|
vDexel.back().nToolMax = nToolNum ;
|
|
//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 = nToolNum ;
|
|
NewSegment.nToolMax = nToolNum ;
|
|
//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 = nToolNum ;
|
|
}
|
|
// 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 = nToolNum ;
|
|
bModified = true ;
|
|
}
|
|
else {
|
|
itNextToLastLeft->dMax = itPrevToFirstRight->dMax ;
|
|
itNextToLastLeft->vtMaxN = itPrevToFirstRight->vtMaxN ;
|
|
itNextToLastLeft->nToolMax = nToolNum ;
|
|
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 = nToolNum ;
|
|
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 = nToolNum ;
|
|
bModified = true ;
|
|
}
|
|
}
|
|
// L'ultimo intervallo non sporge a destra.
|
|
else {
|
|
vDexel.begin()->dMax = dMax ;
|
|
vDexel.begin()->vtMaxN = vtNma ;
|
|
vDexel.begin()->nToolMax = nToolNum ;
|
|
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 = nToolNum ;
|
|
NewSegment.nToolMax = nToolNum ;
|
|
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 = nToolNum ;
|
|
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 = nToolNum ;
|
|
bModified = true ;
|
|
}
|
|
else {
|
|
vDexel.begin()->dMax = itPrevToFirstRight->dMax ;
|
|
vDexel.begin()->vtMaxN = itPrevToFirstRight->vtMaxN ;
|
|
vDexel.begin()->nToolMax = nToolNum ;
|
|
bModified = true ;
|
|
}
|
|
auto itFirstToCancel = vDexel.begin() ;
|
|
++ itFirstToCancel ;
|
|
vDexel.erase( itFirstToCancel, itFirstRight) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se nessuna modifica, esco
|
|
if ( ! bModified)
|
|
return true ;
|
|
|
|
// 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::ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK,
|
|
double& dMin, double& dMax, Vector3d& vtMin, Vector3d& vtMax)
|
|
{
|
|
// Se non Tridex, esco
|
|
if ( ! IsTriDexel())
|
|
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 ;
|
|
|
|
// Valori di Default
|
|
DBLVECTOR vdMin = { -1., -1., -1., -1.} ;
|
|
DBLVECTOR vdMax = { -1., -1., -1., -1.} ;
|
|
VCT3DVECTOR vNMin = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ;
|
|
VCT3DVECTOR vNMax = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ;
|
|
|
|
// Se esiste un voxel precedente lungo x-locale ( nI - 1, nJ)
|
|
if ( nI != 0) {
|
|
// Ne recupero la posizione
|
|
int nPos = nJ * m_nNx[nGrid] + ( nI - 1) ;
|
|
// Scorro tutti gli intervalli del dexel in (nI - 1, nJ)
|
|
for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) {
|
|
// Se nei pressi dell'estremo superiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ;
|
|
vdMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ;
|
|
}
|
|
// Se nei pressi dell'estremo inferiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ;
|
|
vdMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se esiste un voxel successivo lungo x-locale, ne recupero la posizione
|
|
int nPos = nJ * m_nNx[nGrid] + ( nI + 1) ;
|
|
if ( nPos < int( VolZmapRef->m_Values[nGrid].size())) {
|
|
// Cerco l'intervallo corretto sullo Zmap di riferimento
|
|
for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) {
|
|
// Se nei pressi dell'estremo superiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ;
|
|
vdMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ;
|
|
}
|
|
// Se nei pressi dell'estremo inferiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ;
|
|
vdMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se esiste un voxel precedente lungo y-locale
|
|
if ( nJ != 0) {
|
|
// Ne recupero la posizione
|
|
int nPos = ( nJ - 1) * m_nNx[nGrid] + nI ;
|
|
// Cerco l'intervallo corretto sullo Zmap di riferimento
|
|
for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) {
|
|
// Se nei pressi dell'estremo superiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ;
|
|
vdMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ;
|
|
}
|
|
// Se nei pressi dell'estremo inferiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ;
|
|
vdMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se esiste un voxel successivo lungo y-locale, ne recupero la posizione
|
|
nPos = ( nJ + 1) * m_nNx[nGrid] + nI ;
|
|
if ( nPos < int( VolZmapRef->m_Values[nGrid].size())) {
|
|
// Cerco l'intervallo corretto sullo Zmap di riferimento
|
|
for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) {
|
|
// Se nei pressi dell'estremo superiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ;
|
|
vdMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ;
|
|
}
|
|
// Se nei pressi dell'estremo inferiore
|
|
if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep &&
|
|
VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) {
|
|
// Memorizzo i parametri
|
|
vNMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ;
|
|
vdMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- Scelgo le normali che si discostano il meno possibile dalla normale della faccia del voxel
|
|
|
|
// 1) Angolo minimo tra la normale trovata la faccia del voxel
|
|
double dMinAngle = ANG_FULL ;
|
|
// 2) Vettore di riferimento per la direzione della normale
|
|
vtMax = ( nGrid == 0 ? m_MapFrame.VersZ() :
|
|
nGrid == 1 ? m_MapFrame.VersX() :
|
|
nGrid == 2 ? m_MapFrame.VersY() :
|
|
V_INVALID) ;
|
|
Vector3d vtRef = vtMax ;
|
|
// 3) Determino il massimo per questo intervallo
|
|
dMax = ( nK + 1) * m_dStep ;
|
|
for ( int i = 0 ; i < 4 ; ++ i) {
|
|
// Scorro le normali valide trovate
|
|
if ( vNMax[i].IsValid()) {
|
|
// Angolo corrente tra la normale di riferimento e quella della faccia del voxel
|
|
double dCurrAngle ; vNMax[i].GetAngle( vtRef, dCurrAngle) ;
|
|
// Se angolo minore del minimo trovato...
|
|
if ( abs( dCurrAngle) < dMinAngle) {
|
|
// ... Aggiorno i parametri
|
|
dMinAngle = dCurrAngle ;
|
|
vtMax = vNMax[i] ;
|
|
dMax = vdMax[i] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ripeto lo stesso ragionamento per le normali dei massimi
|
|
dMinAngle = ANG_FULL ;
|
|
vtRef.Invert() ;
|
|
dMin = nK * m_dStep ;
|
|
vtMin = vtRef ;
|
|
for ( int i = 0 ; i < 4 ; ++ i) {
|
|
if ( vNMin[i].IsValid()) {
|
|
double dCurrAngle ;
|
|
vNMin[i].GetAngle( vtRef, dCurrAngle) ;
|
|
if ( abs( dCurrAngle) < dMinAngle) {
|
|
dMinAngle = dCurrAngle ;
|
|
vtMin = vNMin[i] ;
|
|
dMin = vdMin[i] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin,
|
|
double dZMax, double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
|
|
const Vector3d& vtToolMax)
|
|
{
|
|
// Se non Tridex, esco
|
|
if ( ! IsTriDexel())
|
|
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 ;
|
|
|
|
// Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia)
|
|
int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio +
|
|
( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
|
|
|
|
// Scorro i Voxel correnti
|
|
for ( int nVox = 0 ; nVox < nVoxNum ; ++ nVox) {
|
|
// Considero solo i Voxel interni all'intervallo corrente
|
|
if ( dZMin - m_dStep / 2. < nVox * m_dStep && nVox * m_dStep < dZMax + m_dStep / 2.) {
|
|
// recupero gli indici per la griglia successiva
|
|
int nMyGrid = ( nGrid + 1) % 3 ;
|
|
int nMyI = nJ ;
|
|
int nMyJ = nVox ;
|
|
int nMyK = nI ;
|
|
double dMyMinZ = nMyK * m_dStep ; // shift di -Step / 2
|
|
double dMyMaxZ = ( nMyK + 1) * m_dStep ; // shift di Step / 2
|
|
Vector3d vtMyMaxN = ( vtToolMax.IsValid() ? vtToolMax :
|
|
nMyGrid == 0 ? m_MapFrame.VersZ() :
|
|
nMyGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY()) ;
|
|
Vector3d vtMyMinN = ( vtToolMin.IsValid() ? vtToolMin : - vtMyMaxN) ;
|
|
if ( bAdd)
|
|
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
else
|
|
SubtractIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
// recupero gli indici della griglia precedente
|
|
nMyGrid = ( nGrid + 2) % 3 ;
|
|
nMyI = nVox ;
|
|
nMyJ = nI ;
|
|
nMyK = nJ ;
|
|
dMyMinZ = nMyK * m_dStep ; // shift di -Step / 2
|
|
dMyMaxZ = ( nMyK + 1) * m_dStep ; // shift di Step / 2
|
|
vtMyMaxN = ( vtToolMax.IsValid() ? vtToolMax :
|
|
nMyGrid == 0 ? m_MapFrame.VersZ() :
|
|
nMyGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY()) ;
|
|
vtMyMinN = ( vtToolMin.IsValid() ? vtToolMin : - vtMyMaxN) ;
|
|
if ( bAdd)
|
|
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
else
|
|
SubtractIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum)
|
|
{
|
|
// Se non Tridex, esco
|
|
if ( ! IsTriDexel())
|
|
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 ;
|
|
|
|
// Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia)
|
|
int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio +
|
|
( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
|
|
|
|
// Scorro i Voxel correnti
|
|
for ( int nVox = - 1 ; nVox < nVoxNum - 1 ; ++ nVox) {
|
|
// Considero solo i Voxel interni all'intervallo corrente
|
|
if ( ( nVox + 1) * m_dStep > dZMin && ( nVox - 1) * m_dStep < dZMax) {
|
|
// Recupero gli indici per la griglia successiva
|
|
int nMyGrid = ( nGrid + 1) % 3 ;
|
|
int nMyI = nJ ;
|
|
int nMyJ = nVox ;
|
|
int nMyK = nI ;
|
|
double dMyMinZ = nMyK * m_dStep ;
|
|
double dMyMaxZ = ( nMyK + 1) * m_dStep ;
|
|
Vector3d vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
|
|
nMyGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY()) ;
|
|
Vector3d vtMyMinN = - vtMyMaxN ;
|
|
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
// Recupero gli indici della griglia precedente
|
|
nMyGrid = ( nGrid + 2) % 3 ;
|
|
nMyI = nVox ;
|
|
nMyJ = nI ;
|
|
nMyK = nJ ;
|
|
dMyMinZ = nMyK * m_dStep ;
|
|
dMyMaxZ = ( nMyK + 1) * m_dStep ;
|
|
vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
|
|
nMyGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY()) ;
|
|
vtMyMinN = - vtMyMaxN ;
|
|
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
}
|
|
}
|
|
// Aggiungo l'intervallo corrente
|
|
Vector3d vtMyMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() :
|
|
nGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY()) ;
|
|
Vector3d vtMyMinN = - vtMyMaxN ;
|
|
AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc)
|
|
{
|
|
// Verifico che lo ZMap corrente sia valido
|
|
if ( ! IsValid())
|
|
return false ;
|
|
|
|
// 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 ;
|
|
|
|
// Calcolo il punto
|
|
ptLoc = m_MapFrame.Orig() ;
|
|
if ( nGrid == 0)
|
|
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersX() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersY() + dZ * m_MapFrame.VersZ()) ;
|
|
else if ( nGrid == 1)
|
|
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersY() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersZ() + dZ * m_MapFrame.VersX()) ;
|
|
else
|
|
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersZ() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersX() + dZ * m_MapFrame.VersY()) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
|
|
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
|
|
Vector3d& vtN, double& dNewZ)
|
|
{
|
|
// Verifico che lo ZMap corrente sia valido
|
|
if ( ! IsValid())
|
|
return false ;
|
|
|
|
// Controllo che il numero di griglia sia entro i limiti
|
|
if ( nGrid < 0 || nGrid > 2)
|
|
return false ;
|
|
|
|
// Inizializzo il vettore da restituire
|
|
vtN = V_NULL ;
|
|
dNewZ = INFINITO ;
|
|
|
|
// Proietto la direzione lungo la mappa della griglia corrente
|
|
Vector3d vtDirProj = OrthoCompo( vtDir, ( nGrid == 0 ? m_MapFrame.VersZ() :
|
|
nGrid == 1 ? m_MapFrame.VersX() :
|
|
m_MapFrame.VersY())) ;
|
|
// Sposto il punto corrente nella direzione opposta a quella trovata
|
|
Point3d ptLoc ;
|
|
if ( ! GetLocalPoint( nGrid, nI, nJ, dZ, ptLoc))
|
|
return false ;
|
|
Point3d ptCenterLoc = ptLoc ;
|
|
ptCenterLoc.Translate( - vtDirProj * dThick) ;
|
|
|
|
// Recupero il Box nel punto
|
|
BBox3d BBoxLoc ; BBoxLoc.Add( ptCenterLoc) ;
|
|
double dExpandX = ( m_MapFrame.VersX() * X_AX) * dThick * ( vtDirProj * X_AX) ;
|
|
double dExpandY = ( m_MapFrame.VersY() * Y_AX) * dThick * ( vtDirProj * Y_AX) ;
|
|
double dExpandZ = ( m_MapFrame.VersZ() * Z_AX) * dThick * ( vtDirProj * Z_AX) ;
|
|
BBoxLoc.Expand( max( ( m_dStep + EPS_SMALL), dExpandX),
|
|
max( ( m_dStep + EPS_SMALL), dExpandY),
|
|
max( ( m_dStep + EPS_SMALL), dExpandZ)) ;
|
|
|
|
// Porto il Box nel Frame della Mappa corrente
|
|
BBox3d BBoxInGrid = GetToLoc( BBoxLoc, m_MapFrame) ;
|
|
// Recupero i suoi estremi
|
|
Point3d ptBoxLocMax = BBoxInGrid.GetMax() ;
|
|
Point3d ptBoxLocMin = BBoxInGrid.GetMin() ;
|
|
// Determino gli intervalli locali in X e Y locali alla Griglia correnti
|
|
double dMinXLoc = ( nGrid == 0 ? ptBoxLocMin.x : nGrid == 1 ? ptBoxLocMin.y : ptBoxLocMin.z) ;
|
|
double dMinYLoc = ( nGrid == 0 ? ptBoxLocMin.y : nGrid == 1 ? ptBoxLocMin.z : ptBoxLocMin.x) ;
|
|
double dMaxXLoc = ( nGrid == 0 ? ptBoxLocMax.x : nGrid == 1 ? ptBoxLocMax.y : ptBoxLocMax.z) ;
|
|
double dMaxYLoc = ( nGrid == 0 ? ptBoxLocMax.y : nGrid == 1 ? ptBoxLocMax.z : ptBoxLocMax.x) ;
|
|
|
|
// Recupero gli Spilloni coinvolti nel Box
|
|
int nStartI = max( 0, int( dMinXLoc / m_dStep)) ;
|
|
int nEndI = min( m_nNx[nGrid] - 1, int( dMaxXLoc / m_dStep)) ;
|
|
int nStartJ = max( 0, int( dMinYLoc / m_dStep)) ;
|
|
int nEndJ = min( m_nNy[nGrid] - 1, int( dMaxYLoc / m_dStep)) ;
|
|
double dSqMinDist = INFINITO ;
|
|
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
|
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
// Determino la posizione corrente dello Spillone
|
|
int nPos = j * m_nNx[nGrid] + i ;
|
|
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
|
|
// Scorro i suoi Intervalli
|
|
for ( int nInterval = 0 ; nInterval < ssize( vDexel) ; ++ nInterval) {
|
|
// Se l'Intervallo presenta un indice del Tool da evitare, passo al successivo
|
|
if ( ( bMinVsMax && vDexel[nInterval].nToolMin != nTool) ||
|
|
( ! bMinVsMax && vDexel[nInterval].nToolMax != nTool))
|
|
continue ;
|
|
// Recupero l'estremo da analizzare
|
|
double dZInterval = ( bMinVsMax ? vDexel[nInterval].dMin : vDexel[nInterval].dMax) ;
|
|
// Recupero il punto associato
|
|
Point3d ptInterval ;
|
|
if ( ! GetLocalPoint( nGrid, i, j, dZInterval, ptInterval))
|
|
return false ;
|
|
// Se il punto è dentro nel Box, aggiungo il contributo della normale presente
|
|
if ( BBoxLoc.Encloses( ptInterval)) {
|
|
double dCurrSqDist = ( SqDist( ptInterval, ptLoc)) ;
|
|
if ( dCurrSqDist < dSqMinDist) {
|
|
dSqMinDist = dCurrSqDist ;
|
|
vtN = ( bMinVsMax ? vDexel[nInterval].vtMinN : vDexel[nInterval].vtMaxN) ;
|
|
dNewZ = dZInterval ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( ! vtN.IsSmall() && dZ < INFINITO - 1) ;
|
|
}
|
|
|
|
|
|
// ------------------------- 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
|
|
GetCylMoveRotBBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2, double dRad, double dH)
|
|
{
|
|
// costruisco gli archi che definiscono il top e bottom del tool di partenza nel loro riferimento e li porto nel frame
|
|
BBox3d bbStart = GetCylMoveBBox( ptP1, ptP1, vtV1, dRad, dH) ;
|
|
BBox3d bbEnd = GetCylMoveBBox( ptP2, ptP2, vtV2, dRad, dH) ;
|
|
|
|
// sommo i due box e li restituisco
|
|
BBox3d bbVol ;
|
|
bbVol.Add( bbStart) ;
|
|
bbVol.Add( bbEnd) ;
|
|
|
|
return bbVol ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
return TestCompoBBox( nGrid, ptP1, ptP2, vtV, V_NULL,
|
|
CurrTool.GetRadius(), CurrTool.GetTipRadius(), CurrTool.GetHeigth(),
|
|
nStI, nStJ, nEnI, nEnJ) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, const Vector3d& vtV2,
|
|
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 ;
|
|
if ( vtV.IsSmall())
|
|
b3Box = GetSphereMoveBBox( ptP1, ptP2, dRad) ;
|
|
else if ( AreSameVectorExact( vtV2, V_NULL))
|
|
b3Box = GetCylMoveBBox( ptP1, ptP2, vtV, dMaxRad, dHei) ;
|
|
else
|
|
b3Box = GetCylMoveRotBBox( ptP1, ptP2, vtV, vtV2, dRad, dHei) ;
|
|
|
|
// Verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( ! b3Zmap.Overlaps( 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 : int( dMinX / m_dStep)) ;
|
|
nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : int( dMaxX / m_dStep)) ;
|
|
nStJ = ( dMinY < EPS_SMALL ? 0 : int( dMinY / m_dStep)) ;
|
|
nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : int ( dMaxY / m_dStep)) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ------------------------- LAVORAZIONI --------------------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingStep( int nCurrTool,
|
|
const Point3d& ptPs, const Vector3d& vtDs,
|
|
const Point3d& ptPe, const Vector3d& vtDe)
|
|
{
|
|
return MillingStep( nCurrTool, ptPs, vtDs, Vector3d(), ptPe, vtDe, Vector3d()) ;
|
|
}
|
|
|
|
//static double dTotCount = 0. ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingStep( int nCurrTool,
|
|
const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
|
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe)
|
|
{
|
|
// Controllo utensile
|
|
if ( nCurrTool < 0 || nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
m_nCurrTool = nCurrTool ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Se non è definito l'utensile, non posso fare alcunchè
|
|
if ( CurrTool.GetType() == Tool::UNDEF)
|
|
return false ;
|
|
// 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 ( CurrTool.GetType() == Tool::MORTISER || CurrTool.GetType() == Tool::CHISEL) {
|
|
if ( vtAs.IsSmall() || vtAe.IsSmall())
|
|
return false ;
|
|
}
|
|
|
|
// Punti e vettori descriventi il moto nel sistema intrinseco dello Zmap
|
|
Point3d ptPLs = GetToLoc( ptPs, m_MapFrame) ;
|
|
Point3d ptPLe = GetToLoc( ptPe, m_MapFrame) ;
|
|
Vector3d vtDLs = GetToLoc( vtDs, m_MapFrame) ;
|
|
vtDLs.Normalize() ;
|
|
Vector3d vtDLe = GetToLoc( vtDe, m_MapFrame) ;
|
|
vtDLe.Normalize() ;
|
|
Vector3d vtALs = GetToLoc( vtAs, m_MapFrame) ;
|
|
vtALs.Normalize() ;
|
|
Vector3d vtALe = GetToLoc( vtAe, 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) ;
|
|
// altrimenti anche rotazione
|
|
else
|
|
bOk = MillingGeneralMotionStep( ptPLs, vtDLs, vtALs, ptPLe, vtDLe, vtALe) ;
|
|
|
|
//{
|
|
//// debug per 5 assi
|
|
//double dPartCount = Counter.Stop() ;
|
|
//if ( ! AreSameVectorApprox( vtDLs, vtDLe)) {
|
|
// dTotCount += dPartCount ;
|
|
// string sOut = "Calc5Axis=" + ToString( dTotCount, 3) ;
|
|
// LOG_INFO( GetEGkLogger(), sOut.c_str())
|
|
//}
|
|
////debug per 5 assi
|
|
|
|
//dTotCount += dPartCount ;
|
|
//string sOut = "Calc=" + ToString( dTotCount, 3) ;
|
|
//LOG_INFO( GetEGkLogger(), sOut.c_str())
|
|
//Counter.Start() ;
|
|
//}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
GetAlongAcrossRotation( const Vector3d& vtDir1, const Vector3d& vtDir2, const Vector3d& vtRef,
|
|
double& dAlongAngDeg, double& dAcrossAngDeg)
|
|
{
|
|
Vector3d vtAxis = vtRef ;
|
|
if ( vtAxis.Normalize()) {
|
|
bool bDet ; vtDir1.GetRotation( vtDir2, vtAxis, dAcrossAngDeg, bDet) ;
|
|
Vector3d vtDirM = GetRotate( vtDir1, vtAxis, dAcrossAngDeg) ;
|
|
vtDirM.GetAngle( vtDir2, dAlongAngDeg) ;
|
|
}
|
|
else {
|
|
vtDir1.GetAngle( vtDir2, dAlongAngDeg) ;
|
|
dAcrossAngDeg = 0 ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
UpdateMaxMin( Point3d& ptBez, Vector3d& vtN, PNTVEC3DVECTOR& vInters)
|
|
{
|
|
if ( ! AreSameVectorExact( vtN, V_NULL))
|
|
vInters.emplace_back( PNTVEC3D( ptBez, vtN)) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::InitializeAuxPoints( Point3d ptTop1s[3], Point3d ptTop1e[3], Point3d ptTop2s[3], Point3d ptTop2e[3],
|
|
Point3d ptBottom1s[3], Point3d ptBottom1e[3], Point3d ptBottom2s[3], Point3d ptBottom2e[3])
|
|
{
|
|
// per ogni array il punto epr la prima griglia è già settato, devo aggiungere i punti per le altre due, permutando le coordinate
|
|
if ( m_nMapNum > 1) {
|
|
ptTop1s[1].x = ptTop1s[0].y ; ptTop1s[1].y = ptTop1s[0].z ; ptTop1s[1].z = ptTop1s[0].x ;
|
|
ptTop1s[2].x = ptTop1s[0].z ; ptTop1s[2].y = ptTop1s[0].x ; ptTop1s[2].z = ptTop1s[0].y ;
|
|
ptTop1e[1].x = ptTop1e[0].y ; ptTop1e[1].y = ptTop1e[0].z ; ptTop1e[1].z = ptTop1e[0].x ;
|
|
ptTop1e[2].x = ptTop1e[0].z ; ptTop1e[2].y = ptTop1e[0].x ; ptTop1e[2].z = ptTop1e[0].y ;
|
|
ptTop2s[1].x = ptTop2s[0].y ; ptTop2s[1].y = ptTop2s[0].z ; ptTop2s[1].z = ptTop2s[0].x ;
|
|
ptTop2s[2].x = ptTop2s[0].z ; ptTop2s[2].y = ptTop2s[0].x ; ptTop2s[2].z = ptTop2s[0].y ;
|
|
ptTop2e[1].x = ptTop2e[0].y ; ptTop2e[1].y = ptTop2e[0].z ; ptTop2e[1].z = ptTop2e[0].x ;
|
|
ptTop2e[2].x = ptTop2e[0].z ; ptTop2e[2].y = ptTop2e[0].x ; ptTop2e[2].z = ptTop2e[0].y ;
|
|
ptBottom1s[1].x = ptBottom1s[0].y ; ptBottom1s[1].y = ptBottom1s[0].z ; ptBottom1s[1].z = ptBottom1s[0].x ;
|
|
ptBottom1s[2].x = ptBottom1s[0].z ; ptBottom1s[2].y = ptBottom1s[0].x ; ptBottom1s[2].z = ptBottom1s[0].y ;
|
|
ptBottom1e[1].x = ptBottom1e[0].y ; ptBottom1e[1].y = ptBottom1e[0].z ; ptBottom1e[1].z = ptBottom1e[0].x ;
|
|
ptBottom1e[2].x = ptBottom1e[0].z ; ptBottom1e[2].y = ptBottom1e[0].x ; ptBottom1e[2].z = ptBottom1e[0].y ;
|
|
ptBottom2s[1].x = ptBottom2s[0].y ; ptBottom2s[1].y = ptBottom2s[0].z ; ptBottom2s[1].z = ptBottom2s[0].x ;
|
|
ptBottom2s[2].x = ptBottom2s[0].z ; ptBottom2s[2].y = ptBottom2s[0].x ; ptBottom2s[2].z = ptBottom2s[0].y ;
|
|
ptBottom2e[1].x = ptBottom2e[0].y ; ptBottom2e[1].y = ptBottom2e[0].z ; ptBottom2e[1].z = ptBottom2e[0].x ;
|
|
ptBottom2e[2].x = ptBottom2e[0].z ; ptBottom2e[2].y = ptBottom2e[0].x ; ptBottom2e[2].z = ptBottom2e[0].y ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|
const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Descrizione geometrica del moto
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
// Vettore delle normali agli archi
|
|
const VCT3DVECTOR& vArcNorm = CurrTool.GetArcNormalVec() ;
|
|
// Poiché 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 = CurrTool.GetApproxOutline() ;
|
|
int nCrv = -1 ;
|
|
const ICurve* pPrevCurve = nullptr ;
|
|
const ICurve* pCurve = ToolProfile.GetCurve( ++ nCrv) ;
|
|
double dCumHeight = 0 ; // altezza cumulativa dei tratti già considerati
|
|
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 = 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 = true ;
|
|
const ICurve* pNextCurve = ToolProfile.GetCurve( ++ nCrv) ;
|
|
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)
|
|
CompCyl_5AxisMilling( nGrid, ptI, ptF, vtLs, vtLe, dHeight, dRadius, nToolNum, n5AxisType) ;
|
|
}
|
|
// se altrimenti X decrescente, è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
CompConus_5AxisMilling( nGrid, ptI, ptF, vtLs, vtLe, dHeight, dMaxRad, dMinRad,
|
|
bTapB, bTapT, vtNormSt, vtNormEn, nToolNum, n5AxisType) ;
|
|
}
|
|
// altrimenti X crescente, è un cono con vettore opposto a quello dell'utensile
|
|
else {
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
Point3d ptIn = ptI - vtLs * dHeight;
|
|
Point3d ptFn = ptF - vtLe * dHeight;
|
|
vtNormEn.z = - vtNormEn.z ;
|
|
vtNormSt.z = - vtNormSt.z ;
|
|
Vector3d vNewVtLs = - vtLs ;
|
|
Vector3d vNewVtLe = - vtLe ;
|
|
CompConus_5AxisMilling( nGrid, ptIn, ptFn, vNewVtLs, vNewVtLe, dHeight, dMaxRad, dMinRad,
|
|
bTapT, bTapB, vtNormEn, vtNormSt, nToolNum, n5AxisType) ;
|
|
}
|
|
// Passo alla curva successiva
|
|
pPrevCurve = pCurve ;
|
|
pCurve = pNextCurve ;
|
|
}
|
|
else {
|
|
// Passo alla curva successiva
|
|
pPrevCurve = pCurve ;
|
|
pCurve = ToolProfile.GetCurve( ++ nCrv) ;
|
|
}
|
|
}
|
|
|
|
// 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 - vtLs * ( ptStart.y - ptCen.y ) ;
|
|
Point3d ptCenE = ptF - vtLe * ( ptStart.y - ptCen.y ) ;
|
|
// Eseguo l'asportazione del materiale
|
|
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius, nToolNum) ;
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
// Passo alla curva successiva
|
|
pPrevCurve = pCurve ;
|
|
pCurve = ToolProfile.GetCurve( ++ nCrv) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
dCumHeight += dHeight ;
|
|
ptI = ptS - vtLs * dCumHeight ;
|
|
ptF = ptE - vtLe * dCumHeight ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static void
|
|
SortGroupInters( PNTVEC3DVECTOR& vInters, INTINTVECTOR& vStartEnds, const Vector3d& vMainAx)
|
|
{
|
|
if ( AreSameVectorExact(vMainAx, Z_AX))
|
|
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.z < b.first.z ; }) ;
|
|
else if ( AreSameVectorExact(vMainAx, Y_AX))
|
|
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.y < b.first.y ; }) ;
|
|
else if ( AreSameVectorExact(vMainAx, X_AX))
|
|
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.x < b.first.x ; }) ;
|
|
// devo controllare che le intersezioni estreme abbiano direzione opposta
|
|
// in caso contrario potrei avere ad uno dei due estremi due punti quasi coincidenti e stare prendendo per più esterno quello con la normale sbagliata
|
|
bool bExtremesAreOpposite = ( vInters.front().second * vMainAx) * (vInters.back().second * vMainAx) < 0 ;
|
|
if ( ! bExtremesAreOpposite) {
|
|
// se ad uno dei due estremi trovo due punti quasi coincidenti scambio le normali dei due punti di intersezione
|
|
bool bAtStart = false ;
|
|
bool bAtEnd = false ;
|
|
if ( AreSameVectorExact(vMainAx, Z_AX)) {
|
|
bAtStart = (vInters[0].first.z - vInters[1].first.z) < EPS_SMALL ;
|
|
bAtEnd = (vInters.back().first.z - vInters.end()[-2].first.z) < EPS_SMALL ;
|
|
}
|
|
else if ( AreSameVectorExact(vMainAx, Y_AX) ) {
|
|
bAtStart = (vInters[0].first.y - vInters[1].first.y) < EPS_SMALL ;
|
|
bAtEnd = (vInters.back().first.y - vInters.end()[-2].first.y) < EPS_SMALL ;
|
|
}
|
|
else if ( AreSameVectorExact(vMainAx, X_AX) ) {
|
|
bAtStart = (vInters[0].first.x - vInters[1].first.x) < EPS_SMALL ;
|
|
bAtEnd = (vInters.back().first.x - vInters.end()[-2].first.x) < EPS_SMALL ;
|
|
}
|
|
if ( bAtStart && vInters.size() == 2)
|
|
return ;
|
|
|
|
if ( bAtStart)
|
|
swap( vInters[0].second, vInters[1].second) ;
|
|
else if ( bAtEnd)
|
|
swap( vInters.back().second, vInters.end()[-2].second) ;
|
|
}
|
|
|
|
INTINT pStartEnd ;
|
|
bool bDirStart = vInters.front().second * vMainAx > 0 ;
|
|
bool bFirstEndFound = false ;
|
|
pStartEnd.first = 0 ;
|
|
for ( int w = 1 ; w < int( vInters.size()) ; ++w) {
|
|
bool bDir = vInters[w].second * vMainAx > 0 ;
|
|
// se è l'ultimo punto esco
|
|
if ( w == int( vInters.size() - 1) && bDirStart != bDir) {
|
|
pStartEnd.second = w ;
|
|
vStartEnds.push_back(pStartEnd) ;
|
|
break ;
|
|
}
|
|
// sennò scorro finché non trovo l'uscita più lontana ( prima di un altro ingresso o eventualmente l'ultima inters)
|
|
else if ( bDirStart != bDir)
|
|
bFirstEndFound = true ;
|
|
// se trovo di nuovo un'intersezione orientata come la prima dello spillone allora ho un nuovo start e posso chiudere l'intervallo precedente
|
|
else if ( bFirstEndFound && bDirStart == bDir) {
|
|
pStartEnd.second = w - 1 ;
|
|
bFirstEndFound = false ;
|
|
vStartEnds.push_back(pStartEnd) ;
|
|
pStartEnd.first = w ;
|
|
pStartEnd.second = -1 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
struct SurfBezForInters {
|
|
SurfBezier sBez ;
|
|
BBox3d bbSurfOriented ;
|
|
Frame3d frBox ;
|
|
Vector3d a3, a2, a1, a0, b3, b2, b1, b0 ;
|
|
} ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
IntersLineBezierSurfSet( const Point3d& ptLineStart, const Vector3d& vtLineDir,
|
|
const vector<SurfBezForInters>& vSurfBez, const BBox3d& bbVol, const Frame3d& frVol, PNTVEC3DVECTOR& vInters, INTVECTOR& vSurfInters,
|
|
const Vector3d& vtN, DBLDBLVECTOR& vInterv)
|
|
{
|
|
Point3d r = ptLineStart ;
|
|
Vector3d q = vtLineDir ;
|
|
|
|
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
|
|
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
|
|
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
|
|
Frame3d frRot ;
|
|
if ( bNeedToRotX)
|
|
frRot.Set( ORIG, X_AX) ;
|
|
if ( bNeedToRotY)
|
|
frRot.Set( ORIG, Y_AX) ;
|
|
if ( bNeedToRot) {
|
|
r.ToLoc( frRot) ;
|
|
q.ToLoc( frRot) ;
|
|
}
|
|
|
|
// calcolo se un intevallo sul dexel interseca il box dell'intero volume spazzato
|
|
bool bIntersVol = false ;
|
|
{
|
|
Point3d rLoc = r;
|
|
Vector3d qLoc = q;
|
|
rLoc.ToLoc(frVol);
|
|
qLoc.ToLoc(frVol);
|
|
for (int k = 0; k < int(vInterv.size()) && !bIntersVol; ++k) {
|
|
INTDBLVECTOR vIntersDash;
|
|
IntersLineBox(rLoc + qLoc * vInterv[k].first, rLoc + qLoc * vInterv[k].second, bbVol, vIntersDash, true);
|
|
bIntersVol = vIntersDash.size() > 0;
|
|
}
|
|
}
|
|
// se non sono stati passati gli intervalli allora vuol dire che lo spillone interseca
|
|
if ( vInterv.size() == 0)
|
|
bIntersVol = true ;
|
|
|
|
if ( bIntersVol) {
|
|
// interseco con le bezier
|
|
for ( int s = 0 ; s < int( vSurfBez.size()) ; ++s) {
|
|
// se ho già trovato l'intersezione con questa superficie vado avanti
|
|
|
|
const SurfBezForInters& srf = vSurfBez[s] ;
|
|
BBox3d bbox = srf.bbSurfOriented;
|
|
Point3d rLoc = r ;
|
|
Vector3d qLoc = q ;
|
|
if ( ! bNeedToRot) {
|
|
rLoc.ToLoc( srf.frBox) ;
|
|
qLoc.ToLoc( srf.frBox) ;
|
|
}
|
|
else {
|
|
rLoc.LocToLoc( frRot, srf.frBox) ;
|
|
qLoc.LocToLoc( frRot, srf.frBox) ;
|
|
}
|
|
|
|
bool bCalcInters = false ;
|
|
// verifico se il voxel interseca la box
|
|
INTDBLVECTOR vIntersDash ;
|
|
IntersLineBox(rLoc, qLoc, 0, bbox, vIntersDash, false) ;
|
|
bCalcInters = vIntersDash.size() > 0 ;
|
|
|
|
// verifico che lo spillone faccia interferenza con il box della superficie
|
|
if ( bCalcInters) {
|
|
// se la linea è parallela all'asse X o Y allora ruoto tutto di 45 gradi rispetto a Z
|
|
Vector3d a3, a2, a1, a0, b3, b2, b1, b0 ;
|
|
if ( ! bNeedToRot) {
|
|
a3 = srf.a3 ;
|
|
a2 = srf.a2 ;
|
|
a1 = srf.a1 ;
|
|
a0 = srf.a0 ;
|
|
b3 = srf.b3 ;
|
|
b2 = srf.b2 ;
|
|
b1 = srf.b1 ;
|
|
b0 = srf.b0 ;
|
|
}
|
|
else {
|
|
SurfBezier sBezRot = srf.sBez ;
|
|
sBezRot.ToLoc( frRot) ;
|
|
PNTVECTOR vPntCtrl = sBezRot.GetAllControlPoints() ;
|
|
|
|
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
|
|
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
|
|
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
|
|
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
|
|
Vector3d E = vPntCtrl[0] - ORIG ;
|
|
Vector3d F = vPntCtrl[1] - ORIG ;
|
|
Vector3d G = vPntCtrl[2] - ORIG ;
|
|
Vector3d H = vPntCtrl[3] - ORIG ;
|
|
|
|
a3 = -A + 3*B - 3*C + D ;
|
|
a2 = 3*A - 6*B + 3*C ;
|
|
a1 = -3*A +3*B ;
|
|
a0 = A ;
|
|
|
|
b3 = -E + 3*F - 3*G + H ;
|
|
b2 = 3*E - 6*F + 3*G ;
|
|
b1 = -3*E + 3*F ;
|
|
b0 = E ;
|
|
}
|
|
|
|
DBLVECTOR vdCoeff, vdRoots ;
|
|
// coefficienti dal grado più basso al grado più alto
|
|
vdCoeff = { // c0
|
|
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
|
|
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
|
|
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
|
|
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
|
|
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
|
|
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
|
|
|
|
// c1
|
|
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
|
|
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
|
|
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
|
|
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
|
|
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
|
|
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
|
|
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
|
|
|
|
// c2
|
|
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
|
|
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
|
|
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
|
|
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
|
|
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
|
|
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) + q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
|
|
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
|
|
|
|
// c3
|
|
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
|
|
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
|
|
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
|
|
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
|
|
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
|
|
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) + q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
|
|
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
|
|
|
|
// c4
|
|
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
|
|
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
|
|
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
|
|
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
|
|
|
|
// c5
|
|
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
|
|
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
|
|
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
|
|
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
|
|
|
|
// c6
|
|
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
|
|
q.y*q.z*a3.z*b3.x - q.z*q.z*a3.y*b3.x + // 4
|
|
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
|
|
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
|
|
for ( int w = 0 ; w < nRoots ; ++w) {
|
|
double dU = 0, dV = 0 ;
|
|
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
|
|
dU = vdRoots[w] ;
|
|
// verifico che non sia una soluzione con molteplicità > 1
|
|
bool bAlreadyFound = false ;
|
|
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
|
|
bAlreadyFound = ( abs( dU - vdRoots[k]) < EPS_PARAM) ;
|
|
if ( ! bAlreadyFound) {
|
|
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
|
|
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
|
|
double dDen = ( vAlpha.x * q.z - vAlpha.z * q.x) ;
|
|
if ( abs( dDen) > EPS_ZERO)
|
|
dV = ( ( vBeta.z - r.z) * q.x - ( vBeta.x - r.x ) * q.z) / dDen ;
|
|
else {
|
|
// se la prima equazione risulta un x/0 allora uso la seconda equazione per trovare il secondo parametro
|
|
double dDen2 = ( vAlpha.y * q.z - vAlpha.z * q.y) ;
|
|
dV = ( ( vBeta.z - r.z) * q.y - ( vBeta.y - r.y ) * q.z) / dDen2 ;
|
|
}
|
|
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
|
|
Point3d ptBez ;
|
|
Vector3d vtN ;
|
|
srf.sBez.GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez, vtN) ;
|
|
vtN *= -1 ;
|
|
UpdateMaxMin( ptBez, vtN, vInters) ;
|
|
vSurfInters.push_back( s) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
#if false
|
|
#define TEST
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
|
double dHeight, double dMaxRad, double dMinRad, int nToolNum, int n5AxisType)
|
|
{
|
|
// tolgo il volume spazzato dal tool durante il movimento
|
|
// Verifica sull'interferenza con lo Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtLs, vtLe, dMaxRad, dMinRad, dHeight, nStartI, nStartJ, nEndI, nEndJ))
|
|
return true ;
|
|
|
|
// vettori di riferimento per trovare i punti ausiliari
|
|
|
|
int nDegU = 3 ; int nDegV = 1 ;
|
|
int nSpanU = 1 ; int nSpanV = 1 ;
|
|
bool bRat = false ;
|
|
|
|
int nSub = 2 ; // numero di bezier di grado 3x1 con cui approssimare il (quasi) semi-cilindro ellissoide che descrive il volume della punta e della cima del tool
|
|
PNTVECTOR d ;
|
|
Vector3d q = Z_AX ;
|
|
|
|
int nTotSurf = 4 ;
|
|
if ( n5AxisType == Move5Axis::NO_BASE_INTERS)
|
|
nTotSurf = 2 + nSub * 2 + nSub * 2 + 8 ; // sup laterali, sup superiori e inferiori, superfici verticali di inizio e fine, superfici di base dei tool
|
|
else if ( n5AxisType == Move5Axis::ACROSS)
|
|
nTotSurf = 2 + nSub * 4 + nSub * 2 + 16 ; // come sopra
|
|
|
|
// punti di riferimento sul tool
|
|
// tip del tool
|
|
Point3d ptP1T ;
|
|
Point3d ptP2T ;
|
|
// determino la posizione della punta del tool nella posizione iniziale e in quella finale
|
|
ptP1T = ptS - dHeight * vtLs ;
|
|
ptP2T = ptE - dHeight * vtLe ;
|
|
// determino la direzione di movimento del top del tool e della punta del tool
|
|
Vector3d vtDirTop = ptE - ptS ;
|
|
Vector3d vtDirTip = ptP2T - ptP1T ;
|
|
bool bTopIsPivot = vtDirTop.IsSmall() ;
|
|
bool bTipIsPivot = vtDirTip.IsSmall() ;
|
|
bool bSmallMovement = vtDirTop.Len() < 10 * EPS_SMALL && vtDirTip.Len() < 10 * EPS_SMALL ;
|
|
bool bInverse = ! (bTopIsPivot || bTipIsPivot) && vtDirTop * vtDirTip < 0 ;
|
|
|
|
if ( bInverse)
|
|
nTotSurf += 4 ;
|
|
if ( bSmallMovement)
|
|
nTotSurf += 2 ;
|
|
|
|
int nSurfInd = 0 ;
|
|
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
|
double dSide = 0 ;
|
|
|
|
// box dell'intero volume spazzato, nel riferimento object oriented
|
|
BBox3d bbVol ;
|
|
Frame3d frVol ; frVol.Set(ptS, vtLs, vtDirTop) ;
|
|
|
|
// punti sul top e tip del tool che servono per costruire le bilineare di congiunzione tra step
|
|
PNTVECTOR vPntTipStartFront(3) ;
|
|
PNTVECTOR vPntTipEndFront(3) ;
|
|
PNTVECTOR vPntTopStartFront(3) ;
|
|
PNTVECTOR vPntTopEndFront(3) ;
|
|
// punti addizionali che servono nei casi che rischiedono più superfici bilineari ( tutti tranne NO_BASE_INTERS)
|
|
PNTVECTOR vPntTipStartBack(3) ;
|
|
PNTVECTOR vPntTipEndBack(3) ;
|
|
PNTVECTOR vPntTopStartBack(3) ;
|
|
PNTVECTOR vPntTopEndBack(3) ;
|
|
if ( nSub > 1) {
|
|
if ( bTopIsPivot)
|
|
vtDirTop = vtDirTip ;
|
|
if ( bTipIsPivot)
|
|
vtDirTip = vtDirTop ;
|
|
// determino in che modo collegare il cilindro iniziale con quello finale
|
|
Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ;
|
|
vtTopBaseEnd.Normalize() ;
|
|
vtTopBaseEnd *= dMaxRad ;
|
|
Point3d ptRefEnd = ptE - vtTopBaseEnd ;
|
|
Vector3d vtTopBaseStart = vtDirTop - (( vtDirTop * vtLs) * vtLs) ;
|
|
vtTopBaseStart.Normalize() ;
|
|
vtTopBaseStart *= dMaxRad ;
|
|
Point3d ptRefStart = ptS + vtTopBaseStart ;
|
|
dSide = ( ptRefEnd - ptRefStart) * vtLs ;
|
|
|
|
// calcolo anche i vettori per le basi inferiori
|
|
Vector3d vtTipBaseStart = bInverse ? ( vtLs ^ vtDirTip) : -( vtLs ^ vtDirTip) ;
|
|
vtTipBaseStart.Normalize() ;
|
|
vtTipBaseStart *= dMinRad ;
|
|
Vector3d vtTipBaseEnd = bInverse ? ( vtLe ^ vtDirTip) : -( vtLe ^ vtDirTip) ;
|
|
vtTipBaseEnd.Normalize() ;
|
|
vtTipBaseEnd *= dMinRad ;
|
|
// aggiungo il primo punto per ognuno dei gruppi
|
|
vtTopBaseStart.Rotate( vtLs, 90) ;
|
|
vtTopBaseEnd.Rotate( vtLe, 90) ;
|
|
vPntTopStartFront[0] = ptS - vtTopBaseStart ;
|
|
vPntTopEndFront[0] = ptE - vtTopBaseEnd ;
|
|
vPntTipStartFront[0] = ptP1T + vtTipBaseStart ;
|
|
vPntTipEndFront[0] = ptP2T + vtTipBaseEnd ;
|
|
|
|
// punti addizionali per superfici bilineari
|
|
vPntTopStartBack[0] = ptS + vtTopBaseStart ;
|
|
vPntTopEndBack[0] = ptE + vtTopBaseEnd ;
|
|
vPntTipStartBack[0] = ptP1T - vtTipBaseStart ;
|
|
vPntTipEndBack[0] = ptP2T - vtTipBaseEnd ;
|
|
double dSubAng = 90 ;
|
|
// girano tutti in verso CCW rispetto alla normale del tool
|
|
for ( int i = 1; i < 3; ++i) {
|
|
// punti sulla base superiore dei cilindri
|
|
// start
|
|
// frontale
|
|
vPntTopStartFront[i] = vPntTopStartFront[i - 1] ;
|
|
vPntTopStartFront[i].Rotate( ptS, vtLs, dSubAng) ;
|
|
// posteriore
|
|
vPntTopStartBack[i] = vPntTopStartBack[i - 1];
|
|
vPntTopStartBack[i].Rotate( ptS, vtLs, dSubAng) ;
|
|
// end
|
|
// frontale
|
|
vPntTopEndFront[i] = vPntTopEndFront[i - 1] ;
|
|
vPntTopEndFront[i].Rotate( ptE, vtLe, dSubAng) ;
|
|
// posteriore
|
|
vPntTopEndBack[i] = vPntTopEndBack[i - 1] ;
|
|
vPntTopEndBack[i].Rotate( ptE, vtLe, dSubAng) ;
|
|
|
|
// punti sulla base inferiore dei cilindri
|
|
vPntTipStartFront[i] = vPntTipStartFront[i - 1] ;
|
|
vPntTipStartFront[i].Rotate( ptP1T, vtLs, dSubAng) ;
|
|
vPntTipStartBack[i] = vPntTipStartBack[i - 1] ;
|
|
vPntTipStartBack[i].Rotate( ptP1T, vtLs, dSubAng) ;
|
|
|
|
vPntTipEndFront[i] = vPntTipEndFront[i - 1] ;
|
|
vPntTipEndFront[i].Rotate( ptP2T, vtLe, dSubAng) ;
|
|
vPntTipEndBack[i] = vPntTipEndBack[i - 1] ;
|
|
vPntTipEndBack[i].Rotate( ptP2T, vtLe, dSubAng) ;
|
|
}
|
|
}
|
|
|
|
vector<PNTVECTOR> vvPtCtrl ;
|
|
if ( ! bSmallMovement) {
|
|
// superficie laterale sinistra
|
|
CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ;
|
|
if ( ! cLineLeftBottom.IsValid())
|
|
return false ;
|
|
if ( bInverse)
|
|
cLineLeftBottom.Invert() ;
|
|
PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ;
|
|
if ( IsNull( cBezLeftBottom))
|
|
return false ;
|
|
CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ;
|
|
if ( ! cLineLeftTop.IsValid())
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ;
|
|
if ( IsNull( cBezLeftTop))
|
|
return false ;
|
|
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
|
|
// superficie laterale destra
|
|
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
|
|
if ( ! cLineRightBottom.IsValid())
|
|
return false ;
|
|
if ( bInverse)
|
|
cLineRightBottom.Invert() ;
|
|
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
|
|
if ( IsNull( cBezRightBottom))
|
|
return false ;
|
|
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
|
|
if ( ! cLineRightTop.IsValid())
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
|
|
if ( IsNull( cBezRightTop))
|
|
return false ;
|
|
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
|
|
}
|
|
if ( nSub == 1) {
|
|
// superficie inferiore
|
|
vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ;
|
|
// superficie superiore
|
|
vvPtCtrl.emplace_back( PNTVECTOR( { vPntTopStartFront.back(), vPntTopStartFront.front(), vPntTopEndFront.back(), vPntTopEndFront.front() })) ;
|
|
}
|
|
else {
|
|
// costruisco tutti gli archi subito
|
|
// archi inferiori front
|
|
CurveArc cArcTipStartF1, cArcTipEndF1, cArcTipStartF2, cArcTipEndF2 ;
|
|
if ( ! cArcTipStartF1.SetC2PN(ptP1T, vPntTipStartFront[0], vPntTipStartFront[1], vtLs) ||
|
|
! cArcTipEndF1.SetC2PN(ptP2T, vPntTipEndFront[0], vPntTipEndFront[1], vtLe) ||
|
|
! cArcTipStartF2.SetC2PN(ptP1T, vPntTipStartFront[1], vPntTipStartFront[2], vtLs) ||
|
|
! cArcTipEndF2.SetC2PN(ptP2T, vPntTipEndFront[1], vPntTipEndFront[2], vtLe))
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezTipStartF1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipStartF1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipEndF1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipEndF1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipStartF2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipStartF2, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipEndF2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipEndF2, nDegU, bRat)));
|
|
// archi inferiori back
|
|
CurveArc cArcTipStartB1, cArcTipEndB1, cArcTipStartB2, cArcTipEndB2;
|
|
if ( ! cArcTipStartB1.SetC2PN(ptP1T, vPntTipStartBack[0], vPntTipStartBack[1], vtLs) ||
|
|
! cArcTipEndB1.SetC2PN(ptP2T, vPntTipEndBack[0], vPntTipEndBack[1], vtLe) ||
|
|
! cArcTipStartB2.SetC2PN(ptP1T, vPntTipStartBack[1], vPntTipStartBack[2], vtLs) ||
|
|
! cArcTipEndB2.SetC2PN(ptP2T, vPntTipEndBack[1], vPntTipEndBack[2], vtLe))
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezTipStartB1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipStartB1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipEndB1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipEndB1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipStartB2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipStartB2, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTipEndB2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTipEndB2, nDegU, bRat)));
|
|
if ( IsNull( cBezTipStartB1) || IsNull( cBezTipEndB1) || IsNull( cBezTipStartB2) || IsNull( cBezTipEndB2))
|
|
return false ;
|
|
// archi superiori front
|
|
CurveArc cArcTopStartF1, cArcTopEndF1, cArcTopStartF2, cArcTopEndF2;
|
|
if ( ! cArcTopStartF1.SetC2PN(ptS, vPntTopStartFront[0], vPntTopStartFront[1], vtLs) ||
|
|
! cArcTopEndF1.SetC2PN(ptE, vPntTopEndFront[0], vPntTopEndFront[1], vtLe) ||
|
|
! cArcTopStartF2.SetC2PN(ptS, vPntTopStartFront[1], vPntTopStartFront[2], vtLs) ||
|
|
! cArcTopEndF2.SetC2PN(ptE, vPntTopEndFront[1], vPntTopEndFront[2], vtLe))
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezTopStartF1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopStartF1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopEndF1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopEndF1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopStartF2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopStartF2, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopEndF2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopEndF2, nDegU, bRat)));
|
|
if ( IsNull( cBezTopStartF1) || IsNull( cBezTopEndF1) || IsNull( cBezTopStartF2) || IsNull( cBezTopEndF2))
|
|
return false ;
|
|
// archi superiori back
|
|
CurveArc cArcTopStartB1, cArcTopEndB1, cArcTopStartB2, cArcTopEndB2;
|
|
if ( ! cArcTopStartB1.SetC2PN(ptS, vPntTopStartBack[0], vPntTopStartBack[1], vtLs) ||
|
|
! cArcTopEndB1.SetC2PN(ptE, vPntTopEndBack[0], vPntTopEndBack[1], vtLe) ||
|
|
! cArcTopStartB2.SetC2PN(ptS, vPntTopStartBack[1], vPntTopStartBack[2], vtLs) ||
|
|
! cArcTopEndB2.SetC2PN(ptE, vPntTopEndBack[1], vPntTopEndBack[2], vtLe))
|
|
return false ;
|
|
PtrOwner<CurveBezier> cBezTopStartB1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopStartB1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopEndB1(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopEndB1, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopStartB2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopStartB2, nDegU, bRat)));
|
|
PtrOwner<CurveBezier> cBezTopEndB2(GetBasicCurveBezier(ArcToBezierCurve(&cArcTopEndB2, nDegU, bRat)));
|
|
if ( IsNull( cBezTopStartB1) || IsNull( cBezTopEndB1) || IsNull( cBezTopStartB2) || IsNull( cBezTopEndB2))
|
|
return false ;
|
|
|
|
if ( n5AxisType == Move5Axis::NO_BASE_INTERS || n5AxisType == Move5Axis::ACROSS) {
|
|
if ( ! bTipIsPivot) {
|
|
// inferiori
|
|
if ( dSide > 0) {
|
|
PNTVECTOR vPntTipEnd01 = cBezTipStartF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
|
|
PNTVECTOR vPntTipEnd1 = cBezTipEndF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ;
|
|
PNTVECTOR vPntTipEnd02 = cBezTipStartF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
|
|
PNTVECTOR vPntTipEnd2 = cBezTipEndF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
|
|
}
|
|
else {
|
|
PNTVECTOR vPntTipEnd01 = cBezTipStartB1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTipEnd01.rbegin(), vPntTipEnd01.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTipEnd01.begin(), vPntTipEnd01.end()) ;
|
|
PNTVECTOR vPntTipEnd1 = cBezTipEndB1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.rbegin(), vPntTipEnd1.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ;
|
|
PNTVECTOR vPntTipEnd02 = cBezTipStartB2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTipEnd02.rbegin(), vPntTipEnd02.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTipEnd02.begin(), vPntTipEnd02.end()) ;
|
|
PNTVECTOR vPntTipEnd2 = cBezTipEndB2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.rbegin(), vPntTipEnd2.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ;
|
|
}
|
|
}
|
|
if ( ! bTopIsPivot) {
|
|
// superiori
|
|
if ( dSide > 0) {
|
|
PNTVECTOR vPntTopEnd01 = cBezTopStartB1->GetAllControlPoints() ;
|
|
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
|
|
PNTVECTOR vPntTopEnd1 = cBezTopEndB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
|
|
PNTVECTOR vPntTopEnd02 = cBezTopStartB2->GetAllControlPoints() ;
|
|
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
|
|
PNTVECTOR vPntTopEnd2 = cBezTopEndB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
|
|
}
|
|
else {
|
|
PNTVECTOR vPntTopEnd01 = cBezTopStartF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTopEnd01.rbegin(), vPntTopEnd01.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTopEnd01.begin(), vPntTopEnd01.end()) ;
|
|
PNTVECTOR vPntTopEnd1 = cBezTopEndF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.rbegin(), vPntTopEnd1.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ;
|
|
PNTVECTOR vPntTopEnd02 = cBezTopStartF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTopEnd02.rbegin(), vPntTopEnd02.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTopEnd02.begin(), vPntTopEnd02.end()) ;
|
|
PNTVECTOR vPntTopEnd2 = cBezTopEndF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.rbegin(), vPntTopEnd2.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ;
|
|
}
|
|
}
|
|
|
|
// aggiungo le superfici bilineari anche nell'altro verso sia per il top che per il tip
|
|
if ( n5AxisType == Move5Axis::ACROSS) {
|
|
if ( ! bTipIsPivot) {
|
|
// inferiori
|
|
if ( dSide > 0) {
|
|
PNTVECTOR vPntTip01 = cBezTipStartB1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
|
|
PNTVECTOR vPntTip1 = cBezTipEndB1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
|
|
PNTVECTOR vPntTip02 = cBezTipStartB2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
|
|
PNTVECTOR vPntTip2 = cBezTipEndB2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
|
|
}
|
|
else {
|
|
PNTVECTOR vPntTip01 = cBezTipStartF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTip01.begin(), vPntTip01.end()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTip01.rbegin(), vPntTip01.rend()) ;
|
|
PNTVECTOR vPntTip1 = cBezTipEndF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.rbegin(), vPntTip1.rend()) ;
|
|
PNTVECTOR vPntTip02 = cBezTipStartF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTip02.begin(), vPntTip02.end()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTip02.rbegin(), vPntTip02.rend()) ;
|
|
PNTVECTOR vPntTip2 = cBezTipEndF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.rbegin(), vPntTip2.rend()) ;
|
|
}
|
|
}
|
|
|
|
if ( ! bTopIsPivot) {
|
|
// superiori
|
|
if ( dSide > 0) {
|
|
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTop01.rbegin(), vPntTop01.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTop01.begin(), vPntTop01.end()) ;
|
|
PNTVECTOR vPntTop1 = cBezTopEndF1->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.rbegin(), vPntTop1.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end()) ;
|
|
PNTVECTOR vPntTop02 = cBezTopStartF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.emplace_back( vPntTop02.rbegin(), vPntTop02.rend()) ;
|
|
else
|
|
vvPtCtrl.emplace_back( vPntTop02.begin(), vPntTop02.end()) ;
|
|
PNTVECTOR vPntTop2 = cBezTopEndF2->GetAllControlPoints() ;
|
|
if ( ! bInverse)
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.rbegin(), vPntTop2.rend()) ;
|
|
else
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end()) ;
|
|
}
|
|
else {
|
|
vvPtCtrl.emplace_back(cBezTopStartB1->GetAllControlPoints());
|
|
PNTVECTOR vPntTop1 = cBezTopEndB1->GetAllControlPoints();
|
|
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end());
|
|
vvPtCtrl.emplace_back(cBezTopStartB2->GetAllControlPoints());
|
|
PNTVECTOR vPntTop2 = cBezTopEndB2->GetAllControlPoints();
|
|
vvPtCtrl.back().insert(vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// chiudo il volume con le superfici verticali e le basi dei tool
|
|
|
|
// chiudo il volume con le superici verticali end front 1
|
|
vvPtCtrl.emplace_back( cBezTipEndF1->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntEndF1 = cBezTopEndF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF1.begin(), vPntEndF1.end()) ;
|
|
// chiudo il volume con le superici verticali end front 2
|
|
vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntEndF2 = cBezTopEndF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF2.begin(), vPntEndF2.end()) ;
|
|
if ( bInverse || bSmallMovement) {
|
|
// chiudo il volume con le superici verticali end back 1
|
|
vvPtCtrl.emplace_back( cBezTipEndB1->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntEndB1 = cBezTopEndB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB1.begin(), vPntEndB1.end()) ;
|
|
// chiudo il volume con le superici verticali end back 2
|
|
vvPtCtrl.emplace_back( cBezTipEndB2->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntEndB2 = cBezTopEndB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndB2.begin(), vPntEndB2.end()) ;
|
|
}
|
|
|
|
// chiudo il volume con le superici verticali start back 1
|
|
vvPtCtrl.emplace_back( cBezTipStartB1->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntStartB1 = cBezTopStartB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB1.begin(), vPntStartB1.end()) ;
|
|
// chiudo il volume con le superfici verticali start back 2
|
|
vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntStartB2 = cBezTopStartB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB2.begin(), vPntStartB2.end()) ;
|
|
if ( bInverse || bSmallMovement) {
|
|
// chiudo il volume con le superici verticali start front 1
|
|
vvPtCtrl.emplace_back( cBezTipStartF1->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntStartF1 = cBezTopStartF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF1.begin(), vPntStartF1.end()) ;
|
|
// chiudo il volume con le superfici verticali start front 2
|
|
vvPtCtrl.emplace_back( cBezTipStartF2->GetAllControlPoints()) ;
|
|
PNTVECTOR vPntStartF2 = cBezTopStartF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartF2.begin(), vPntStartF2.end()) ;
|
|
}
|
|
|
|
// superfici di base dei tool
|
|
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) {
|
|
// start back tip
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T }) ;
|
|
PNTVECTOR vPntTipStartBack1 = cBezTipStartB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartBack1.begin(), vPntTipStartBack1.end()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T }) ;
|
|
PNTVECTOR vPntTipStartBack2 = cBezTipStartB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartBack2.begin(), vPntTipStartBack2.end()) ;
|
|
// start front tip
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T }) ;
|
|
PNTVECTOR vPntTipStartFront1 = cBezTipStartF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartFront1.begin(), vPntTipStartFront1.end()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T }) ;
|
|
PNTVECTOR vPntTipStartFront2 = cBezTipStartF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartFront2.begin(), vPntTipStartFront2.end()) ;
|
|
}
|
|
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide > 0)) {
|
|
// end front tip
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T }) ;
|
|
PNTVECTOR vPntTipEndFront1 = cBezTipEndF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndFront1.begin(), vPntTipEndFront1.end()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T }) ;
|
|
PNTVECTOR vPntTipEndFront2 = cBezTipEndF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndFront2.begin(), vPntTipEndFront2.end()) ;
|
|
// end back tip
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T }) ;
|
|
PNTVECTOR vPntTipEndBack1 = cBezTipEndB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndBack1.begin(), vPntTipEndBack1.end()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T }) ;
|
|
PNTVECTOR vPntTipEndBack2 = cBezTipEndB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndBack2.begin(), vPntTipEndBack2.end()) ;
|
|
}
|
|
|
|
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide > 0)) {
|
|
// start back top
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptS, ptS, ptS, ptS }) ;
|
|
PNTVECTOR vPntTopStartBack1 = cBezTopStartB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartBack1.rbegin(), vPntTopStartBack1.rend()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptS, ptS, ptS, ptS }) ;
|
|
PNTVECTOR vPntTopStartBack2 = cBezTopStartB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartBack2.rbegin(), vPntTopStartBack2.rend()) ;
|
|
// start front top
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptS, ptS, ptS, ptS }) ;
|
|
PNTVECTOR vPntTopStartFront1 = cBezTopStartF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartFront1.rbegin(), vPntTopStartFront1.rend()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptS, ptS, ptS, ptS }) ;
|
|
PNTVECTOR vPntTopStartFront2 = cBezTopStartF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartFront2.rbegin(), vPntTopStartFront2.rend()) ;
|
|
}
|
|
if ( ! ( n5AxisType == Move5Axis::NO_BASE_INTERS && dSide < 0)) {
|
|
// end front top
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptE, ptE, ptE, ptE }) ;
|
|
PNTVECTOR vPntTopEndFront1 = cBezTopEndF1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndFront1.rbegin(), vPntTopEndFront1.rend()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptE, ptE, ptE, ptE }) ;
|
|
PNTVECTOR vPntTopEndFront2 = cBezTopEndF2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndFront2.rbegin(), vPntTopEndFront2.rend()) ;
|
|
// end back top
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptE, ptE, ptE, ptE }) ;
|
|
PNTVECTOR vPntTopEndBack1 = cBezTopEndB1->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndBack1.rbegin(), vPntTopEndBack1.rend()) ;
|
|
vvPtCtrl.emplace_back( PNTVECTOR{ ptE, ptE, ptE, ptE }) ;
|
|
PNTVECTOR vPntTopEndBack2 = cBezTopEndB2->GetAllControlPoints() ;
|
|
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndBack2.rbegin(), vPntTopEndBack2.rend()) ;
|
|
}
|
|
}
|
|
|
|
// inizializzo le superfici bilineari e i parametri per le intersezioni
|
|
for ( int z = 0 ; z < ssize( vvPtCtrl) ; ++z) {
|
|
vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 2, vvPtCtrl[z][2]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 3, vvPtCtrl[z][3]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 4, vvPtCtrl[z][4]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 5, vvPtCtrl[z][5]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ;
|
|
vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ;
|
|
|
|
#if SAVETRIMMINGTOOL
|
|
if ( nGrid == 0)
|
|
vGeo.push_back( vSurfBez[nSurfInd].sBez.Clone()) ;
|
|
#endif
|
|
|
|
Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ;
|
|
Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ;
|
|
Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ;
|
|
Vector3d D = vvPtCtrl[z][7] - vvPtCtrl[z][3] ;
|
|
Vector3d E = vvPtCtrl[z][0] - ORIG ;
|
|
Vector3d F = vvPtCtrl[z][1] - ORIG ;
|
|
Vector3d G = vvPtCtrl[z][2] - ORIG ;
|
|
Vector3d H = vvPtCtrl[z][3] - ORIG ;
|
|
|
|
vSurfBez[nSurfInd].a3 = -A + 3 * B - 3 * C + D ;
|
|
vSurfBez[nSurfInd].a2 = 3 * A - 6 * B + 3 * C ;
|
|
vSurfBez[nSurfInd].a1 = -3 * A + 3 * B ;
|
|
vSurfBez[nSurfInd].a0 = A ;
|
|
|
|
vSurfBez[nSurfInd].b3 = -E + 3 * F - 3 * G + H ;
|
|
vSurfBez[nSurfInd].b2 = 3 * E - 6 * F + 3 * G ;
|
|
vSurfBez[nSurfInd].b1 = -3 * E + 3 * F ;
|
|
vSurfBez[nSurfInd].b0 = E ;
|
|
|
|
Vector3d vtDirZ = vvPtCtrl[z][4] - vvPtCtrl[z][0] ;
|
|
Vector3d vtDirX = vvPtCtrl[z][3] - vvPtCtrl[z][0] ;
|
|
|
|
// devo gestire il caso in cui uno dei due vettori sia == 0
|
|
if (vtDirZ.IsSmall()) {
|
|
vtDirZ = vvPtCtrl[z][7] - vvPtCtrl[z][4];
|
|
}
|
|
if (vtDirX.IsSmall()) {
|
|
vtDirX = vvPtCtrl[z][7] - vvPtCtrl[z][3];
|
|
}
|
|
|
|
// calcolo il box in un riferimento che usi come asse x la direzione P10 - P00 o P11 - P01 ( proiettata sul piano perperndicolare a Z)
|
|
if ( vSurfBez[nSurfInd].frBox.Set( ORIG, vtDirZ, vtDirX)) {
|
|
// porto tutti i punti in quel riferimento e calcolo il box
|
|
PNTVECTOR vPtCtrlLoc = vvPtCtrl[z] ;
|
|
for ( int p = 0 ; p < int( vPtCtrlLoc.size()) ; ++p)
|
|
vPtCtrlLoc[p].ToLoc( vSurfBez[nSurfInd].frBox) ;
|
|
vSurfBez[nSurfInd].bbSurfOriented.Add( vPtCtrlLoc) ;
|
|
}
|
|
|
|
// aggiungo i punti al box del volume spazzato
|
|
PNTVECTOR vPtCtrlLoc = vvPtCtrl[z] ;
|
|
for (int p = 0; p < int(vPtCtrlLoc.size()); ++p)
|
|
vPtCtrlLoc[p].ToLoc(frVol);
|
|
bbVol.Add(vPtCtrlLoc) ;
|
|
|
|
++ nSurfInd ;
|
|
}
|
|
|
|
#if SAVETRIMMINGTOOL
|
|
if ( nGrid == 0)
|
|
SaveGeoObj( vGeo, "D:\\Temp\\VirtualMilling\\5axisAdvanced\\marmo sottosquadra\\volume.nge") ;
|
|
#endif
|
|
|
|
// scorro tutti gli spilloni interessati
|
|
int j = 0 ;
|
|
int nLastForwardJ = -1 ;
|
|
bool bUseOnlyExtremes = false ;
|
|
bool bFirstAmbiguousCaseType = false ;
|
|
bool bForward = true ;
|
|
bool bAllSameType = false ;
|
|
struct IntervalsToSubtract {
|
|
int i = 0 ;
|
|
int j = 0 ;
|
|
bool bUseOnlyExtremes = false ;
|
|
PNTVEC3DVECTOR vInters ;
|
|
INTINTVECTOR vStartEnds ;
|
|
IntervalsToSubtract( int nI, int nJ, PNTVEC3DVECTOR& vPntInt, INTINTVECTOR& vSE, bool bUseExtremes) : i( nI), j( nJ), bUseOnlyExtremes( bUseExtremes), vInters( vPntInt), vStartEnds( vSE) {}
|
|
} ;
|
|
vector<IntervalsToSubtract> vIntervalsToSubtr ;
|
|
|
|
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
|
nLastForwardJ = -1 ;
|
|
j = nStartJ ;
|
|
bAllSameType = false ;
|
|
bForward = true ;
|
|
bFirstAmbiguousCaseType = false ;
|
|
while ( j <= nEndJ && j > nLastForwardJ) {
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
Point3d r( dX, dY, 0) ;
|
|
PNTVEC3DVECTOR vInters ;
|
|
INTINTVECTOR vStartEnds ;
|
|
|
|
INTVECTOR vSurfInters ;
|
|
int nPos = j * m_nNx[nGrid] + i ;
|
|
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
|
|
DBLDBLVECTOR vInterv, vEmpty ;
|
|
for ( int k = 0 ; k < int(vDexel.size()) ; ++k )
|
|
vInterv.emplace_back( vDexel[k].dMin, vDexel[k].dMax) ;
|
|
|
|
if ( vDexel.size() != 0) {
|
|
IntersLineBezierSurfSet( r, q, vSurfBez, bbVol, frVol, vInters, vSurfInters, vtLs, vInterv) ;
|
|
|
|
if ( vInters.size() > 2) {
|
|
SortGroupInters( vInters, vStartEnds, Z_AX) ;
|
|
if ( bForward && vStartEnds.size() > 1) {
|
|
// se ho più di un intervallo da togliere allora devo capire se sono dentro il volume spazzato dal tool o no
|
|
nLastForwardJ = j ;
|
|
j = nEndJ + 1 ;
|
|
bForward = false ;
|
|
}
|
|
if ( ! bForward && vStartEnds.size() > 1) {
|
|
// salvo la prima intersezione dubbia e comincio a scorrere al contrario per trovare l'ultima e capire se è dello stesso tipo della prima
|
|
|
|
if ( ! bAllSameType) {
|
|
bUseOnlyExtremes = false ;
|
|
|
|
// calcolo le intersezioni anche sugli altri due spilloni passanti per un punto a metà tra due dei vari intervalli
|
|
// ho almeno due intervalli; prendo un punto a metà tra la fine del primo e l'inzio del secondo
|
|
Point3d ptLineStart = (vInters[vStartEnds[0].second].first + vInters[vStartEnds[1].first].first ) / 2 ;
|
|
Vector3d vtLineStart = X_AX ;
|
|
PNTVEC3DVECTOR vIntersX ;
|
|
INTVECTOR vSurfX ;
|
|
INTINTVECTOR vStartEndsX ;
|
|
bool bXInclude = false ;
|
|
IntersLineBezierSurfSet( ptLineStart, vtLineStart, vSurfBez, bbVol, frVol, vIntersX, vSurfX, V_NULL, vEmpty) ;
|
|
if ( vIntersX.size() > 1) {
|
|
SortGroupInters( vIntersX, vStartEndsX, X_AX) ;
|
|
if ( vStartEndsX.size() != 0)
|
|
// se ho più di una intersezione e il punto di studio è compreso tra questi punti allora le info lungo questa direzione mi dicono che sono interno al volume spazzato
|
|
bXInclude = ( vIntersX[vStartEndsX.front().first].first.x < ptLineStart.x &&
|
|
vIntersX[vStartEndsX.back().second].first.x > ptLineStart.x) ;
|
|
}
|
|
|
|
vtLineStart = Y_AX ;
|
|
PNTVEC3DVECTOR vIntersY ;
|
|
INTVECTOR vSurfY ;
|
|
INTINTVECTOR vStartEndsY ;
|
|
bool bYInclude = false ;
|
|
IntersLineBezierSurfSet( ptLineStart, vtLineStart, vSurfBez, bbVol, frVol, vIntersY, vSurfY, V_NULL, vEmpty) ;
|
|
if ( vIntersY.size() > 1) {
|
|
SortGroupInters( vIntersY, vStartEndsY, Y_AX) ;
|
|
if ( vStartEndsY.size() != 0)
|
|
// se ho più di una intersezione e il punto di studio è compreso tra questi punti allora le info lungo questa direzione mi dicono che sono interno al volume spazzato
|
|
bYInclude = ( vIntersY[vStartEndsY.front().first].first.y < ptLineStart.y &&
|
|
vIntersY[vStartEndsY.back().second].first.y > ptLineStart.y) ;
|
|
}
|
|
|
|
// se anche gli spilloni nelle altre due direzioni fanno intersezione sia a destra che a sinistra rispetto al punto a metà tra gli intervalli, allora sono all'interno del volume
|
|
if ( bXInclude && bYInclude)
|
|
bUseOnlyExtremes = true ;
|
|
}
|
|
|
|
int nJToSave = j ;
|
|
if ( j == nEndJ + 1) {
|
|
nJToSave = nLastForwardJ ;
|
|
bFirstAmbiguousCaseType = bUseOnlyExtremes ;
|
|
}
|
|
else {
|
|
// se ho trovato un caso ambiguo ( scorrendo al contrario) che è uguale al primo che ho trovato scorrendo dritto allora posso considerare tutti gli spilloni restanti di
|
|
// questo tipo e calcolare solo le intersezioni
|
|
if ( bUseOnlyExtremes == bFirstAmbiguousCaseType)
|
|
bAllSameType = true ;
|
|
}
|
|
|
|
if ( ! bAllSameType)
|
|
vIntervalsToSubtr.emplace_back( i, nJToSave, vInters, vStartEnds, bUseOnlyExtremes) ;
|
|
else {
|
|
bUseOnlyExtremes = bFirstAmbiguousCaseType ;
|
|
if ( bUseOnlyExtremes)
|
|
SubtractIntervals( nGrid, i, j, vInters.front().first.z, vInters.back().first.z,
|
|
vInters.front().second, vInters.back().second, nToolNum) ;
|
|
else {
|
|
for ( auto p : vStartEnds)
|
|
SubtractIntervals( nGrid, i, j, vInters[p.first].first.z, vInters[p.second].first.z,
|
|
vInters[p.first].second, vInters[p.second].second, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for ( auto p : vStartEnds)
|
|
SubtractIntervals( nGrid, i, j, vInters[p.first].first.z, vInters[p.second].first.z,
|
|
vInters[p.first].second, vInters[p.second].second, nToolNum) ;
|
|
}
|
|
}
|
|
else if ( vInters.size() == 2) {
|
|
vStartEnds.push_back(INTINT(0, 1)) ;
|
|
SubtractIntervals( nGrid, i, j, vInters.front().first.z, vInters.back().first.z,
|
|
vInters.front().second, vInters.back().second, nToolNum) ;
|
|
}
|
|
else if ( vInters.size() == 1) {
|
|
// se trovo solo un'intersezione è una tangenza tra spillone e una superficie
|
|
}
|
|
}
|
|
|
|
if ( bForward)
|
|
++j ;
|
|
else
|
|
--j ;
|
|
}
|
|
}
|
|
|
|
for ( IntervalsToSubtract& intToSub : vIntervalsToSubtr) {
|
|
if ( intToSub.bUseOnlyExtremes)
|
|
SubtractIntervals( nGrid, intToSub.i, intToSub.j, intToSub.vInters.front().first.z, intToSub.vInters.back().first.z,
|
|
intToSub.vInters.front().second, intToSub.vInters.back().second, nToolNum) ;
|
|
else {
|
|
// scorro le intersezione su questo spillone togliendo gli intervalli usando vStartEnds
|
|
for ( int z = 0 ; z < int( intToSub.vStartEnds.size()) ; ++z) {
|
|
int nStart = intToSub.vStartEnds[z].first ;
|
|
int nEnd = intToSub.vStartEnds[z].second ;
|
|
SubtractIntervals( nGrid, intToSub.i, intToSub.j, intToSub.vInters[nStart].first.z, intToSub.vInters[nEnd].first.z,
|
|
intToSub.vInters[nStart].second, intToSub.vInters[nEnd].second, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompCyl_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
|
double dHeight, double dRadius, int nToolNum, int n5AxisType)
|
|
{
|
|
// tolgo il volume spazzato dal tool durante il movimento
|
|
return Comp_5AxisMilling( nGrid, ptS, ptE, vtLs, vtLe, dHeight, dRadius, dRadius, nToolNum, n5AxisType) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Cyl_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, double dHeightCorr, int n5AxisType)
|
|
{
|
|
// tolgo il volume dei cilindri all'inizio e alla fine del tratto e poi uso delle bilineari per approssimare il volume spazzato
|
|
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
// recupero le info del tool
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
double dHeight = CurrTool.GetHeigth() - dHeightCorr ;
|
|
double dRadius = CurrTool.GetRadius() ;
|
|
|
|
return CompCyl_5AxisMilling( nGrid, ptS, ptE, vtLs, vtLe, dHeight, dRadius, nToolNum, n5AxisType) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
double dHeight = CurrTool.GetHeigth() - CurrTool.GetTipRadius() ;
|
|
double dRadius = CurrTool.GetRadius() ;
|
|
CompCyl_5AxisMilling( nGrid, ptS, ptE, vtLs, vtLe, dHeight, dRadius, nToolNum, n5AxisType) ;
|
|
|
|
// devo poi togliere la sfera tip iniziale, la sfera tip finale e il cilindro del volume spazzato
|
|
Point3d ptTipS = ptS - vtLs * ( CurrTool.GetHeigth()) ;
|
|
Point3d ptTipE = ptE - vtLe * ( CurrTool.GetHeigth()) ;
|
|
CompBall_Milling( nGrid, ptTipS, ptTipE, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompConus_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, double dHei, double dMaxRad, double dMinRad,
|
|
bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum, int n5AxisType)
|
|
{
|
|
// come per le altre funzioni che lavorano con i coni, se il cono è inverso ( che va allargandosi andando verso il fondo del tool), allora i vtL passati sono invertiti rispetto a quelli
|
|
// reali del tool e i punti ptS e ptE sono invertiti( così come dMaxRad e dMinRad)
|
|
|
|
// al momento i bool bTapB e bTapT vengono ignorati e di default si crea un volume chiuso con anche le superfici superiore e inferiore.
|
|
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
|
|
// tolgo il valume spazzato dal tool durante il movimento
|
|
return Comp_5AxisMilling( nGrid, ptS, ptE, vtLs, vtLe, dHei, dMaxRad, dMinRad, nToolNum, n5AxisType) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
// recupero le info del tool
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
double dHeight = CurrTool.GetHeigth() ;
|
|
double dRadius = CurrTool.GetRadius() ;
|
|
double dTipRadius = CurrTool.GetTipRadius() ;
|
|
|
|
double dStemHeigth = dHeight - CurrTool.GetTipHeigth() ;
|
|
|
|
// elimino la parte del volume spazzato dalla parte cilindrica del tool
|
|
Cyl_5AxisMilling( nGrid, ptS, ptE, vtLs, vtLe, nToolNum, CurrTool.GetTipHeigth(), n5AxisType) ;
|
|
|
|
// elimino la parte spazzata dalla punta conica del tool
|
|
if ( CurrTool.GetTipRadius() < dRadius) {
|
|
// Trapano
|
|
Point3d ptSConus = ptS - dStemHeigth * vtLs ;
|
|
Point3d ptEConus = ptE - dStemHeigth * vtLe ;
|
|
CompConus_5AxisMilling( nGrid, ptSConus, ptEConus, vtLs, vtLe, dHeight,
|
|
dRadius, dTipRadius, true, false, V_NULL, V_NULL, CurrTool.GetToolNum(), n5AxisType) ;
|
|
}
|
|
else {
|
|
double dHeight = CurrTool.GetHeigth() ;
|
|
Point3d ptSInvertedConus = ptS - dHeight * vtLs ;
|
|
Point3d ptEInvertedConus = ptE - dHeight * vtLe ;
|
|
Vector3d vNewVtLs = - vtLs ;
|
|
Vector3d vNewVtLe = - vtLe ;
|
|
CompConus_5AxisMilling( nGrid, ptSInvertedConus, ptEInvertedConus, vNewVtLs, vNewVtLe, dHeight,
|
|
dTipRadius, dRadius, false, true, V_NULL, V_NULL, CurrTool.GetToolNum(), n5AxisType) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SelectGeneralMotion( int nGrid, const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtLs, const Vector3d& vtLe, int n5AxisType)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_5AxisMilling( nGrid, ptPs, ptPe, vtLs, vtLe, CurrTool.GetToolNum(), n5AxisType) ;
|
|
case Tool::CYLMILL :
|
|
return Cyl_5AxisMilling( nGrid, ptPs, ptPe, vtLs, vtLe, CurrTool.GetToolNum(), 0, n5AxisType) ;
|
|
case Tool::BALLMILL :
|
|
return CylBall_5AxisMilling( nGrid, ptPs, ptPe, vtLs, vtLe, CurrTool.GetToolNum(), n5AxisType) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_5AxisMilling( nGrid, ptPs, ptPe, vtLs, vtLe, CurrTool.GetToolNum(), n5AxisType) ;
|
|
case Tool::MORTISER :
|
|
return false ; // in realtà potremmo accettare un moto con un angolo solo along
|
|
case Tool::CHISEL :
|
|
return false ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
|
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe)
|
|
{
|
|
// Flag per impostare vecchia (approssimativa) o nuova modalità di calcolo
|
|
constexpr bool OLD_LINEAR = false ;
|
|
|
|
// Deve essere definito l'utensile corrente
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
|
|
// Angoli di rotazione longitudinale e trasversale massimi per singolo step
|
|
const double ANG_ALONG_STEP = 1.0 ;
|
|
const double ANG_ACROSS_STEP = ( OLD_LINEAR ? 0.04 : 1.0) ;
|
|
|
|
// Calcolo angoli di rotazione utensile longitudinale e trasversale rispetto al movimento per eventuale suddivisione
|
|
double dAlongAngDeg, dAcrossAngDeg ;
|
|
GetAlongAcrossRotation( vtDs, vtDe, ptPe - ptPs, dAlongAngDeg, dAcrossAngDeg) ;
|
|
|
|
// Calcolo numero degli step di movimento
|
|
int nStepCnt = int( max( { abs( dAlongAngDeg) / ANG_ALONG_STEP, abs( dAcrossAngDeg) / ANG_ACROSS_STEP, 1.})) ;
|
|
|
|
bool bOk = true ;
|
|
|
|
// Divido il movimento in tratti lineari con direzione utensile costante (approssimazione a scaletta)
|
|
if ( OLD_LINEAR) {
|
|
// Calcolo coefficiente di riduzione movimenti con direzione costante per evitare extra tagli
|
|
double dToolLen = m_vTool[m_nCurrTool].GetHeigth() ;
|
|
double dToolCrad = m_vTool[m_nCurrTool].GetCornRadius() ;
|
|
Vector3d vtBase = ptPe - ptPs ;
|
|
double dBaseLen = vtBase.Len() ;
|
|
Vector3d vtTip = ptPe - dToolLen * vtDe - ( ptPs - dToolLen * vtDs) ;
|
|
double dTipLen = vtTip.Len() ;
|
|
double dK = ( vtBase * vtTip > EPS_SMALL ? dTipLen / dBaseLen : 0) ;
|
|
if ( dTipLen / nStepCnt < 0.1 * dToolCrad)
|
|
dK = 0 ;
|
|
for ( int i = 0 ; i <= nStepCnt && bOk ; ++ i) {
|
|
double dStCoeff, dEnCoeff, dDirCoeff ;
|
|
if ( i == 0) {
|
|
dStCoeff = 0 ;
|
|
dEnCoeff = dK / nStepCnt ;
|
|
dDirCoeff = 0 ;
|
|
}
|
|
else if ( i < nStepCnt) {
|
|
dStCoeff = ( i - dK) / nStepCnt ;
|
|
dEnCoeff = ( i + dK) / nStepCnt ;
|
|
dDirCoeff = double( i) / nStepCnt ;
|
|
}
|
|
else {
|
|
dStCoeff = ( nStepCnt - dK) / nStepCnt ;
|
|
dEnCoeff = 1 ;
|
|
dDirCoeff = 1 ;
|
|
}
|
|
Point3d ptSt = Media( ptPs, ptPe, dStCoeff) ;
|
|
Point3d ptEn = Media( ptPs, ptPe, dEnCoeff) ;
|
|
Vector3d vtD = Media( vtDs, vtDe, dDirCoeff) ; vtD.Normalize() ;
|
|
Vector3d vtA = Media( vtAs, vtAe, dDirCoeff) ; vtA.Normalize() ;
|
|
bOk = bOk && MillingTranslationStep( ptSt, ptEn, vtD, vtA) ;
|
|
}
|
|
// esco
|
|
return bOk ;
|
|
}
|
|
|
|
// Divido il movimento in tratti lineari con direzione utensile variabile linearmente (approssimazione lineare)
|
|
|
|
// Determino il tipo di movimento 5 assi
|
|
Vector3d vtDir = ptPe - ptPs ;
|
|
double dH = vtDir * vtDs ;
|
|
double dHStep = abs( dH / nStepCnt) ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
double dRad = CurrTool.GetRadius() ;
|
|
bool bAcross = ( abs( dAcrossAngDeg) > EPS_SMALL) ;
|
|
bool bAcrossInters = false ;
|
|
if ( vtDe * vtDir < vtDs * vtDir)
|
|
dAlongAngDeg *= -1 ;
|
|
bool bAlong = ( abs( dAlongAngDeg) > EPS_SMALL) ;
|
|
bool bAlongInters = false ;
|
|
if ( bAcross && bAlong) {
|
|
Vector3d vtInters = vtDs ^ vtDe ;
|
|
Vector3d vtMaxDir = vtInters ^ vtDe ;
|
|
if ( ! vtMaxDir.Normalize())
|
|
return false ;
|
|
vtMaxDir *= dRad ;
|
|
if ( abs( vtMaxDir * vtDs) > dHStep) {
|
|
bAcrossInters = true ;
|
|
bAlongInters = true ;
|
|
}
|
|
}
|
|
else if ( bAcross)
|
|
bAcrossInters = ( dRad * sin( dAcrossAngDeg * DEGTORAD) > dHStep) ;
|
|
else if ( bAlong)
|
|
bAlongInters = ( dRad * sin( abs( dAlongAngDeg) * DEGTORAD) > dHStep) ;
|
|
|
|
int n5AxisType = Move5Axis::NO_BASE_INTERS ;
|
|
if ( bAcross && bAlong && ( bAcrossInters || bAlongInters))
|
|
n5AxisType = Move5Axis::ACROSS ;
|
|
else if ( bAcross) {
|
|
if ( bAcrossInters)
|
|
n5AxisType = Move5Axis::ACROSS ;
|
|
else
|
|
n5AxisType = Move5Axis::NO_BASE_INTERS ;
|
|
}
|
|
else if ( bAlong) {
|
|
if ( bAlongInters)
|
|
n5AxisType = Move5Axis::ACROSS ;
|
|
else
|
|
n5AxisType = Move5Axis::NO_BASE_INTERS ;
|
|
}
|
|
|
|
Point3d ptLs[N_MAPS] ;
|
|
Point3d ptLe[N_MAPS] ;
|
|
Vector3d vtLs[N_MAPS] ;
|
|
Vector3d vtLe[N_MAPS] ;
|
|
|
|
// calcolo gli step (anticipo un poco gli inizi intermedi)
|
|
for ( int i = 0 ; i < nStepCnt ; ++i) {
|
|
double dCoeffS = max(( i - 0.05) / nStepCnt, 0.) ;
|
|
double dCoeffE = min(( i + 1.) / nStepCnt, 1.) ;
|
|
Point3d ptSti = Media( ptPs, ptPe, dCoeffS) ;
|
|
Vector3d vtDSi = Media( vtDs, vtDe, dCoeffS) ; vtDSi.Normalize() ;
|
|
Point3d ptEni = Media( ptPs, ptPe, dCoeffE) ;
|
|
Vector3d vtDEi = Media( vtDs, vtDe, dCoeffE) ; vtDEi.Normalize() ;
|
|
|
|
InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, ptLs, ptLe, vtLs, vtLe) ;
|
|
|
|
// Standard è multithread
|
|
constexpr bool MULTITHREAD = false ;
|
|
if ( MULTITHREAD) {
|
|
// Ciclo sulle mappe
|
|
vector<future<bool>> vRes( m_nMapNum) ;
|
|
|
|
for ( int j = 0 ; j < m_nMapNum ; ++j) {
|
|
vRes[j] = async(launch::async, &VolZmap::SelectGeneralMotion, this, j, cref(ptLs[j]), cref(ptLe[j]), cref(vtLs[j]), cref(vtLe[j]), n5AxisType) ;
|
|
}
|
|
|
|
int nTerminated = 0;
|
|
while ( nTerminated < m_nMapNum) {
|
|
for ( int j = 0 ; j < m_nMapNum ; ++j) {
|
|
if ( vRes[j].valid() && vRes[j].wait_for(chrono::nanoseconds{ 1 }) == future_status::ready) {
|
|
bOk = vRes[j].get() && bOk ;
|
|
++nTerminated ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
|
else {
|
|
// Ciclo sulle mappe
|
|
for ( int j = 0 ; j < m_nMapNum ; ++j) {
|
|
bOk = SelectGeneralMotion(j, ptLs[j], ptLe[j], vtLs[j], vtLe[j], n5AxisType) && bOk ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA)
|
|
{
|
|
// Assegno i dati per le diverse mappe di spilloni presenti
|
|
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) ;
|
|
|
|
// Standarda è multithread
|
|
constexpr bool MULTITHREAD = true ;
|
|
if ( MULTITHREAD) {
|
|
// Ciclo sulle mappe
|
|
vector< future<bool>> vRes( 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 bOk ;
|
|
}
|
|
|
|
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
|
else {
|
|
// Ciclo sulle mappe
|
|
bool bOk = true ;
|
|
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
|
|
bOk = SelectMotion( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) && bOk ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_ZDrilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
return Chs_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
}
|
|
}
|
|
|
|
// Fresatura con vettore movimento perpendicolare all'utensile
|
|
else if ( abs( vtMove.z) < EPS_SMALL) {
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_ZPerp( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_ZPerp( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::ADDITIVE :
|
|
return AddingMotion( nGrid, ptLs, ptLe, vtL) ;
|
|
}
|
|
}
|
|
|
|
// Fresatura con vettore movimento generico rispetto all'utensile
|
|
else {
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_ZMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_ZMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::ADDITIVE :
|
|
return AddingMotion( nGrid, ptLs, ptLe, vtL) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_XYDrilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_XYDrilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
return Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
}
|
|
}
|
|
// Fresatura con vettore movimento perpendicolare all'utensile
|
|
else if ( dSqLLong < EPS_SMALL * EPS_SMALL) {
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_Milling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_XYPerp( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
// Usiamo la generica per via dell'intsabilità di Conus_XYPerp
|
|
//return Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ;
|
|
return Conus_Milling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::ADDITIVE :
|
|
return AddingMotion( nGrid, ptLs, ptLe, vtL) ;
|
|
}
|
|
}
|
|
// Fresatura con vettore movimento generico rispetto all'utensile
|
|
else {
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_Milling( nGrid, ptLs, ptLe, vtL);
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_XYMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_XYMilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::ADDITIVE :
|
|
return AddingMotion( nGrid, ptLs, ptLe, vtL) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_Drilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_Drilling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
return Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
}
|
|
}
|
|
// Fresatura con vettore movimento generico rispetto all'utensile
|
|
else {
|
|
switch ( CurrTool.GetType()) {
|
|
case Tool::GEN :
|
|
return GenTool_Milling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CYLMILL :
|
|
case Tool::BALLMILL :
|
|
return CylBall_Milling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::CONEMILL :
|
|
return Conus_Milling( nGrid, ptLs, ptLe, vtL) ;
|
|
case Tool::MORTISER :
|
|
return Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
case Tool::CHISEL :
|
|
// ammesso solo movimento perpendicolare all'asse utensile
|
|
if ( dSqLLong < EPS_SMALL * EPS_SMALL)
|
|
return Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ;
|
|
break ;
|
|
case Tool::ADDITIVE :
|
|
return AddingMotion( nGrid, ptLs, ptLe, vtL) ;
|
|
}
|
|
}
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
|
|
// ---------- VERSORE UTENSILE DIRETTO COME Z --------------------------------
|
|
|
|
// ---------- Cilindro e sfera -----------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.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 * CurrTool.GetRadius() * EPS_SMALL) {
|
|
// utensile cilindrico
|
|
if ( CurrTool.GetType() == Tool::CYLMILL)
|
|
SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, -Z_AX, CurrTool.GetToolNum()) ;
|
|
// utensile sferico
|
|
else if ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dSafeRad = CurrTool.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 ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Utensile sferico
|
|
else if ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_ZMilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dSafeRadius = CurrTool.GetRadius() - EPS_SMALL ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.GetRadius() ;
|
|
double dSafeSqRad = dSqRad - 2 * CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( CurrTool.GetType() == Tool::BALLMILL)
|
|
|
|
CompBall_Milling( nGrid, ptIT, ptFT, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
// ---------- Coni -----------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dMinRad = min( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dMaxRad = max( CurrTool.GetRadius(), CurrTool.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 * CurrTool.GetHeigth()),
|
|
max( ptE.z, ptE.z - vtToolDir.z * CurrTool.GetHeigth())) ;
|
|
double dZMin = min( min( ptS.z, ptS.z - vtToolDir.z * CurrTool.GetHeigth()),
|
|
min( ptE.z, ptE.z - vtToolDir.z * CurrTool.GetHeigth())) ;
|
|
|
|
// Parametri geometrici per
|
|
// determinare il vettore normale
|
|
double dL = CurrTool.GetTipHeigth() * dMaxRad / dDeltaRad ;
|
|
|
|
// Trapano
|
|
if ( CurrTool.GetTipRadius() < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
|
|
else if ( dSqDist < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDist) ;
|
|
double dl = dr * dMaxRad / dL ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
|
|
double dMin = dZMin + CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
double dMin = dZMin ;
|
|
double dMax = dZMax - CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else if ( dSqDist < dSqMaxRad) {
|
|
|
|
double dr = sqrt( dSqDist) ;
|
|
double dl = dr * dMaxRad / dL ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
double dMin = dZMin ;
|
|
double dMax = dZMax - dStemHeigth - CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
double dMin = dZMin + dStemHeigth + CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZPerp( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dMinRad = min( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dMaxRad = max( CurrTool.GetRadius(), CurrTool.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 * CurrTool.GetHeigth() ;
|
|
|
|
// Lunghezza cono
|
|
double dL = CurrTool.GetTipHeigth() * dMaxRad / dDeltaRad ;
|
|
|
|
// Punta a trapano
|
|
if ( CurrTool.GetTipRadius() < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmax.Normalize() ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmax.Normalize() ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmax.Normalize() ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Coda di rondine
|
|
else {
|
|
|
|
Vector3d vtV = - vtToolDir ;
|
|
|
|
Point3d ptVS = ptS - vtToolDir * ( CurrTool.GetHeigth() - dL) ;
|
|
Point3d ptVE = ptE - vtToolDir * ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmin.Normalize() ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmin.Normalize() ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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 - CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmin.Normalize() ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
double dStemH = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
|
|
CompCyl_ZMilling( nGrid, ptS, ptE, vtToolDir, dStemH, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
|
|
if ( CurrTool.GetTipRadius() < CurrTool.GetRadius()) {
|
|
Point3d ptSC = ptS - vtToolDir * dStemH ;
|
|
Point3d ptEC = ptE - vtToolDir * dStemH ;
|
|
CompConus_ZMilling( nGrid, ptSC, ptEC, vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetRadius(), CurrTool.GetTipRadius(), V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
Point3d ptSC = ptS - vtToolDir * CurrTool.GetHeigth() ;
|
|
Point3d ptEC = ptE - vtToolDir * CurrTool.GetHeigth() ;
|
|
CompConus_ZMilling( nGrid, ptSC, ptEC, - vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetTipRadius(), CurrTool.GetRadius(), V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// --------- Mortasatrice -----------------------------------------------------
|
|
|
|
// ----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Mrt_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetMrtChsWidth() ;
|
|
double dLenY = CurrTool.GetMrtChsThickness() ;
|
|
double dLenZ = CurrTool.GetHeigth() - CurrTool.GetCornRadius() ;
|
|
|
|
CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
// Se la punta è di tipo bull-nose
|
|
if ( abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) > EPS_SMALL) {
|
|
|
|
// Parallelepipedo di punta
|
|
Point3d ptTipS = ptS - dLenZ * vtToolDir ;
|
|
Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ;
|
|
|
|
dLenX = abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) ;
|
|
dLenZ = CurrTool.GetCornRadius() ;
|
|
|
|
CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// 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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
|
|
// --------- Chisel ----------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Chs_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
CompPar_ZDrilling( nGrid, CurrTool.GetMrtChsWidth(), CurrTool.GetMrtChsThickness(), CurrTool.GetHeigth(),
|
|
ptS, ptE, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Chs_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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, CurrTool.GetMrtChsWidth(), CurrTool.GetMrtChsThickness(), CurrTool.GetHeigth(),
|
|
ptSp, ptEp, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
return true ;
|
|
}
|
|
|
|
// --------- Utensile generico ------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Descrizione geometrica del moto
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
Vector3d vtMove = ptE - ptS ;
|
|
// Vettore delle normali agli archi
|
|
const VCT3DVECTOR& vArcNorm = CurrTool.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 = CurrTool.GetApproxOutline() ;
|
|
int i = - 1 ;
|
|
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) {
|
|
// Se X costante, è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
double dRadius = ptStart.x ;
|
|
if ( dRadius > 10 * EPS_SMALL)
|
|
CompCyl_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius, CurrTool.GetToolNum()) ;
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// 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)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Descrizione geometrica del moto
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
Vector3d vtMove = ptE - ptS ;
|
|
// Vettore delle normali agli archi
|
|
const VCT3DVECTOR& vArcNorm = CurrTool.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 = CurrTool.GetApproxOutline() ;
|
|
int i = - 1 ;
|
|
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) {
|
|
// Se X costante, è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
double dRadius = ptStart.x ;
|
|
if ( dRadius > 10 * EPS_SMALL)
|
|
CompCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius, CurrTool.GetToolNum()) ;
|
|
// aggiorno l'altezza
|
|
dHeight = abs( ptStart.y - ptEnd.y) ;
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtToolDir * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
|
|
// 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)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.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) < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Se l'utensile è sferico sottraggo anche la punta
|
|
if ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_XYPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d & vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.GetRadius() ;
|
|
double dSafeSqRad = dSqRad - 2 * CurrTool.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 + CurrTool.GetRadius() * ( vtP.z > 0 ? vtP : - vtP) ;
|
|
Point3d ptDw = ptI + CurrTool.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 = CurrTool.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 > - CurrTool.GetRadius() + EPS_SMALL &&
|
|
dP2 < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
if ( CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 > - CurrTool.GetRadius() && dP2 < dLenXY + CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
|
|
// Se l'utensile è ball-end sottraggo la punta
|
|
if ( CurrTool.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 < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_XYMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
if ( CurrTool.GetType() == Tool::CYLMILL)
|
|
return CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, CurrTool.GetHeigth(), CurrTool.GetRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
|
|
else if ( CurrTool.GetType() == Tool::BALLMILL) {
|
|
double dHei = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, CurrTool.GetRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
CompBall_Milling( nGrid, ptS - dHei * vtToolDir, ptE - dHei * vtToolDir, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
return true ;
|
|
}
|
|
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
|
|
// --------- Coni ------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dMinRad = min( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dMaxRad = max( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dDeltaRad = dMaxRad - dMinRad ;
|
|
|
|
// Geometria del moto
|
|
double dLenXY = ( ptE - ptS).LenXY() ;
|
|
Point3d ptI = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) ;
|
|
double dMatStemLen = ( CurrTool.GetRadius() > CurrTool.GetTipRadius() ? dStemHeigth + dLenXY : dStemHeigth) ;
|
|
double dSqTipRad = CurrTool.GetTipRadius() * CurrTool.GetTipRadius() ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.GetRadius() ;
|
|
|
|
// Determinazione del vertice del cono
|
|
double dL = CurrTool.GetTipHeigth() * dMaxRad / dDeltaRad ;
|
|
|
|
Point3d ptV ; // Vertice
|
|
Vector3d vtV ; // Vettore riferimento con origine nel vertice
|
|
|
|
if ( CurrTool.GetRadius() > CurrTool.GetTipRadius()) {
|
|
vtV = vtToolDir ;
|
|
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * ( dStemHeigth + dL) ;
|
|
}
|
|
|
|
else {
|
|
vtV = - vtToolDir ;
|
|
ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) - vtToolDir * ( CurrTool.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 = CurrTool.GetRadius() + ( dX1 - dMatStemLen) * ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) / CurrTool.GetTipHeigth() ;
|
|
|
|
if ( dX1 > EPS_SMALL && dX1 < dMatStemLen && abs( dX2) < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else if ( dX1 >= dMatStemLen &&
|
|
dX1 < dMatStemLen + CurrTool.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 - CurrTool.GetTipHeigth() * vtUmin ;
|
|
vtNmin.Normalize() ;
|
|
|
|
Point3d ptIntMax( dX, dY, dMax) ;
|
|
Vector3d vtUmax = ( ptIntMax - ptV) - ( ptIntMax - ptV) * vtV * vtV ;
|
|
vtUmax.Normalize() ;
|
|
Vector3d vtNmax = dDeltaRad * vtV - CurrTool.GetTipHeigth() * vtUmax ;
|
|
vtNmax.Normalize() ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
if ( CurrTool.GetTipRadius() >= CurrTool.GetRadius()) {
|
|
|
|
if ( dX1 > dMatStemLen + CurrTool.GetTipHeigth() - 2 * EPS_SMALL &&
|
|
dX1 < dMatStemLen + CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
double dMinRad = min( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dMaxRad = max( CurrTool.GetRadius(), CurrTool.GetTipRadius()) ;
|
|
double dSqRad = CurrTool.GetRadius() * CurrTool.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 = CurrTool.GetTipHeigth() * dMaxRad / dDeltaRad ;
|
|
Vector3d vtV = ( CurrTool.GetRadius() > CurrTool.GetTipRadius() ? vtToolDir : - vtToolDir) ;
|
|
Point3d ptVI = ptI - ( CurrTool.GetRadius() > CurrTool.GetTipRadius() ? dStemHeigth + dL : CurrTool.GetHeigth() - dL) * vtToolDir ;
|
|
Point3d ptVF = ptF - ( CurrTool.GetRadius() > CurrTool.GetTipRadius() ? dStemHeigth + dL : CurrTool.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 > - CurrTool.GetRadius() + EPS_SMALL && dP2 < CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Parte conica
|
|
else if ( dP1 > dStemHeigth && dP1 < CurrTool.GetHeigth() - EPS_SMALL && abs( dP2) < CurrTool.GetRadius() +
|
|
( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth() - EPS_SMALL) {
|
|
|
|
double dr = dP2 ;
|
|
double dMr = CurrTool.GetRadius() + ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.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 - CurrTool.GetTipHeigth() * vtUmin ;
|
|
vtNmin.Normalize() ;
|
|
|
|
Point3d ptIntMax( dX, dY, dMax) ;
|
|
Vector3d vtUmax = ( ptIntMax - ptVF) - ( ptIntMax - ptVF) * vtV * vtV ;
|
|
vtUmax.Normalize() ;
|
|
Vector3d vtNmax = dDeltaRad * vtV - CurrTool.GetTipHeigth() * vtUmax ;
|
|
vtNmax.Normalize() ;
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 + CurrTool.GetRadius() * vtCross ;
|
|
Point3d ptDw = ptI - vtToolDir * dStemHeigth - CurrTool.GetRadius() * vtCross ;
|
|
double dSmallLength = CurrTool.GetRadius() * vtCross.LenXY() ;
|
|
// Punti di tangenza in corrispondenza della punta
|
|
Point3d ptTipUp = ptI - vtToolDir * CurrTool.GetHeigth() + CurrTool.GetTipRadius() * vtCross ;
|
|
Point3d ptTipDw = ptI - vtToolDir * CurrTool.GetHeigth() - CurrTool.GetTipRadius() * vtCross ;
|
|
|
|
Vector3d vtUpTan = ptTipUp - ptUp ;
|
|
Vector3d vtDwTan = ptTipDw - ptDw ;
|
|
|
|
Vector3d vtUpTanXY( vtUpTan.x, vtUpTan.y, 0) ;
|
|
double dDeltaSmallAbs = abs( vtUpTanXY * vtV2) ;
|
|
double dDeltaSmall = ( CurrTool.GetRadius() > CurrTool.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 > - CurrTool.GetRadius() && dP2 < dLengthPathXY + CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Parte conica
|
|
else if ( dP1 > dStemHeigth && dP1 < CurrTool.GetHeigth() - EPS_SMALL &&
|
|
dP2 > - CurrTool.GetRadius() - ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth() &&
|
|
dP2 < CurrTool.GetRadius() + dLengthPathXY +
|
|
( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth()) {
|
|
|
|
// Massimi
|
|
if ( dP2 < - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth()) {
|
|
|
|
double dr = dP2 ;
|
|
double dMr = CurrTool.GetRadius() + ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmax.Normalize() ;
|
|
}
|
|
|
|
else if ( dP2 < dLengthPathXY - dSmallLength +
|
|
dDeltaSmall * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth()) {
|
|
dMax = ( dDotUp - dX * vtUpCross.x - dY * vtUpCross.y) / vtUpCross.z ;
|
|
vtNmax = vtUpCross ;
|
|
}
|
|
|
|
else {
|
|
double dr = dP2 - dLengthPathXY ;
|
|
double dMr = CurrTool.GetRadius() + ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmax.Normalize() ;
|
|
}
|
|
|
|
// Minimi
|
|
if ( dP2 < dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth()) {
|
|
|
|
double dr = dP2 ;
|
|
double dMr = CurrTool.GetRadius() + ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmin.Normalize() ;
|
|
}
|
|
|
|
else if ( dP2 < dLengthPathXY + dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / CurrTool.GetTipHeigth()) {
|
|
dMin = ( dDotDw - dX * vtDwCross.x - dY * vtDwCross.y) / vtDwCross.z ;
|
|
vtNmin = vtDwCross ;
|
|
}
|
|
|
|
else {
|
|
|
|
double dr = dP2 - dLengthPathXY ;
|
|
double dMr = CurrTool.GetRadius() + ( CurrTool.GetTipRadius() - CurrTool.GetRadius()) * ( dP1 - dStemHeigth) / CurrTool.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 - CurrTool.GetTipHeigth() * vtU ;
|
|
vtNmin.Normalize() ;
|
|
}
|
|
|
|
SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_XYMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
double dStemHeigth = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, CurrTool.GetRadius(), false, true, CurrTool.GetToolNum()) ;
|
|
|
|
if ( CurrTool.GetTipRadius() < CurrTool.GetRadius()) {
|
|
Point3d ptSTip = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptETip = ptE - dStemHeigth * vtToolDir ;
|
|
CompConus_Milling( nGrid, ptSTip, ptETip, vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetRadius(), CurrTool.GetTipRadius(),
|
|
true, false, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
Point3d ptSTip = ptS - CurrTool.GetHeigth() * vtToolDir ;
|
|
Point3d ptETip = ptE - CurrTool.GetHeigth() * vtToolDir ;
|
|
CompConus_Milling( nGrid, ptSTip, ptETip, - vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetTipRadius(), CurrTool.GetRadius(),
|
|
false, true, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
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)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Altezza cilindro
|
|
double dStemHeigth = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
// Sottraggo cilindro
|
|
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, CurrTool.GetRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
// Se è sfera la sottraggo
|
|
if ( CurrTool.GetType() == Tool::BALLMILL) {
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
CompBall_Milling( nGrid, ptSBall, ptEBall, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CylBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Altezza cilindro
|
|
double dStemHeigth = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
// Sottraggo cilindro
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, CurrTool.GetRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
// Se è sfera la sottraggo
|
|
if ( CurrTool.GetType() == Tool::BALLMILL) {
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
CompBall_Milling( nGrid, ptSBall, ptEBall, CurrTool.GetRadius(), CurrTool.GetToolNum()) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Coni -----------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
double dStemHeigth = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
|
|
CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, CurrTool.GetRadius(), false, true, CurrTool.GetToolNum()) ;
|
|
|
|
// Trapano
|
|
if ( CurrTool.GetTipRadius() < CurrTool.GetRadius()) {
|
|
Point3d ptSCone = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptECone = ptE - dStemHeigth * vtToolDir ;
|
|
CompConus_Drilling( nGrid, ptSCone, ptECone, vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetRadius(), CurrTool.GetTipRadius(),
|
|
true, false, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
Point3d ptSCone = ptS - CurrTool.GetHeigth() * vtToolDir ;
|
|
Point3d ptECone = ptE - CurrTool.GetHeigth() * vtToolDir ;
|
|
CompConus_Drilling( nGrid, ptSCone, ptECone, - vtToolDir,
|
|
CurrTool.GetTipHeigth(), CurrTool.GetTipRadius(), CurrTool.GetRadius(),
|
|
false, true, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
double dStemHeigth = CurrTool.GetHeigth() - CurrTool.GetTipHeigth() ;
|
|
|
|
CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, CurrTool.GetRadius(), false, true, CurrTool.GetToolNum()) ;
|
|
|
|
// Trapano
|
|
if ( CurrTool.GetTipRadius() < CurrTool.GetRadius()) {
|
|
Point3d ptSBall = ptS - dStemHeigth * vtToolDir ;
|
|
Point3d ptEBall = ptE - dStemHeigth * vtToolDir ;
|
|
CompConus_Milling( nGrid, ptSBall, ptEBall, vtToolDir, CurrTool.GetTipHeigth(),
|
|
CurrTool.GetRadius(), CurrTool.GetTipRadius(), true, false, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
else {
|
|
Point3d ptSBall = ptS - CurrTool.GetHeigth() * vtToolDir ;
|
|
Point3d ptEBall = ptE - CurrTool.GetHeigth() * vtToolDir ;
|
|
CompConus_Milling( nGrid, ptSBall, ptEBall, - vtToolDir, CurrTool.GetTipHeigth(),
|
|
CurrTool.GetTipRadius(), CurrTool.GetRadius(), false, true, V_NULL, V_NULL, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Mortasatrice ---------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// 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 = CurrTool.GetMrtChsWidth() ;
|
|
double dLenY = CurrTool.GetMrtChsThickness() ;
|
|
double dLenZ = CurrTool.GetHeigth() - CurrTool.GetCornRadius() ;
|
|
CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
// Se la punta è di tipo bull-nose
|
|
if ( abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) > EPS_SMALL) {
|
|
|
|
// Parallelepipedo di punta
|
|
Point3d ptTipS = ptS - dLenZ * vtToolDir ;
|
|
Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ;
|
|
|
|
dLenX = abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) ;
|
|
dLenZ = CurrTool.GetCornRadius() ;
|
|
|
|
CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// 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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Scompongo la mortasatrice in solidi semplici
|
|
|
|
// Parallelepipedo di base
|
|
double dLenX = CurrTool.GetMrtChsWidth() ;
|
|
double dLenY = CurrTool.GetMrtChsThickness() ;
|
|
double dLenZ = CurrTool.GetHeigth() - CurrTool.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, CurrTool.GetToolNum()) ;
|
|
// Se la punta è di tipo bull-nose
|
|
if ( abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) > EPS_SMALL) {
|
|
|
|
// Parallelepipedo di punta
|
|
Point3d ptTipPS = ptBasePS - 0.5 * dLenZ * vtToolDir ;
|
|
Point3d ptTipPE = ptBasePE - 0.5 * dLenZ * vtToolDir ;
|
|
|
|
dLenX = abs( CurrTool.GetMrtChsWidth() - 2 * CurrTool.GetCornRadius()) ;
|
|
dLenZ = CurrTool.GetCornRadius() ;
|
|
|
|
ptTipPS -= 0.5 * dLenZ * vtToolDir ;
|
|
ptTipPE -= 0.5 * dLenZ * vtToolDir ;
|
|
|
|
CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptTipPS, ptTipPE, vtAux, vtToolDir, CurrTool.GetToolNum()) ;
|
|
// 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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// 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, CurrTool.GetCornRadius(), false, false, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Chisel ---------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Proiezione della traiettoria sulla varietà del movimento
|
|
Point3d ptProjE = ptS + ( ptE - ptS) * vtToolDir * vtToolDir ;
|
|
|
|
CompPar_Drilling( nGrid, CurrTool.GetMrtChsWidth(), CurrTool.GetMrtChsThickness(), CurrTool.GetHeigth(),
|
|
ptS, ptProjE, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Proiezione della traiettoria sul piano dei movimenti possibili
|
|
Vector3d vtMoveOnP = ( ptE - ptS) - ( ptE - ptS) * vtToolDir * vtToolDir ;
|
|
Point3d ptProjE = ptS + vtMoveOnP ;
|
|
|
|
CompPar_Milling( nGrid, CurrTool.GetMrtChsWidth(), CurrTool.GetMrtChsThickness(), CurrTool.GetHeigth(),
|
|
ptS, ptProjE, vtToolDir, vtAux, CurrTool.GetToolNum()) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- Utensile generico ----------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Descrizione geometrica del moto
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
Vector3d vtMove = ptE - ptS ;
|
|
// Vettore delle normali agli archi
|
|
const VCT3DVECTOR& vArcNorm = CurrTool.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 = CurrTool.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, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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, CurrTool.GetToolNum()) ;
|
|
// 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_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Descrizione geometrica del moto
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
Vector3d vtMove = ptE - ptS ;
|
|
// Vettore delle normali agli archi
|
|
const VCT3DVECTOR& vArcNorm = CurrTool.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 = CurrTool.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 = 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 = true ;
|
|
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 = false ;
|
|
}
|
|
// Se X costante, è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
double dRadius = ptStart.x ;
|
|
if ( dRadius > 10 * EPS_SMALL)
|
|
CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT, CurrTool.GetToolNum()) ;
|
|
}
|
|
// se altrimenti X decrescente, è un cono con vettore equiverso a quello dell'utensile
|
|
else if ( ptStart.x > ptEnd.x) {
|
|
double dMaxRad = ptStart.x ;
|
|
double dMinRad = ptEnd.x ;
|
|
CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad,
|
|
bTapB, bTapT, vtNormSt, vtNormEn, CurrTool.GetToolNum()) ;
|
|
}
|
|
// altrimenti X crescente, è un cono con vettore opposto a quello dell'utensile
|
|
else {
|
|
double dMaxRad = ptEnd.x ;
|
|
double dMinRad = ptStart.x ;
|
|
Point3d ptIn = ptI - vtToolDir * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
vtNormEn.z = -vtNormEn.z ;
|
|
vtNormSt.z = -vtNormSt.z ;
|
|
CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad,
|
|
bTapT, bTapB, vtNormEn, vtNormSt, CurrTool.GetToolNum()) ;
|
|
}
|
|
// 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, CurrTool.GetToolNum()) ;
|
|
// 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 ;
|
|
}
|
|
|
|
// ------------------------- 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, int nToolNum)
|
|
{
|
|
// Verifica sull'interferenza con lo Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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, nToolNum) ;
|
|
}
|
|
}
|
|
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, int nToolNum)
|
|
{
|
|
// i vettori vtArcNormMaxR e vtArcNormMinR servono nel caso in cui un tratto del tool sia identificato da un arco, ma si decida di approssimarlo con un cono
|
|
// in quel caso per il calcolo corretto della normale viene fatta una somma pesata tra le normali alla superficie nei punti estremi dell'arco
|
|
// i pesi sono riferiti alla posizione relativa dell'intersezione spillone-superficie e questi due punti estremi
|
|
|
|
// Verifica sull'interferenza con lo Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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, nToolNum) ;
|
|
}
|
|
|
|
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, nToolNum) ;
|
|
}
|
|
|
|
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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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, int nToolNum)
|
|
{
|
|
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, nToolNum) ;
|
|
}
|
|
}
|
|
|
|
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, int nToolNum)
|
|
{
|
|
// Verifica sull'interferenza con lo Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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 ;
|
|
|
|
// calcolo il box del volume spazzato
|
|
BBox3d bbVol = GetCylMoveBBox(ptS, ptE, vtToolDir, dRad, dHei) ;
|
|
INTDBLVECTOR vIntersDash ;
|
|
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 ;
|
|
|
|
// calcolo l'intersezione solo se ho un tratto sullo spillone che interseca il volume spazzato dal tool
|
|
int nPos = j * m_nNx[nGrid] + i;
|
|
vector<Data>& vDexel = m_Values[nGrid][nPos];
|
|
DBLDBLVECTOR vInterv ;
|
|
for (int k = 0; k < int ( vDexel.size () ); ++k)
|
|
vInterv.emplace_back ( vDexel[k].dMin, vDexel[k].dMax ) ;
|
|
|
|
bool bIntersVol = false ;
|
|
if ( vDexel.size () != 0) {
|
|
for (int k = 0; k < int ( vInterv.size () ) && !bIntersVol; ++k) {
|
|
IntersLineBox ( ptC + Z_AX * vInterv[k].first, ptC + Z_AX * vInterv[k].second, bbVol, vIntersDash, true ) ;
|
|
bIntersVol = vIntersDash.size () > 0 ;
|
|
}
|
|
if ( bIntersVol) {
|
|
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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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 nToolNum)
|
|
{
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
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, int nToolNum)
|
|
{
|
|
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, nToolNum) ;
|
|
|
|
// 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, nToolNum) ;
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
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, int nToolNum)
|
|
{
|
|
// Verifico che il cilindro con il suo movimento intersechi la griglia
|
|
int nStartI, nEndI, nStartJ, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
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 nToolNum)
|
|
{
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
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, int nToolNum)
|
|
{
|
|
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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
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, int nToolNum)
|
|
{
|
|
// Verifica sull'interferenza utensile Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, 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() ;
|
|
|
|
// Parametri di contenimento
|
|
Vector3d vtPerp = vtToolDir ^ Z_AX ;
|
|
bool bPerpOk = vtPerp.Normalize() ;
|
|
if ( vtPerp * vtMove < 0)
|
|
vtPerp.Invert() ;
|
|
int nSkip = 0 ;
|
|
|
|
// calcolo il box del volume spazzato
|
|
Frame3d frVol ; frVol.Set( ptI, vtToolDir, vtMove) ;
|
|
Point3d ptILoc = ptI ; ptILoc.ToLoc( frVol) ;
|
|
Point3d ptFLoc = ptF ; ptFLoc.ToLoc( frVol) ;
|
|
Vector3d vtToolLoc = vtToolDir ; vtToolLoc.ToLoc( frVol) ;
|
|
BBox3d bbVol = GetCylMoveBBox( ptILoc, ptFLoc, vtToolLoc, dRad, dHei) ;
|
|
INTDBLVECTOR vIntersDash ;
|
|
|
|
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) ;
|
|
|
|
// calcolo l'intersezione solo se ho un tratto sullo spillone che interseca il volume spazzato dal tool
|
|
int nPos = j * m_nNx[nGrid] + i;
|
|
vector<Data>& vDexel = m_Values[nGrid][nPos];
|
|
DBLDBLVECTOR vInterv ;
|
|
for ( int k = 0 ; k < int ( vDexel.size ()); ++k)
|
|
vInterv.emplace_back( vDexel[k].dMin, vDexel[k].dMax) ;
|
|
|
|
Point3d ptCLoc = ptC ; ptCLoc.ToLoc( frVol) ;
|
|
Vector3d vtZLoc = Z_AX ; vtZLoc.ToLoc( frVol) ;
|
|
bool bIntersVol = false ;
|
|
if ( vDexel.size () != 0) {
|
|
for ( int k = 0 ; k < int ( vInterv.size ()) && ! bIntersVol ; ++k) {
|
|
IntersLineBox ( ptCLoc + vtZLoc * vInterv[k].first, ptCLoc + vtZLoc * vInterv[k].second, bbVol, vIntersDash, true) ;
|
|
bIntersVol = vIntersDash.size () > 0 ;
|
|
}
|
|
if ( bIntersVol) {
|
|
// salto il controllo degli spilloni sotto il piano limite in basso o sopra il piano limite in alto
|
|
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL &&
|
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL) {
|
|
++ nSkip ;
|
|
continue ;
|
|
}
|
|
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL &&
|
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL) {
|
|
++ nSkip ;
|
|
continue ;
|
|
}
|
|
|
|
// salto il controllo degli spilloni prima del piano di fianco verticale di inizio o dopo il piano di fianco verticale di fine
|
|
if ( bPerpOk &&
|
|
( ptC + Z_AX * m_dMinZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL &&
|
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL) {
|
|
++ nSkip ;
|
|
continue ;
|
|
}
|
|
if ( bPerpOk &&
|
|
( ptC + Z_AX * m_dMinZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL &&
|
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL) {
|
|
++ nSkip ;
|
|
continue ;
|
|
}
|
|
|
|
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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//string sLog = "Skipped dexel = " + ToString( nSkip) + " / " + ToString( ( nEndI - nStartI + 1) * ( nEndJ - nStartJ + 1)) ;
|
|
//LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static Vector3d
|
|
AdjustConeNormal( const Point3d& ptInt, const Vector3d& vtN, const Point3d& ptV, const Vector3d& vtToolDir,
|
|
double dMinRad, double dDeltaR, const Vector3d& vtArcNormMinR, const Vector3d& vtArcNormMaxR)
|
|
{
|
|
if ( AreSameOrOppositeVectorEpsilon( vtN, vtToolDir, 0.1 * EPS_SMALL))
|
|
return vtN ;
|
|
Vector3d vtL = ( ptInt - ptV) - (( ptInt - ptV) * vtToolDir) * vtToolDir ;
|
|
double dL = vtL.Len() ;
|
|
vtL /= dL ;
|
|
Vector3d vtOriginalN = ( ( dDeltaR - dL + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL - dMinRad) / dDeltaR) * vtArcNormMaxR ;
|
|
Vector3d vtNewN = - vtOriginalN.z * vtToolDir - vtOriginalN.x * vtL ;
|
|
vtNewN.Normalize() ;
|
|
return vtNewN ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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, int nToolNum)
|
|
{
|
|
// Verifico interferenza
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, V_NULL, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
|
|
return true ;
|
|
|
|
// Geometria del cono
|
|
double dDeltaR = dMaxRad - dMinRad ;
|
|
|
|
// Studio simmetrie
|
|
Point3d ptI = ptS ;
|
|
Point3d ptF = ptE ;
|
|
if ( vtToolDir * ( ptE - ptS) <= 0)
|
|
swap( ptI, ptF) ;
|
|
|
|
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) ;
|
|
|
|
// Necessità ricalcolo normali (perchè variabili per approx curve)
|
|
bool bRecalNorm = ( ! vtArcNormMaxR.IsSmall() && ! vtArcNormMinR.IsSmall()) ;
|
|
|
|
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 ( bRecalNorm) {
|
|
vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
|
}
|
|
|
|
// Cono finale
|
|
ConusFrame.ChangeOrig( ptV + vtMove) ;
|
|
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
|
if ( bRecalNorm) {
|
|
vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV + vtMove, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV + vtMove, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
|
}
|
|
|
|
// Solido interno
|
|
Point3d ptPoly = GetToLoc( ptC, PolyFrame) ;
|
|
Vector3d vtPoly = GetToLoc( Z_AX, PolyFrame) ;
|
|
|
|
// Intervallo di intersezione (infinito) e normali (nulle)
|
|
bool bValid = true ;
|
|
double dPar1 = -INFINITO ;
|
|
double dPar2 = +INFINITO ;
|
|
vtN1 = V_NULL ;
|
|
vtN2 = V_NULL ;
|
|
|
|
// Verifica con facce iniziale e finale
|
|
if ( bValid) {
|
|
// Distanza con segno del punto di riferimento del dexel dal piano delle facce iniziale e finale
|
|
double dDistI = ( ptPoly - ptFacet135) * -vtIF ;
|
|
double dDistF = ( ptPoly - ptFacet246) * vtIF ;
|
|
// Se dexel non parallelo alle facce
|
|
if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) {
|
|
// posizione parametrica delle intersezioni
|
|
double dParI = -dDistI / ( vtPoly * -vtIF) ;
|
|
double dParF = -dDistF / ( vtPoly * vtIF) ;
|
|
// se intervallo tra intersezioni praticamente nullo
|
|
if ( abs( dParI - dParF) < EPS_ZERO)
|
|
bValid = false ;
|
|
// altrimenti
|
|
else {
|
|
if ( dParI < dParF) {
|
|
dPar1 = dParI ;
|
|
vtN1 = vtIF ;
|
|
dPar2 = dParF ;
|
|
vtN2 = -vtIF ;
|
|
}
|
|
else {
|
|
dPar1 = dParF ;
|
|
vtN1 = -vtIF ;
|
|
dPar2 = dParI ;
|
|
vtN2 = vtIF ;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti praticamente parallelo
|
|
else {
|
|
// se esterno ad almeno uno invalida tutto
|
|
if ( dDistI > 0 || dDistF > 0)
|
|
bValid = false ;
|
|
// altrimenti non cambia niente
|
|
}
|
|
}
|
|
|
|
// Verifica con facce sopra e sotto
|
|
if ( bValid) {
|
|
// Distanza con segno del punto di riferimento del dexel dal piano delle facce sopra e sotto
|
|
double dDistU = ( ptPoly - ptFacet246) * -vtUD ;
|
|
double dDistD = ( ptPoly - ptFacet135) * vtUD ;
|
|
// Se dexel non parallelo alle facce
|
|
if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) {
|
|
// posizione parametrica delle intersezioni
|
|
double dParU = -dDistU / ( vtPoly * -vtUD) ;
|
|
double dParD = -dDistD / ( vtPoly * vtUD) ;
|
|
// se intervallo tra intersezioni praticamente nullo
|
|
if ( abs( dParU - dParD) < EPS_ZERO)
|
|
bValid = false ;
|
|
// altrimenti
|
|
else {
|
|
if ( dParU < dParD) {
|
|
if ( dParD < dPar1 + EPS_ZERO || dParU > dPar2 - EPS_ZERO)
|
|
bValid = false ;
|
|
else {
|
|
if ( dParU > dPar1) {
|
|
dPar1 = dParU ;
|
|
vtN1 = vtUD ;
|
|
}
|
|
if ( dParD < dPar2) {
|
|
dPar2 = dParD ;
|
|
vtN2 = -vtUD ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ( dParU < dPar1 + EPS_ZERO || dParD > dPar2 - EPS_ZERO)
|
|
bValid = false ;
|
|
else {
|
|
if ( dParD > dPar1) {
|
|
dPar1 = dParD ;
|
|
vtN1 = -vtUD ;
|
|
}
|
|
if ( dParU < dPar2) {
|
|
dPar2 = dParU ;
|
|
vtN2 = vtUD ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// altrimenti praticamente parallelo
|
|
else {
|
|
// se esterno ad almeno uno invalida tutto
|
|
if ( dDistU > 0 || dDistD > 0)
|
|
bValid = false ;
|
|
// altrimenti non cambia niente
|
|
}
|
|
}
|
|
|
|
// Taglio con la faccia sinistra
|
|
if ( bValid) {
|
|
// Distanza con segno del punto di riferimento del dexel dal piano della faccia sinistra
|
|
double dDistS = ( ptPoly - ptFacet135) * vtNs ;
|
|
// Se dexel non parallelo alla faccia
|
|
if ( abs( vtPoly * vtNs) > COS_ORTO_ANG_ZERO) {
|
|
// posizione parametrica della intersezione
|
|
double dParS = -dDistS / ( vtPoly * vtNs) ;
|
|
// verifico limitazioni su inizio e fine dell'intervallo
|
|
int nLimit = 0 ;
|
|
// se limita inizio
|
|
if ( vtPoly * vtNs < 0) {
|
|
// se oltre la fine, invalida tutto
|
|
if ( dParS > dPar2 - EPS_ZERO)
|
|
bValid = false ;
|
|
// se altrimenti solo oltre inizio, riduce
|
|
else if ( dParS >= dPar1) {
|
|
dPar1 = dParS ;
|
|
nLimit = 1 ;
|
|
}
|
|
}
|
|
// altrimenti limita fine
|
|
else {
|
|
// se prima dell'inizio, invalida tutto
|
|
if ( dParS < dPar1 + EPS_ZERO)
|
|
bValid = false ;
|
|
// se altrimenti solo prima della fine, riduce
|
|
else if ( dParS <= dPar2) {
|
|
dPar2 = dParS ;
|
|
nLimit = 2 ;
|
|
}
|
|
}
|
|
// se limita, devo aggiornare la normale
|
|
if ( nLimit != 0) {
|
|
Vector3d vtNewN = -vtNs ;
|
|
if ( bRecalNorm) {
|
|
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() ;
|
|
Point3d ptInt = ptPoly + dParS * vtPoly ;
|
|
vtNewN = ( ( dDeltaZ - ptInt.z + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( ptInt.z - dLenZ) / dDeltaZ) * vtOrigMaxR ;
|
|
vtNewN.Normalize() ;
|
|
}
|
|
if ( nLimit == 1)
|
|
vtN1 = vtNewN ;
|
|
else
|
|
vtN2 = vtNewN ;
|
|
}
|
|
}
|
|
// altrimenti praticamente parallelo
|
|
else {
|
|
// se esterno invalida tutto
|
|
if ( dDistS > 0)
|
|
bValid = false ;
|
|
// altrimenti non cambia niente
|
|
}
|
|
}
|
|
|
|
// Taglio con la faccia destra
|
|
if ( bValid) {
|
|
// Distanza con segno del punto di riferimento del dexel dal piano della faccia destra
|
|
double dDistD = ( ptPoly - ptFacet246) * vtNd ;
|
|
// Se dexel non parallelo alla faccia
|
|
if ( abs( vtPoly * vtNd) > COS_ORTO_ANG_ZERO) {
|
|
// posizione parametrica della intersezione
|
|
double dParD = -dDistD / ( vtPoly * vtNd) ;
|
|
// verifico limitazioni su inizio e fine dell'intervallo
|
|
int nLimit = 0 ;
|
|
// se limita inizio
|
|
if ( vtPoly * vtNd < 0) {
|
|
// se oltre la fine, invalida tutto
|
|
if ( dParD > dPar2 - EPS_ZERO)
|
|
bValid = false ;
|
|
// se altrimenti solo oltre inizio, riduce
|
|
else if ( dParD >= dPar1) {
|
|
dPar1 = dParD ;
|
|
nLimit = 1 ;
|
|
}
|
|
}
|
|
// altrimenti limita fine
|
|
else {
|
|
// se prima dell'inizio, invalida tutto
|
|
if ( dParD < dPar1 + EPS_ZERO)
|
|
bValid = false ;
|
|
// se altrimenti solo prima della fine, riduce
|
|
else if ( dParD <= dPar2) {
|
|
dPar2 = dParD ;
|
|
nLimit = 2 ;
|
|
}
|
|
}
|
|
// se limita, devo aggiornare la normale
|
|
if ( nLimit != 0) {
|
|
Vector3d vtNewN = -vtNd ;
|
|
if ( bRecalNorm) {
|
|
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() ;
|
|
Point3d ptInt = ptPoly + dParD * vtPoly ;
|
|
vtNewN = ( ( dDeltaZ - abs( ptInt.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ;
|
|
vtNewN.Normalize() ;
|
|
}
|
|
if ( nLimit == 1)
|
|
vtN1 = vtNewN ;
|
|
else
|
|
vtN2 = vtNewN ;
|
|
}
|
|
}
|
|
// altrimenti praticamente parallelo
|
|
else {
|
|
// se esterno invalida tutto
|
|
if ( dDistD > 0)
|
|
bValid = false ;
|
|
// altrimenti non cambia niente
|
|
}
|
|
}
|
|
|
|
// Se rimasto qualcosa lo sottraggo al dexel
|
|
if ( bValid) {
|
|
// Punti di intersezione e normali nel sistema griglia
|
|
ptInt1 = ptC + dPar1 * Z_AX ;
|
|
vtN1.ToGlob( PolyFrame) ;
|
|
ptInt2 = ptC + dPar2 * Z_AX ;
|
|
vtN2.ToGlob( PolyFrame) ;
|
|
// Eseguo sottrazione
|
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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 ( bRecalNorm) {
|
|
vtN1 = AdjustConeNormal( ptInt1, vtN1, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
vtN2 = AdjustConeNormal( ptInt2, vtN2, ptV, vtToolDir, dMinRad, dDeltaR, vtArcNormMinR, vtArcNormMaxR) ;
|
|
}
|
|
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
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, int nToolNum)
|
|
{
|
|
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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ---------- SFERA ----------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe, double dRad, int nToolNum)
|
|
{
|
|
// Verifico interferisca
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptLs, ptLe, V_NULL, 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
|
|
// 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, nToolNum) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
// ------------------------- Utensili additivi ---------------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx)
|
|
{
|
|
// 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() ;
|
|
|
|
// Utensile sfiancato
|
|
if ( dCornerRad * dCornerRad - 0.25 * dHei * dHei > 0) {
|
|
return AddingGeneral( nGrid, ptS, ptE, vtAx) ;
|
|
}
|
|
// Utensile sferico
|
|
else if ( dRad - dCornerRad < EPS_SMALL) {
|
|
return AddingSphere( nGrid, ptS - dRad * vtAx, ptE - dRad * vtAx, dRad) ;
|
|
}
|
|
// Utensile cilindro
|
|
else if ( dCornerRad < EPS_SMALL) {
|
|
return AddingCylinder( nGrid, ptS, ptE, vtAx, dHei, dRad) ;
|
|
}
|
|
// Utensile naso di toro
|
|
else {
|
|
return AddingGeneral( nGrid, ptS, ptE, vtAx) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddingGeneral( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx)
|
|
{
|
|
// 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* 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) {
|
|
// Se X costante, è un cilindro
|
|
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
|
|
double dRadius = ptStart.x ;
|
|
if (dRadius > 10 * EPS_SMALL)
|
|
AddingCylinder( nGrid, ptI, ptF, vtAx, 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 ;
|
|
AddingTruncatedCone( nGrid, ptI, ptF, vtAx, dMaxRad, dMinRad, dHeight, 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 - vtAx * dHeight ;
|
|
Point3d ptFn = ptIn + vtMove ;
|
|
vtNormEn.z *= -1 ;
|
|
vtNormSt.z *= -1 ;
|
|
AddingTruncatedCone( nGrid, ptIn, ptFn, - vtAx, dMaxRad, dMinRad, dHeight, vtNormEn, vtNormSt) ;
|
|
|
|
}
|
|
// Passo alla curva successiva
|
|
pCurve = ToolProfile.GetCurve( ++ i) ;
|
|
}
|
|
else {
|
|
// Passo alla curva successiva
|
|
pCurve = ToolProfile.GetCurve( ++ i) ;
|
|
}
|
|
}
|
|
|
|
// Determino le posizioni iniziale e finale del componente successivo
|
|
ptI = ptI - vtAx * dHeight ;
|
|
ptF = ptI + vtMove ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Verifica sull'interferenza utensile Zmap
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, V_NULL, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
|
|
return true ;
|
|
|
|
Vector3d vtV1 = ptE - ptS ;
|
|
double dLen1 = vtV1.Len() ;
|
|
vtV1 /= dLen1 ;
|
|
|
|
double dMyTol = 0 ;
|
|
Frame3d CylFrame, PolyFrame ;
|
|
if ( ! CylFrame.Set( ptS - dHei * vtAx, vtAx))
|
|
return false ;
|
|
if ( ! PolyFrame.Set( ptS - ( dHei + dMyTol) * vtAx, vtAx, vtV1))
|
|
return false ;
|
|
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, dHei, dRad, true, true,
|
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
|
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
|
|
ptInt1, vtN1, ptInt2, vtN2)) {
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddingTruncatedCone( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
|
|
double dMaxRad, double dMinRad, double dHei,
|
|
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Verifico interferenza
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, V_NULL, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ))
|
|
return true ;
|
|
|
|
// Geometria del cono
|
|
double dDeltaR = dMaxRad - dMinRad ;
|
|
|
|
// Studio simmetrie
|
|
Point3d ptI = ( vtAx * ( ptE - ptS) > 0 ? ptS : ptE) ;
|
|
Point3d ptF = ( vtAx * ( ptE - ptS) > 0 ? ptE : ptS) ;
|
|
|
|
double dL = ( dMaxRad * dHei) / dDeltaR ;
|
|
double dl = dL - dHei ;
|
|
|
|
Point3d ptV = ptI - vtAx * dL ;
|
|
|
|
// Vettori caratteristici del movimento
|
|
// Elimino eventuali componenti del moto lungo l'asse.
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMvLong = ( vtMove * vtAx) * vtAx ;
|
|
Vector3d vtMvOrt = vtMove - vtMvLong ;
|
|
|
|
// Terna destrorsa e unitaria
|
|
Vector3d vtV1 = vtAx ;
|
|
Vector3d vtV2 = vtMvOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Sistema di riferimento intrinseco del movimento
|
|
Frame3d ConusFrame ;
|
|
if ( ! ConusFrame.Set( ptV, vtV1, vtV2, vtV3))
|
|
return false ;
|
|
|
|
// Dimensioni lineari movimento
|
|
double dLongLen = 0 ;
|
|
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 ;
|
|
if ( ! PolyFrame.Set( ptO, vtV1, vtV2, vtV3))
|
|
return false ;
|
|
|
|
// 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() ;
|
|
|
|
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, true, true, ptInt1, vtN1, ptInt2, vtN2)) {
|
|
vtN1 *= - 1 ;
|
|
vtN2 *= - 1 ;
|
|
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
|
|
if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtAx, 0.1 * EPS_SMALL)) {
|
|
Vector3d vtL1 = ptInt1 - ptV ;
|
|
vtL1 -= ( vtL1 * vtAx) * vtAx ;
|
|
double dL1 = vtL1.Len() ;
|
|
vtL1 /= dL1 ;
|
|
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR;
|
|
vtOriginalN1.Normalize() ;
|
|
vtN1 = vtOriginalN1.z * vtAx + vtOriginalN1.x * vtL1 ;
|
|
vtN1.Normalize() ;
|
|
}
|
|
if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtAx, 0.1 * EPS_SMALL)) {
|
|
Vector3d vtL2 = ptInt2 - ptV ;
|
|
vtL2 -= ( vtL2 * vtAx) * vtAx ;
|
|
double dL2 = vtL2.Len() ;
|
|
vtL2 /= dL2 ;
|
|
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
|
|
vtOriginalN2.Normalize() ;
|
|
vtN2 = vtOriginalN2.z * vtAx + vtOriginalN2.x * vtL2 ;
|
|
vtN2.Normalize() ;
|
|
}
|
|
}
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Cono finale
|
|
ConusFrame.ChangeOrig( ptV + vtMove) ;
|
|
if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, true, true, ptInt1, vtN1, ptInt2, vtN2)) {
|
|
vtN1 *= - 1 ;
|
|
vtN2 *= - 1 ;
|
|
if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) {
|
|
if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtAx, 0.1 * EPS_SMALL)) {
|
|
Vector3d vtL1 = ptInt1 - ptV - vtMove ;
|
|
vtL1 -= ( vtL1 * vtAx) * vtAx ;
|
|
double dL1 = vtL1.Len() ;
|
|
vtL1 /= dL1 ;
|
|
Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
|
|
vtOriginalN1.Normalize() ;
|
|
vtN1 = vtOriginalN1.z * vtAx + vtOriginalN1.x * vtL1 ;
|
|
vtN1.Normalize() ;
|
|
}
|
|
if ( ! AreSameOrOppositeVectorEpsilon(vtN2, vtAx, 0.1 * EPS_SMALL)) {
|
|
Vector3d vtL2 = ptInt2 - ptV - vtMove ;
|
|
vtL2 -= (vtL2 * vtAx) * vtAx;
|
|
double dL2 = vtL2.Len() ;
|
|
vtL2 /= dL2 ;
|
|
Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ;
|
|
vtOriginalN2.Normalize() ;
|
|
vtN2 = vtOriginalN2.z * vtAx + vtOriginalN2.x * vtL2 ;
|
|
vtN2.Normalize() ;
|
|
}
|
|
}
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// 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 + EPS_SMALL) > dLenX * ptPoly1.y &&
|
|
dLenY * ( ptPoly1.x - dDeltaX - EPS_SMALL) < dLenX * ( ptPoly1.y - dDeltaY) &&
|
|
dDeltaX * ( ptPoly1.y + EPS_SMALL) > dDeltaY * ptPoly1.x &&
|
|
dDeltaX * ( ptPoly1.y - dLenY - EPS_SMALL) < 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 + EPS_SMALL) > dLenX * ptPoly2.y &&
|
|
dLenY * ( ptPoly2.x - dDeltaX - EPS_SMALL) < dLenX * ( ptPoly2.y - dDeltaY) &&
|
|
dDeltaX * ( ptPoly2.y + EPS_SMALL) > dDeltaY * ptPoly2.x &&
|
|
dDeltaX * ( ptPoly2.y - dLenY - EPS_SMALL) < 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 > - EPS_SMALL && ptPoly3.x < dDeltaX + EPS_SMALL &&
|
|
dDeltaX * abs( ptPoly3.z) < dDeltaX * dLenZ + dDeltaZ * ptPoly3.x + dDeltaX * EPS_SMALL) {
|
|
|
|
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 - EPS_SMALL && ptPoly4.x < dLenX + dDeltaX + EPS_SMALL &&
|
|
dDeltaX * abs( ptPoly4.z) < dDeltaX * dLenZ + dDeltaZ * ( ptPoly4.x - dLenX) + dDeltaX * EPS_SMALL) {
|
|
|
|
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, aggiungo
|
|
if ( nIntNum == 2) {
|
|
|
|
// Riporto le intersezioni nel sistema griglia
|
|
ptInt1.ToGlob( PolyFrame) ;
|
|
vtN1.ToGlob( PolyFrame) ;
|
|
ptInt2.ToGlob( PolyFrame) ;
|
|
vtN2.ToGlob( PolyFrame) ;
|
|
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad)
|
|
{
|
|
// Controllo utensile
|
|
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size()))
|
|
return false ;
|
|
Tool& CurrTool = m_vTool[m_nCurrTool] ;
|
|
|
|
// Verifico interferisca
|
|
int nStartI, nStartJ, nEndI, nEndJ ;
|
|
if ( ! TestCompoBBox( nGrid, ptS, ptE, V_NULL, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ))
|
|
return true ;
|
|
// Vettore movimento
|
|
Vector3d vtV = ptE - ptS ;
|
|
double dLengthPath = vtV.Len() ;
|
|
if ( dLengthPath > EPS_ZERO)
|
|
vtV /= dLengthPath ;
|
|
// Riferimento per cilindro inviluppo della sfera lungo il movimento
|
|
Frame3d CylFrame ;
|
|
if ( ! CylFrame.Set( ptS, vtV))
|
|
return false ;
|
|
|
|
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, ptS) ;
|
|
if ( dStSqDXY < dSqRad) {
|
|
double dMin = ptS.z - sqrt( dSqRad - dStSqDXY) ;
|
|
Vector3d vtNmin = Point3d( dX, dY, dMin) - ptS ;
|
|
vtNmin.Normalize() ;
|
|
double dMax = ptS.z + sqrt( dSqRad - dStSqDXY) ;
|
|
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptS ;
|
|
vtNmax.Normalize() ;
|
|
AddIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Sfera in posizione end
|
|
double dEnSqDXY = SqDistXY( ptC, ptE) ;
|
|
if ( dEnSqDXY < dSqRad) {
|
|
double dMin = ptE.z - sqrt( dSqRad - dEnSqDXY) ;
|
|
Vector3d vtNmin = Point3d( dX, dY, dMin) - ptE ;
|
|
vtNmin.Normalize() ;
|
|
double dMax = ptE.z + sqrt( dSqRad - dEnSqDXY) ;
|
|
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptE ;
|
|
vtNmax.Normalize() ;
|
|
AddIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, CurrTool.GetToolNum()) ;
|
|
}
|
|
|
|
// Cilindro inviluppo della sfera
|
|
Point3d ptInt1, ptInt2 ;
|
|
Vector3d vtN1, vtN2 ;
|
|
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
|
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|