3bbdfc4a74
- inseriti sviluppi Zmap.
4585 lines
179 KiB
C++
4585 lines
179 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4
|
|
// Contenuto : Implementazione della classe Volume Zmap.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 22.01.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "VolZmap.h"
|
|
#include "GeoObjFactory.h"
|
|
#include "NgeWriter.h"
|
|
#include "NgeReader.h"
|
|
#include "\EgtDev\Include\EGkIntervals.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
VolZmap::VolZmap(void)
|
|
: m_nStatus( TO_VERIFY), m_nTempProp()
|
|
{
|
|
m_dStep = 0 ;
|
|
m_nNx = 0 ;
|
|
m_nNy = 0 ;
|
|
m_nDim = 0 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VolZmap::~VolZmap( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
VolZmap*
|
|
VolZmap::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
VolZmap* pVzm = new(nothrow) VolZmap ;
|
|
if ( pVzm != nullptr) {
|
|
if ( ! pVzm->CopyFrom( *this)) {
|
|
delete pVzm ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
|
|
return pVzm ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CopyFrom( const IGeoObj* pGObjSrc)
|
|
{
|
|
const VolZmap* pVzm = dynamic_cast<const VolZmap*>( pGObjSrc) ;
|
|
if ( pVzm == nullptr)
|
|
return false ;
|
|
return CopyFrom( *pVzm) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CopyFrom( const VolZmap& vzmSrc)
|
|
{
|
|
if ( &vzmSrc == this)
|
|
return true ;
|
|
m_OGrMgr.Reset() ;
|
|
m_LocalFrame = vzmSrc.m_LocalFrame ;
|
|
m_dStep = vzmSrc.m_dStep ;
|
|
m_nDim = vzmSrc.m_nDim ;
|
|
m_nNx = vzmSrc.m_nNx ;
|
|
m_nNy = vzmSrc.m_nNy ;
|
|
m_ZValues = vzmSrc.m_ZValues ;
|
|
m_nStatus = vzmSrc.m_nStatus ;
|
|
m_nTempProp = vzmSrc.m_nTempProp ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
GeoObjType
|
|
VolZmap::GetType( void) const
|
|
{
|
|
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( VolZmap)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
VolZmap::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "Zmap" ;
|
|
return sTitle ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
|
{
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
VolZmap::GetNgeId( void) const
|
|
{
|
|
return GEOOBJ_GETNGEID( VolZmap) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Save( NgeWriter& ngeOut) const
|
|
{
|
|
// parametri di scrittura: sistema di riferimento, minimo incremento, numero di passi
|
|
// in direzione x e y, e per ogni casella, numero di valori e valori
|
|
if ( ! ngeOut.WriteFrame( m_LocalFrame, ";", true))
|
|
return false ;
|
|
if ( ! ngeOut.WriteDouble( m_dStep, ",", false))
|
|
return false ;
|
|
if ( ! ngeOut.WriteInt( m_nNx, ",", false))
|
|
return false ;
|
|
if ( ! ngeOut.WriteInt( m_nNy, ";", true))
|
|
return false ;
|
|
// ciclo sui dexel
|
|
for ( unsigned int i = 0 ; i < m_nDim ; ++ i) {
|
|
// numero di estremi
|
|
int nDim = int( m_ZValues[i].size()) ;
|
|
if ( ! ngeOut.WriteInt( nDim, ",", false))
|
|
return false ;
|
|
// se dexel nullo
|
|
if ( nDim == 0) {
|
|
// scrivo un valore dummy
|
|
if ( ! ngeOut.WriteDouble( 0, ";", true))
|
|
return false ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
for ( unsigned int k = 0 ; k < m_ZValues[i].size() ; ++ k) {
|
|
bool bEndL = ( k == m_ZValues[i].size() - 1) ;
|
|
if ( ! ngeOut.WriteDouble( m_ZValues[i][k], ( bEndL ? ";" : ","), bEndL))
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Load( NgeReader& ngeIn)
|
|
{
|
|
m_nStatus = TO_VERIFY ;
|
|
// parametri di lettura: sistema di riferimento, minimo incremento, numero di passi
|
|
// in direzione x e y, e per ogni casella, numero di valori e valori
|
|
if ( ! ngeIn.ReadFrame( m_LocalFrame, ";", true))
|
|
return false ;
|
|
if ( ! ngeIn.ReadDouble( m_dStep, ",", false))
|
|
return false ;
|
|
int nTemp ;
|
|
if ( ! ngeIn.ReadInt( nTemp, ",", false))
|
|
return false ;
|
|
m_nNx = nTemp ;
|
|
if ( ! ngeIn.ReadInt( nTemp, ";", true))
|
|
return false ;
|
|
m_nNy = nTemp ;
|
|
|
|
// dimensione del vettore di dexel
|
|
m_nDim = m_nNx * m_nNy ;
|
|
m_ZValues.resize(m_nDim) ;
|
|
|
|
// ciclo sui dexel
|
|
for ( unsigned int i = 0 ; i < m_nDim ; ++ i) {
|
|
// leggo il numero di estremi nel dexel
|
|
if ( ! ngeIn.ReadInt( nTemp, ",", false))
|
|
return false ;
|
|
// devono essere pari
|
|
if ( ( nTemp % 2) != 0)
|
|
return false ;
|
|
// se dexel nullo
|
|
if ( nTemp == 0) {
|
|
// leggo un valore dummy
|
|
double dDummy ;
|
|
if ( ! ngeIn.ReadDouble( dDummy, ",", true))
|
|
return false ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// dimensiono l'array
|
|
m_ZValues[i].resize(nTemp) ;
|
|
// leggo i valori
|
|
for ( unsigned int k = 0 ; k < m_ZValues[i].size() ; ++ k) {
|
|
bool bEndL = ( k == m_ZValues[i].size() - 1) ;
|
|
if ( ! ngeIn.ReadDouble( m_ZValues[i][k], ( bEndL ? ";" : ","), bEndL))
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_nStatus = OK ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// reset box
|
|
b3Loc.Reset() ;
|
|
// ciclo sui dexel
|
|
double dY = 0.5 * m_dStep ;
|
|
for ( size_t i = 0 ; i < m_nNy ; ++ i) {
|
|
double dX = 0.5 * m_dStep ;
|
|
for ( size_t j = 0 ; j < m_nNx ; ++ j) {
|
|
size_t nPos = j + i * m_nNx ;
|
|
if ( m_ZValues[nPos].size() > 0) {
|
|
Point3d ptP = m_LocalFrame.Orig() + dX * m_LocalFrame.VersX() + dY * m_LocalFrame.VersY() ;
|
|
b3Loc.Add( ptP + m_ZValues[nPos][0] * m_LocalFrame.VersZ()) ;
|
|
b3Loc.Add( ptP + m_ZValues[nPos][m_ZValues[nPos].size()-1] * m_LocalFrame.VersZ()) ;
|
|
}
|
|
dX += m_dStep ;
|
|
}
|
|
dY += m_dStep ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// reset box
|
|
b3Ref.Reset() ;
|
|
// trasformo il riferimento locale tramite quello passato
|
|
Frame3d frUse = m_LocalFrame ;
|
|
frUse.ToGlob( frRef) ;
|
|
// ciclo sui dexel
|
|
double dY = 0.5 * m_dStep ;
|
|
for ( size_t i = 0 ; i < m_nNy ; ++ i) {
|
|
double dX = 0.5 * m_dStep ;
|
|
for ( size_t j = 0 ; j < m_nNx ; ++ j) {
|
|
size_t nPos = j + i * m_nNx ;
|
|
if ( m_ZValues[nPos].size() > 0) {
|
|
Point3d ptP = frUse.Orig() + dX * frUse.VersX() + dY * frUse.VersY() ;
|
|
b3Ref.Add( ptP + m_ZValues[nPos][0] * frUse.VersZ()) ;
|
|
b3Ref.Add( ptP + m_ZValues[nPos][m_ZValues[nPos].size()-1] * frUse.VersZ()) ;
|
|
}
|
|
dX += m_dStep ;
|
|
}
|
|
dY += m_dStep ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Translate( const Vector3d& vtMove)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// traslo il riferimento
|
|
m_LocalFrame.Translate( vtMove) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// ruoto il riferimento
|
|
return m_LocalFrame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CreateMap( const Point3d& ptO, double dPrec, double dLengthX, double dLengthY, double dLengthZ)
|
|
{
|
|
// Controlli sui parametri
|
|
if ( dPrec < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL)
|
|
return false ;
|
|
|
|
m_LocalFrame.Set( ptO, X_AX, Y_AX, Z_AX) ;
|
|
|
|
m_dStep = dPrec ;
|
|
|
|
m_nNx = static_cast <unsigned int> ( ceil( dLengthX / m_dStep)) ;
|
|
m_nNy = static_cast <unsigned int> ( ceil( dLengthY / m_dStep)) ;
|
|
|
|
m_nDim = m_nNx * m_nNy ;
|
|
|
|
m_ZValues.resize( m_nDim) ;
|
|
|
|
for ( int i = 0 ; i < int( m_nDim) ; i++) {
|
|
m_ZValues[i].resize(2) ;
|
|
|
|
m_ZValues[i][0] = 0 ;
|
|
m_ZValues[i][1] = dLengthZ ;
|
|
}
|
|
|
|
m_dMinZ = 0 ;
|
|
m_dMaxZ = dLengthZ ;
|
|
|
|
m_nStatus = OK ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SubtractIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMax)
|
|
{
|
|
unsigned int nPos ;
|
|
//unsigned int nKD ;
|
|
//unsigned int nKU ;
|
|
//unsigned int nDelta ; // Variazione di dimensione del vettore
|
|
|
|
// Controllo che dMin e dMax non siano quasi coincidenti
|
|
if ( abs( dMax - dMin) < EPS_SMALL)
|
|
|
|
return true ;
|
|
// Controllo che dMin < dMax
|
|
|
|
if ( dMax < dMin ) {
|
|
|
|
double dTemp = dMax ;
|
|
|
|
dMax = dMin ;
|
|
dMin = dTemp ; // cambiato il 3/2
|
|
}
|
|
|
|
// Calcolo nPos
|
|
nPos = nJ*m_nNx + nI ; // O nJ*m_Nx + nI + 1 ?
|
|
|
|
unsigned int i = 0 ;
|
|
|
|
while ( i < m_ZValues[nPos].size() - 1) {
|
|
|
|
if ( m_ZValues[nPos].size() == 0)
|
|
return true ;
|
|
// Casi:
|
|
// Intervallo da sottrarre è tutto a sinistra di quello corrente, non vi è intersezione
|
|
if ( m_ZValues[nPos][i] > dMax - EPS_SMALL) {
|
|
|
|
}
|
|
// Intersezione
|
|
else if ( m_ZValues[nPos][i + 1] > dMax + EPS_SMALL) {
|
|
// L'intervallo corrente corrente viene limitato a sinistra
|
|
if ( m_ZValues[nPos][i] > dMin - EPS_SMALL) {
|
|
|
|
m_ZValues[nPos][i] = dMax ;
|
|
}
|
|
// L'intervallo si divide in due intervalli
|
|
else {
|
|
|
|
m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ;
|
|
|
|
for ( size_t j = m_ZValues[nPos].size() - 1 ; j >= i + 3 ; -- j)
|
|
|
|
m_ZValues[nPos][j] = m_ZValues[nPos][j - 2] ;
|
|
|
|
m_ZValues[nPos][i + 1] = dMin ;
|
|
m_ZValues[nPos][i + 2] = dMax ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
}
|
|
else {
|
|
// L'intervallo corrente viene eliminato
|
|
if ( m_ZValues[nPos][i] > dMin - EPS_SMALL) {
|
|
|
|
for ( unsigned int j = i ; j < m_ZValues[nPos].size() - 2 ; ++ j)
|
|
|
|
m_ZValues[nPos][j] = m_ZValues[nPos][j + 2] ;
|
|
|
|
m_ZValues[nPos].resize( m_ZValues[nPos].size() - 2) ;
|
|
|
|
i = i - 2 ;
|
|
}
|
|
// L'intervallo corrente viene limitato a destra
|
|
else if ( m_ZValues[nPos][i + 1] > dMin + EPS_SMALL) {
|
|
|
|
m_ZValues[nPos][i + 1] = dMin ;
|
|
}
|
|
// L'intervallo da sottrarre è tutto a destra di quello corrente, non vi è intersezione
|
|
else {
|
|
|
|
}
|
|
}
|
|
|
|
i = i + 2 ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SubtractIntervals( const Point3d& ptP, double dMin, double dMax) // ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame)
|
|
{
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( m_LocalFrame) ; // ptPL è ora espresso rispetto al sistema di riferimento intrinseco.
|
|
|
|
double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco
|
|
double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP)
|
|
|
|
dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ;
|
|
dhMin = dZ + dMin ; dhMax = dZ + dMax ;
|
|
|
|
// Cerco il punto della griglia più vicino
|
|
|
|
double integerPartX = floor( dX / m_dStep) ;
|
|
double integerPartY = floor( dY / m_dStep) ;
|
|
|
|
unsigned int i = static_cast <unsigned int> (integerPartX) ; // Indici del punto di griglia più vicino.
|
|
unsigned int j = static_cast <unsigned int> (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1
|
|
|
|
// Controllo se le coordinate x e y del punto dato siano all'interno della griglia:
|
|
// se sono dentro la griglia chiamo l'altra subtract
|
|
if ( dX < m_dStep*m_nNx && dY < m_dStep*m_nNy
|
|
&& dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector e vi è errore runtime
|
|
|
|
return SubtractIntervals( i, j, dhMin, dhMax) ;
|
|
}
|
|
// altrimenti non succede niente
|
|
else {
|
|
|
|
return true ;
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMax)
|
|
{
|
|
unsigned int nPos ;
|
|
//unsigned int nKD ;
|
|
//unsigned int nKU ;
|
|
//unsigned int nDelta ; // Variazione di dimensione del vettore
|
|
|
|
// Controllo che dMin e dMax non siano quasi coincidenti
|
|
if ( abs( dMax - dMin) < EPS_SMALL)
|
|
|
|
return true ;
|
|
|
|
// Controllo che dMin < dMax
|
|
if ( dMax < dMin ) {
|
|
|
|
double dTemp = dMax ;
|
|
|
|
dMax = dMin ;
|
|
dMin = dTemp ; // cambiato il 3/2
|
|
}
|
|
|
|
// Calcolo nPos
|
|
nPos = nJ*m_nNx + nI ; // O nJ*m_Nx + nI + 1 ?
|
|
|
|
if ( m_ZValues[nPos].size() == 0) {
|
|
|
|
m_ZValues[nPos].resize( 2) ;
|
|
|
|
m_ZValues[nPos][0] = dMin ;
|
|
m_ZValues[nPos][1] = dMax ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
unsigned int i = 0 ;
|
|
|
|
while ( i < m_ZValues[nPos].size() - 1) {
|
|
|
|
if ( i > 0) {
|
|
// Caso in cui un intervallo precedente sconfini in quello corrente
|
|
if ( m_ZValues[nPos][i] < m_ZValues[nPos][i - 1] + EPS_SMALL) {
|
|
// Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva
|
|
if ( m_ZValues[nPos][i - 1] < m_ZValues[nPos][i + 1] + EPS_SMALL)
|
|
|
|
m_ZValues[nPos][i - 1] = m_ZValues[nPos][i + 1] ;
|
|
|
|
for ( unsigned int j = i ; j < m_ZValues[nPos].size() - 2 ; ++ j)
|
|
|
|
m_ZValues[nPos][j] = m_ZValues[nPos][j + 2] ;
|
|
|
|
m_ZValues[nPos].resize( m_ZValues[nPos].size() - 2) ;
|
|
|
|
i = i - 2 ;
|
|
}
|
|
}
|
|
|
|
// Caso in cui devo aggiungere un intervallo a sinistra dell'intervallo corrente
|
|
if ( m_ZValues[nPos][i] > dMax + EPS_SMALL) {
|
|
|
|
m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ;
|
|
|
|
for ( size_t j = m_ZValues[nPos].size() - 1 ; j >= i + 2 ; -- j)
|
|
|
|
m_ZValues[nPos][j] = m_ZValues[nPos][j - 2] ;
|
|
|
|
m_ZValues[nPos][i] = dMin ;
|
|
m_ZValues[nPos][i + 1] = dMax ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
// Casi d'intersezione:
|
|
else if ( m_ZValues[nPos][i + 1] > dMax - EPS_SMALL) {
|
|
// Se l'intervallo da aggiungere sconfina a sinistra modifico il minimo dell'intervalo corrente
|
|
if (m_ZValues[nPos][i] > dMin - EPS_SMALL) {
|
|
|
|
m_ZValues[nPos][i] = dMin ;
|
|
}
|
|
}
|
|
else {
|
|
// Se l'intervallo corrente è tutto contenuto nell'intervallo da aggungere modifico gli estremi
|
|
if ( m_ZValues[nPos][i] > dMin + EPS_SMALL) {
|
|
|
|
m_ZValues[nPos][i] = dMin ;
|
|
m_ZValues[nPos][i + 1] = dMax ;
|
|
}
|
|
// Se l'intervallo da aggiungere sconfina a destra modifico il massimo dell'intervallo corrente
|
|
else if ( m_ZValues[nPos][i + 1] > dMin - EPS_SMALL) {
|
|
|
|
m_ZValues[nPos][i + 1] = dMax ;
|
|
}
|
|
else {
|
|
// Aggiungo intervallo a destra dell'ultimo intervallo
|
|
if ( i == m_ZValues[nPos].size() - 2) {
|
|
|
|
m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ;
|
|
|
|
m_ZValues[nPos][i + 2] = dMin ;
|
|
m_ZValues[nPos][i + 3] = dMax ;
|
|
|
|
i = i + 2 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
i = i + 2 ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddIntervals( const Point3d& ptP, double dMin, double dMax) // ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame)
|
|
{
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( m_LocalFrame) ; // ptPL è ora espresso rispetto al sistema di riferimento intrinseco.
|
|
|
|
double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco
|
|
double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP)
|
|
|
|
dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ;
|
|
dhMin = dZ + dMin ; dhMax = dZ + dMax ;
|
|
|
|
// Cerco il punto della griglia più vicino
|
|
|
|
double integerPartX = floor( dX / m_dStep) ;
|
|
double integerPartY = floor( dY / m_dStep) ;
|
|
|
|
unsigned int i = static_cast <unsigned int> (integerPartX) ; // Indici del punto di griglia più vicino.
|
|
unsigned int j = static_cast <unsigned int> (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1
|
|
|
|
// Controllo se le coordinate x e y del punto dato siano all'interno della griglia:
|
|
// se sono dentro la griglia chiamo l'altra subtract
|
|
if ( dX < m_dStep*m_nNx && dY < m_dStep*m_nNy
|
|
&& dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector e vi è errore runtime
|
|
|
|
return AddIntervals( i, j, dhMin, dhMax) ;
|
|
}
|
|
// altrimenti non succede niente
|
|
else {
|
|
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetDexelLines( int nDir, int nPos1, int nPos2, POLYLINELIST& lstPL) const
|
|
{
|
|
// per ora solo perpendicolari a XY (1)
|
|
if ( nDir != 1)
|
|
return false ;
|
|
// verifiche sugli indici
|
|
if ( nPos1 < 0 || nPos1 >= int( m_nNx) || nPos2 < 0 || nPos2 >= int( m_nNy))
|
|
return false ;
|
|
int nPos = nPos1 + nPos2 * m_nNx ;
|
|
if ( nPos < 0 || nPos >= int( m_ZValues.size()))
|
|
return false ;
|
|
// calcolo coordinate punto
|
|
double dX = m_dStep * ( 0.5 + nPos1) ;
|
|
double dY = m_dStep * ( 0.5 + nPos2) ;
|
|
Point3d ptP = m_LocalFrame.Orig() + dX * m_LocalFrame.VersX() + dY * m_LocalFrame.VersY() ;
|
|
// creo le polilinee
|
|
for ( int i = 1 ; i < int( m_ZValues[nPos].size()) ; i += 2) {
|
|
// aggiungo polilinea a lista
|
|
lstPL.emplace_back() ;
|
|
// inserisco punti estremi
|
|
lstPL.back().AddUPoint( 0, ptP + m_ZValues[nPos][i-1] * m_LocalFrame.VersZ()) ;
|
|
lstPL.back().AddUPoint( 1, ptP + m_ZValues[nPos][i] * m_LocalFrame.VersZ()) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetAllTriangles( TRIA3DLIST& lstTria) const
|
|
{
|
|
const int DIM_CHUNK = 4 ;
|
|
for ( int i = 0 ; i < int( m_nNx) ; i += DIM_CHUNK) {
|
|
int nDimChunkX = min( DIM_CHUNK, int( m_nNx) - i) ;
|
|
for ( int j = 0 ; j < int( m_nNy) ; j += DIM_CHUNK) {
|
|
int nDimChunkY = min( DIM_CHUNK, int( m_nNy) - j) ;
|
|
GetChunkPrisms( i, j, nDimChunkX, nDimChunkY, lstTria) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::GetChunkPrisms( int nPos1, int nPos2, int nDim1, int nDim2, TRIA3DLIST& lstTria) const
|
|
{
|
|
// determino se è un semplice parallelepipedo
|
|
bool bIsSimple = true ;
|
|
double dBotZ ;
|
|
double dTopZ ;
|
|
for ( int i = 0 ; i < nDim1 && bIsSimple ; ++ i) {
|
|
for ( int j = 0 ; j < nDim2 && bIsSimple ; ++ j) {
|
|
int nPos = ( nPos1 + i) + ( nPos2 + j) * m_nNx ;
|
|
if ( nPos > int( m_nDim) ||
|
|
int( m_ZValues[nPos].size()) != 2)
|
|
bIsSimple = false ;
|
|
else if ( i == 0 && j == 0) {
|
|
dBotZ = m_ZValues[nPos][0] ;
|
|
dTopZ = m_ZValues[nPos][1] ;
|
|
}
|
|
else if ( abs( m_ZValues[nPos][0] - dBotZ) > EPS_SMALL ||
|
|
abs( m_ZValues[nPos][1] - dTopZ) > EPS_SMALL)
|
|
bIsSimple = false ;
|
|
}
|
|
}
|
|
|
|
// se semplice parallelepipedo
|
|
if ( bIsSimple) {
|
|
CalcChunkPrisms( nPos1, nPos2, nDim1, nDim2, lstTria) ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// elaboro ogni singolo dexel
|
|
for ( int i = 0 ; i < nDim1 ; ++ i) {
|
|
for ( int j = 0 ; j < nDim2 ; ++ j) {
|
|
CalcDexelPrisms( nPos1 + i, nPos2 + j, lstTria) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CalcChunkPrisms( int nPos1, int nPos2, int nDim1, int nDim2, TRIA3DLIST& lstTria) const
|
|
{
|
|
// verifiche sugli indici
|
|
if ( nPos1 < 0 || nPos1 + nDim1 > int( m_nNx) || nPos2 < 0 || nPos2 + nDim2 > int( m_nNy))
|
|
return false ;
|
|
int nPos = nPos1 + nPos2 * m_nNx ;
|
|
if ( nPos < 0 || nPos >= int( m_nDim))
|
|
return false ;
|
|
|
|
// calcolo coordinate punti
|
|
double dX = m_dStep * nPos1 ;
|
|
double dY = m_dStep * nPos2 ;
|
|
Point3d ptP1 = m_LocalFrame.Orig() + dX * m_LocalFrame.VersX() + dY * m_LocalFrame.VersY() ;
|
|
Point3d ptP2 = ptP1 + nDim1 * m_dStep * m_LocalFrame.VersX() ;
|
|
Point3d ptP3 = ptP2 + nDim2 * m_dStep * m_LocalFrame.VersY() ;
|
|
Point3d ptP4 = ptP1 + nDim2 * m_dStep * m_LocalFrame.VersY() ;
|
|
|
|
// creo le facce sopra e sotto
|
|
Vector3d vtDZt = m_ZValues[nPos][1] * m_LocalFrame.VersZ() ;
|
|
Vector3d vtDZb = m_ZValues[nPos][0] * m_LocalFrame.VersZ() ;
|
|
// faccia superiore P1t->P2t->P3t->P4t : sempre visibile
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP1 + vtDZt, ptP2 + vtDZt, ptP3 + vtDZt, m_LocalFrame.VersZ()) ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP3 + vtDZt, ptP4 + vtDZt, ptP1 + vtDZt, m_LocalFrame.VersZ()) ;
|
|
// faccia inferiore P1b->P4b->P3b->P2b : sempre visibile
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP1 + vtDZb, ptP4 + vtDZb, ptP3 + vtDZb, - m_LocalFrame.VersZ()) ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP3 + vtDZb, ptP2 + vtDZb, ptP1 + vtDZb, - m_LocalFrame.VersZ()) ;
|
|
|
|
// creo le facce laterali
|
|
for ( int j = 0 ; j < nDim2 ; ++ j) {
|
|
int nPosD = nPos + nDim1 - 1 + j * m_nNx ;
|
|
int nPosEst = ( nPos1 + nDim1 - 1 < int( m_nNx - 1) ? nPosD + 1 : - 1) ;
|
|
Point3d ptP2D = ptP2 + j * m_dStep * m_LocalFrame.VersY() ;
|
|
Point3d ptP3D = ptP2D + m_dStep * m_LocalFrame.VersY() ;
|
|
AddDexelSideFace( nPosD, nPosEst, ptP2D, ptP3D, m_LocalFrame.VersZ(), m_LocalFrame.VersX(), lstTria) ;
|
|
}
|
|
for ( int i = 0 ; i < nDim1 ; ++ i) {
|
|
int nPosD = nPos + ( nDim2 - 1) * m_nNx + i ;
|
|
int nPosNord = ( nPos2 + nDim2 - 1 < int( m_nNy - 1) ? nPosD + m_nNx : - 1) ;
|
|
Point3d ptP4D = ptP4 + i * m_dStep * m_LocalFrame.VersX() ;
|
|
Point3d ptP3D = ptP4D + m_dStep * m_LocalFrame.VersX() ;
|
|
AddDexelSideFace( nPosD, nPosNord, ptP3D, ptP4D, m_LocalFrame.VersZ(), m_LocalFrame.VersY(), lstTria) ;
|
|
}
|
|
for ( int j = 0 ; j < nDim2 ; ++ j) {
|
|
int nPosD = nPos + j * m_nNx ;
|
|
int nPosWest = ( nPos1 > 0 ? nPosD - 1 : - 1) ;
|
|
Point3d ptP1D = ptP1 + j * m_dStep * m_LocalFrame.VersY() ;
|
|
Point3d ptP4D = ptP1D + m_dStep * m_LocalFrame.VersY() ;
|
|
AddDexelSideFace( nPosD, nPosWest, ptP4D, ptP1D, m_LocalFrame.VersZ(), - m_LocalFrame.VersX(), lstTria) ;
|
|
}
|
|
for ( int i = 0 ; i < nDim1 ; ++ i) {
|
|
int nPosD = nPos + i ;
|
|
int nPosSud = ( nPos2 > 0 ? nPosD - m_nNx : - 1) ;
|
|
Point3d ptP1D = ptP1 + i * m_dStep * m_LocalFrame.VersX() ;
|
|
Point3d ptP2D = ptP1D + m_dStep * m_LocalFrame.VersX() ;
|
|
AddDexelSideFace( nPosD, nPosSud, ptP1D, ptP2D, m_LocalFrame.VersZ(), - m_LocalFrame.VersY(), lstTria) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::CalcDexelPrisms( int nPos1, int nPos2, TRIA3DLIST& lstTria) const
|
|
{
|
|
// verifiche sugli indici
|
|
if ( nPos1 < 0 || nPos1 >= int( m_nNx) || nPos2 < 0 || nPos2 >= int( m_nNy))
|
|
return false ;
|
|
int nPos = nPos1 + nPos2 * m_nNx ;
|
|
if ( nPos < 0 || nPos >= int( m_nDim))
|
|
return false ;
|
|
|
|
// calcolo coordinate punto
|
|
double dX = m_dStep * nPos1 ;
|
|
double dY = m_dStep * nPos2 ;
|
|
Point3d ptP1 = m_LocalFrame.Orig() + dX * m_LocalFrame.VersX() + dY * m_LocalFrame.VersY() ;
|
|
Point3d ptP2 = ptP1 + m_dStep * m_LocalFrame.VersX() ;
|
|
Point3d ptP3 = ptP2 + m_dStep * m_LocalFrame.VersY() ;
|
|
Point3d ptP4 = ptP1 + m_dStep * m_LocalFrame.VersY() ;
|
|
|
|
// creo le facce sopra e sotto di ogni intervallo (sempre visibili)
|
|
for ( int i = 1 ; i < int( m_ZValues[nPos].size()) ; i += 2) {
|
|
Vector3d vtDZt = m_ZValues[nPos][i] * m_LocalFrame.VersZ() ;
|
|
Vector3d vtDZb = m_ZValues[nPos][i-1] * m_LocalFrame.VersZ() ;
|
|
// faccia superiore P1t->P2t->P3t->P4t : sempre visibile
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP1 + vtDZt, ptP2 + vtDZt, ptP3 + vtDZt, m_LocalFrame.VersZ()) ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP3 + vtDZt, ptP4 + vtDZt, ptP1 + vtDZt, m_LocalFrame.VersZ()) ;
|
|
// faccia inferiore P1b->P4b->P3b->P2b : sempre visibile
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP1 + vtDZb, ptP4 + vtDZb, ptP3 + vtDZb, - m_LocalFrame.VersZ()) ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP3 + vtDZb, ptP2 + vtDZb, ptP1 + vtDZb, - m_LocalFrame.VersZ()) ;
|
|
}
|
|
|
|
// creo le facce laterali
|
|
int nPosEst = ( nPos1 < int( m_nNx - 1) ? nPos + 1 : - 1) ;
|
|
AddDexelSideFace( nPos, nPosEst, ptP2, ptP3, m_LocalFrame.VersZ(), m_LocalFrame.VersX(), lstTria) ;
|
|
int nPosNord = ( nPos2 < int( m_nNy - 1) ? nPos + m_nNx : - 1) ;
|
|
AddDexelSideFace( nPos, nPosNord, ptP3, ptP4, m_LocalFrame.VersZ(), m_LocalFrame.VersY(), lstTria) ;
|
|
int nPosWest = ( nPos1 > 0 ? nPos - 1 : - 1) ;
|
|
AddDexelSideFace( nPos, nPosWest, ptP4, ptP1, m_LocalFrame.VersZ(), - m_LocalFrame.VersX(), lstTria) ;
|
|
int nPosSud = ( nPos2 > 0 ? nPos - m_nNx : - 1) ;
|
|
AddDexelSideFace( nPos, nPosSud, ptP1, ptP2, m_LocalFrame.VersZ(), - m_LocalFrame.VersY(), lstTria) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::AddDexelSideFace( int nPos, int nPosAdj, const Point3d& ptP, const Point3d& ptQ,
|
|
const Vector3d& vtZ, const Vector3d& vtNorm, TRIA3DLIST& lstTria) const
|
|
{
|
|
Intervals intFace ;
|
|
for ( int i = 1 ; i < int( m_ZValues[nPos].size()) ; i += 2)
|
|
intFace.Add( m_ZValues[nPos][i-1], m_ZValues[nPos][i]) ;
|
|
if ( nPosAdj > 0) {
|
|
for ( int i = 1 ; i < int( m_ZValues[nPosAdj].size()) ; i += 2)
|
|
intFace.Subtract( m_ZValues[nPosAdj][i-1], m_ZValues[nPosAdj][i]) ;
|
|
}
|
|
double dMin, dMax ;
|
|
bool bFound = intFace.GetFirst( dMin, dMax) ;
|
|
while ( bFound) {
|
|
Vector3d vtDZt = dMax * vtZ ;
|
|
Vector3d vtDZb = dMin * vtZ ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptP + vtDZb, ptQ + vtDZb, ptQ + vtDZt, vtNorm) ;
|
|
lstTria.emplace_back() ;
|
|
lstTria.back().Set( ptQ + vtDZt, ptP + vtDZt, ptP + vtDZb, vtNorm) ;
|
|
bFound = intFace.GetNext( dMin, dMax) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SetTool( const string& pToolName, const CurveComposite* pToolOutline)
|
|
{
|
|
m_sToolName = pToolName ;
|
|
|
|
m_nToolType = GenericTool ;
|
|
|
|
m_ToolOutline.CopyFrom( pToolOutline) ;
|
|
|
|
// Dimensioni dell'utensile
|
|
BBox3d Bounding ;
|
|
m_ToolOutline.GetLocalBBox( Bounding) ;
|
|
double m_dHeight = Bounding.GetMax().y - Bounding.GetMin().y ;
|
|
double m_dRadius = Bounding.GetMax().x - Bounding.GetMin().x ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::SetStdTool( const string& pToolName, unsigned int nToolType, double dH, double dTH, double dR, double dTR, double dRc)
|
|
{
|
|
// Controllo sull'ammissibilità del tipo di utensile
|
|
if ( nToolType == GenericTool || nToolType > 4)
|
|
|
|
return false ;
|
|
else {
|
|
// Controllo sull'ammissibilità dei parametri geometrici dell'utensile
|
|
if ( dH < EPS_SMALL || dR < EPS_SMALL)
|
|
|
|
return false ;
|
|
|
|
m_sToolName = pToolName ;
|
|
m_nToolType = nToolType ;
|
|
|
|
m_dRadius = dR ;
|
|
m_dHeight = dH ;
|
|
|
|
if ( nToolType == CylindricalMill) {
|
|
|
|
m_dTipHeight = 0 ;
|
|
m_dTipRadius = m_dRadius ;
|
|
}
|
|
else if ( nToolType == BallEndMill) {
|
|
|
|
m_dTipHeight = m_dRadius ;
|
|
m_dTipRadius = 0 ;
|
|
}
|
|
else if ( nToolType == BullNoseMill) {
|
|
|
|
if ( dR < dRc)
|
|
|
|
return false ;
|
|
|
|
m_dRCorner = dRc ;
|
|
m_dTipHeight = dRc ;
|
|
m_dTipRadius = dR - dRc ;
|
|
|
|
if ( dRc < EPS_SMALL) {
|
|
|
|
m_dRCorner = 0 ;
|
|
m_nToolType = CylindricalMill ;
|
|
}
|
|
|
|
if ( dRc > dR - EPS_SMALL) {
|
|
|
|
m_dRCorner = m_dRadius ;
|
|
m_nToolType = BallEndMill ;
|
|
}
|
|
}
|
|
else if ( nToolType == ConusMill) {
|
|
|
|
if ( dTH < 0 || dTR < 0)
|
|
|
|
return false ;
|
|
|
|
if ( abs( dR - dTR) < EPS_SMALL) {
|
|
|
|
m_nToolType = CylindricalMill ;
|
|
|
|
m_dTipHeight = 0 ;
|
|
m_dTipRadius = m_dRadius ;
|
|
}
|
|
else {
|
|
|
|
m_dTipHeight = dTH ;
|
|
m_dTipRadius = dTR ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingStep( const Point3d& ptPs, const Point3d& ptPe, Vector3d& vtDs, Vector3d& vtDe)
|
|
{
|
|
|
|
// Porto i dati del movimento nel riferimento intrinseco
|
|
Point3d ptLs = ptPs ;
|
|
ptLs.ToLoc( m_LocalFrame) ;
|
|
Point3d ptLe = ptPe ;
|
|
ptLe.ToLoc( m_LocalFrame) ;
|
|
Vector3d vtLs = vtDs ;
|
|
vtLs.ToLoc( m_LocalFrame) ;
|
|
Vector3d vtLe = vtDe ;
|
|
vtLe.ToLoc( m_LocalFrame) ;
|
|
|
|
if ( AreSamePointApprox( ptLs, ptLe) && AreSameVectorApprox( vtLs, vtLe))
|
|
return true ;
|
|
|
|
// Normalizzo i vettori
|
|
vtLs.Normalize() ;
|
|
vtLe.Normalize() ;
|
|
|
|
// Direzione utensile costante
|
|
if ( AreSameVectorApprox( vtLs, vtLe)) {
|
|
// Versori della direzione utensile paralleli/ antiparalleli a Z
|
|
if ( vtLs.IsZplus() || vtLs.IsZminus()) {
|
|
// Movimento diretto come direzione utensile
|
|
if ( AreSamePointXYApprox( ptLs, ptLe))
|
|
return MillingDrillZ( ptLs, ptLe, vtLs) ;
|
|
// Movimento perpendicolare a direzione utensile
|
|
else if ( abs( ptLe.z - ptLs.z) < EPS_SMALL)
|
|
return MillingPerpZ( ptLs, ptLe, vtLs) ;
|
|
// Movimento generico
|
|
else
|
|
return MillingZ( ptLs, ptLe, vtLs) ;
|
|
}
|
|
// Versori della direzione utensile perpendicolari all'asse Z
|
|
else if ( abs(vtLs * Z_AX) < EPS_SMALL) {
|
|
// Movimento con Z costante (con vettore movimento parallelo od ortogonale al versore dell'utensile)
|
|
if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) {
|
|
// Movimento parallelo alla direzione dell'utensile (foratura)
|
|
Vector3d vtTest = ptLe - ptLs ; vtTest.Normalize() ;
|
|
if ( abs( ( vtTest * vtLs) - 1) < EPS_SMALL)
|
|
return MillingDrillXY( ptLs, ptLe, vtLs) ;
|
|
// Movimento perpendicolare alla direzione dell'utensile
|
|
else if ( abs( (ptLe - ptLs) * vtLs) < EPS_SMALL)
|
|
return MillingPerpXY( ptLs, ptLe, vtLs) ;
|
|
// Movimento nel piano generico
|
|
else
|
|
return MillingXYPlaneGen( ptLs, ptLe, vtLs) ;
|
|
}
|
|
// Movimento con Z non costante
|
|
else {
|
|
// Grandezze geometriche per selezione
|
|
Vector3d vtMove = ptLe - ptLs ;
|
|
Vector3d vtTest = vtMove - ( vtMove * vtLs) * vtLs ;
|
|
|
|
if ( abs( vtTest * X_AX) < EPS_SMALL && abs( vtTest * Y_AX) < EPS_SMALL)
|
|
return MillingXYLongVert( ptLs, ptLe, vtLs) ;
|
|
else {
|
|
if ( abs( vtMove * vtLs) < EPS_SMALL) {
|
|
if ( m_nToolType == 1)
|
|
return MillingXYCyl( ptLs, ptLe, vtLs) ;
|
|
else if ( m_nToolType == 2)
|
|
return MillingXYBall( ptLs, ptLe, vtLs) ;
|
|
}
|
|
else {
|
|
if ( m_nToolType ==1)
|
|
return MillingXYPlusCyl( ptLs, ptLe, vtLs) ;
|
|
else if ( m_nToolType == 2)
|
|
return MillingXYPlusBall( ptLs, ptLe, vtLs) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Altri casi, non gestiti
|
|
return false ;
|
|
}
|
|
|
|
// Frese: cylindrical, ball-end e bull-nose //////////////////////////////////
|
|
// Versore utensile parallelo all'asse Z
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingDrillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir)
|
|
{
|
|
if ( m_nToolType == 4)
|
|
return ConusDrillingZ( ptLs, ptLe, vtToolDir) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ;
|
|
|
|
// Verifico interferisca con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determino i limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Determino quote estreme del tagliente
|
|
double dMax = ptLs.z - m_dHeight ; // Volendo si può effettuare un controllo su quota punto finale e iniziale,
|
|
double dMin = ptLe.z - m_dHeight ; // ma non è necessaria dal momento che Subtract intervals scambia min con max se max < min
|
|
double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale
|
|
double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente
|
|
|
|
// Limite sul quadrato del raggio
|
|
double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ;
|
|
|
|
// Ciclo sui punti nei limiti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
// punto
|
|
Point3d ptQ( dX, dY, 0) ;
|
|
// determino il quadrato della distanza
|
|
double dSqDist = SqDistXY( ptQ, ptLe) ;
|
|
// se distanza nei limiti, taglio
|
|
if ( dSqDist < dSqRad)
|
|
GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingPerpZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir)
|
|
{
|
|
if ( m_nToolType == 4)
|
|
return ConusPerpZ( ptLs, ptLe, vtToolDir) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ;
|
|
|
|
// Verifico interferisca con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determino i limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Determino quote estreme del tagliente
|
|
double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale
|
|
double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente
|
|
|
|
// Limite sul quadrato del raggio
|
|
double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ;
|
|
|
|
// Segmento di movimento (nel piano griglia)
|
|
Point3d ptStart( ptLs.x, ptLs.y, 0) ;
|
|
Point3d ptEnd( ptLe.x, ptLe.y, 0) ;
|
|
double dLen ;
|
|
Vector3d vtDir ;
|
|
DirDist( ptStart, ptEnd, vtDir, dLen) ;
|
|
|
|
// Ciclo sui punti nei limiti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
// punto
|
|
Point3d ptQ( dX, dY, 0) ;
|
|
// determino il quadrato della distanza del punto dal segmento
|
|
double dProiez = vtDir * ( ptQ - ptStart) ;
|
|
if ( dProiez < 0)
|
|
dProiez = 0 ;
|
|
else if ( dProiez > dLen)
|
|
dProiez = dLen ;
|
|
Point3d ptMinDist = ptStart + vtDir * dProiez ;
|
|
double dSqDist = SqDistXY( ptQ, ptMinDist) ;
|
|
// se distanza nei limiti, taglio
|
|
if ( dSqDist < dSqRad)
|
|
GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
if ( m_nToolType == 4)
|
|
if ( m_dRadius > m_dTipRadius)
|
|
return ConusMillingZDr( ptLs, ptLe, vtToolDir) ;
|
|
else
|
|
return ConusMillingZSw( ptLs, ptLe, vtToolDir) ;
|
|
|
|
// Setto il fattore per l'orientazione in z
|
|
double dFactor = ( vtToolDir.z < 0 ? 1 : - 1) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ;
|
|
double dMinZ = min( min( ptLs.z, ptLs.z + dFactor * m_dHeight), min( ptLe.z, ptLe.z + dFactor * m_dHeight)) ;
|
|
double dMaxZ = max( max( ptLs.z, ptLs.z + dFactor * m_dHeight), max( ptLe.z, ptLe.z + dFactor * m_dHeight)) ;
|
|
|
|
// Verifico interferisca con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determino i limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
//
|
|
double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale
|
|
double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente
|
|
|
|
// Limite sul quadrato del raggio
|
|
double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ;
|
|
|
|
// Segmento di movimento (nel piano griglia)
|
|
Point3d ptStart( ptLs.x, ptLs.y, 0) ;
|
|
Point3d ptEnd( ptLe.x, ptLe.y, 0) ;
|
|
double dLen ;
|
|
Vector3d vtDir ;
|
|
DirDist( ptStart, ptEnd, vtDir, dLen) ;
|
|
|
|
// Ciclo sui punti nei limiti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) {
|
|
double dX = ( i + 0.5) * m_dStep ;
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
double dY = ( j + 0.5) * m_dStep ;
|
|
// punto
|
|
Point3d ptQ( dX, dY, 0) ;
|
|
// determino il quadrato della distanza del punto dal segmento
|
|
double dProj = vtDir * ( ptQ - ptStart) ;
|
|
double dProiez ;
|
|
|
|
if ( dProj < 0)
|
|
dProiez = 0 ;
|
|
else if ( dProj < dLen)
|
|
dProiez = dProj ;
|
|
else
|
|
dProiez = dLen ;
|
|
|
|
Point3d ptMinDist = ptStart + vtDir * dProiez ;
|
|
double dSqDist = SqDistXY( ptQ, ptMinDist) ;
|
|
|
|
// se distanza nei limiti, taglio
|
|
if ( dSqDist < dSqRad)
|
|
GetMinMaxZGen( i, j, dProj, dSqDist, dLen, dZCutBase, dDeltaZ, vtToolDir) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxZ( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) {
|
|
|
|
// Definisco variabili
|
|
double dSqRad = m_dRadius * m_dRadius ;
|
|
double dFactor = ( vtToolDir.z < 0 ? - 1 : 1) ;
|
|
double dZtip = ( vtToolDir.z < 0 ? dZCutBase + m_dHeight : dZCutBase - m_dHeight) ;
|
|
|
|
double dMin ; double dMax ;
|
|
|
|
// Caso utensile generico al momento non gestito
|
|
if ( m_nToolType == 0)
|
|
|
|
return false;
|
|
// Caso Cylindrical Mill
|
|
else if ( m_nToolType == 1) {
|
|
|
|
if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) { // Non è meglio fare if (vt * delta < - Eps_small ) else if ( vt * delta < Eps) else ?
|
|
dMin = min(dZCutBase, dZtip) ;
|
|
dMax = max(dZCutBase, dZtip) ;
|
|
}
|
|
else if ( vtToolDir.z * dDeltaZ < 0) {
|
|
dMin = min(dZtip, dZtip + dDeltaZ) ;
|
|
dMax = max(dZtip, dZtip + dDeltaZ) ;
|
|
}
|
|
else {
|
|
dMin = min(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
dMax = max(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
}
|
|
return SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
// Caso Ball-End Mill
|
|
else if ( m_nToolType == 2) {
|
|
|
|
if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) {
|
|
dMin = min(dZCutBase, dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist))) ;
|
|
dMax = max(dZCutBase, dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist))) ;
|
|
}
|
|
else if ( vtToolDir.z * dDeltaZ < 0) {
|
|
dMin = min(dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)), dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)) + dDeltaZ) ;// ocio
|
|
dMax = max(dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)), dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)) + dDeltaZ) ;// ocio
|
|
}
|
|
else {
|
|
dMin = min(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
dMax = max(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
}
|
|
return SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
// Caso Bull-Nose Mill
|
|
else if ( m_nToolType == 3) {
|
|
|
|
double dDeltaR = m_dRadius - m_dRCorner ;
|
|
|
|
if ( dSqDist < dDeltaR*dDeltaR) {
|
|
|
|
if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) {
|
|
dMin = min(dZCutBase, dZtip) ;
|
|
dMax = max(dZCutBase, dZtip) ;
|
|
}
|
|
else if ( vtToolDir.z * dDeltaZ < 0) {
|
|
dMin = min(dZtip, dZtip + dDeltaZ) ;
|
|
dMax = max(dZtip, dZtip + dDeltaZ) ;
|
|
}
|
|
else {
|
|
dMin = min(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
dMax = max(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
}
|
|
return SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
else {
|
|
|
|
double dSqRadC = m_dRCorner*m_dRCorner ;
|
|
double dSqd = dSqDist + dDeltaR*dDeltaR - 2*sqrt(dSqDist)*dDeltaR ;
|
|
|
|
if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) {
|
|
dMin = min(dZCutBase, dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd))) ;
|
|
dMax = max(dZCutBase, dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd))) ;
|
|
}
|
|
else if ( vtToolDir.z * dDeltaZ < 0) {
|
|
dMin = min(dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)), dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)) + dDeltaZ) ;
|
|
dMax = max(dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)), dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)) + dDeltaZ) ;
|
|
}
|
|
else {
|
|
dMin = min(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
dMax = max(dZCutBase, dZCutBase + dDeltaZ) ;
|
|
}
|
|
return SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
}
|
|
// Caso di utensile inesistente ( m_nToolType fuori dai valori concessi)
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxZGen( unsigned int nI, unsigned int nJ, double dProj, double dSqd, double dLenPath, double dZheight, double dDelta, const Vector3d& vtToolDir) {
|
|
|
|
// Controllo sul tipo di utensile: se 0 utensile generico (al momento non gestito) se maggiore di 3 utensile fuori dai tipi consentiti
|
|
if ( m_nToolType == 0 || m_nToolType > 3)
|
|
return false ;
|
|
|
|
// Definisco variabili quota della punta, minimo e massimo dell'intervallo da sottrarre
|
|
double dZTip = ( vtToolDir.z < 0 ? dZheight + m_dHeight : dZheight - m_dHeight) ;
|
|
double dMin, dMax ; double dStart ; // dStart è un parametro che esprime l'ascissa in cui la retta congiungente le due posizioni iniziale e finale
|
|
double dRSqDist1, dRSqDist2 ; // di un punto del tagliente (nel sistema dell'asse dell'utensile nella posizione iniziale) assume la quota dZheight
|
|
|
|
// Nei conti è comodo che dSqd assuma sempre il significato di distanza del punto dall'asse del movimento al quadrato
|
|
if ( dProj < 0)
|
|
dSqd = dSqd - dProj * dProj ;
|
|
else if ( dProj > dLenPath)
|
|
dSqd = dSqd - ( dProj - dLenPath) * ( dProj - dLenPath) ;
|
|
|
|
// Caso di cylindrical mill
|
|
if ( m_nToolType == 1) {
|
|
|
|
double dZ1, dZ2 ;
|
|
// Se lavora la punta
|
|
if ( vtToolDir.z * dDelta < 0) {
|
|
dZ1 = dZTip ;
|
|
dZ2 = dZheight ;
|
|
}
|
|
// Se lavora il fondo
|
|
else {
|
|
dZ1 = dZheight ;
|
|
dZ2 = dZTip ;
|
|
}
|
|
|
|
dStart = sqrt( m_dRadius * m_dRadius - dSqd) ;
|
|
dRSqDist1 = dProj * dProj + dSqd ;
|
|
dRSqDist2 = ( dLenPath - dProj) * ( dLenPath - dProj) + dSqd ;
|
|
|
|
if ( dRSqDist1 < (m_dRadius + EPS_SMALL) * (m_dRadius + EPS_SMALL)) {
|
|
|
|
dMin = min( max( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ1 + dDelta), dZ2) ;
|
|
dMax = max( min( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ1 + dDelta), dZ2) ;
|
|
}
|
|
else if ( dRSqDist2 < (m_dRadius + EPS_SMALL) * (m_dRadius + EPS_SMALL)) {
|
|
|
|
dMin = min( min(dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath, dZ2 + dDelta), dZ1 + dDelta) ;
|
|
dMax = max( max(dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath, dZ2 + dDelta), dZ1 + dDelta) ;
|
|
}
|
|
else {
|
|
|
|
dMin = min( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath) ;
|
|
dMax = max( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath) ;
|
|
}
|
|
}
|
|
// Caso di ball-end mill
|
|
else if ( m_nToolType == 2) {
|
|
|
|
if ( dDelta < 0) {
|
|
|
|
dDelta = - dDelta ;
|
|
dProj = dLenPath - dProj ;
|
|
dZheight = dZheight - dDelta ;
|
|
dZTip = dZTip - dDelta ;
|
|
}
|
|
|
|
dStart = sqrt( m_dRadius * m_dRadius - dSqd) ;
|
|
dRSqDist1 = dProj * dProj + dSqd ;
|
|
dRSqDist2 = ( dLenPath - dProj) * ( dLenPath - dProj) + dSqd ;
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
|
|
// Semi-asse ellisse
|
|
double dSemiAxMin = m_dRadius * sqrt( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ;
|
|
double dSqrSemiAxMin = m_dRadius * m_dRadius * ( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ;
|
|
double dXD2 = ( dProj - dLenPath) * ( dProj - dLenPath) ;
|
|
|
|
if ( dRSqDist2 < m_dRadius * m_dRadius) {
|
|
|
|
dMax = dZheight + dDelta ;
|
|
|
|
double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ;
|
|
|
|
if ( dProj - dLenPath > dSemiAxMin * dTest) {
|
|
|
|
double dSqrRad = ( dProj - dLenPath) * ( dProj - dLenPath) + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
dMin = dZTip + m_dRadius + dDelta - dH ;
|
|
}
|
|
else if ( dProj > dSemiAxMin * dTest) {
|
|
// Determino l'altezza del punto sull'ellisse da cui passa la retta
|
|
double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dLenPath + dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : dLenPath) ;
|
|
double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ;
|
|
double dZ0 = ( ( dPr0 - dLenPath) * dPar) / dSemiAxMin ;
|
|
|
|
dMin = dZTip + dDelta + m_dRadius - dZ0 + ( dDelta / dLenPath) * ( dProj - dPr0) ;
|
|
}
|
|
else {
|
|
|
|
double dSqrRad = dProj * dProj + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
dMin = dZTip + m_dRadius - dH ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
dMax = dZheight + ( dDelta * ( dProj + dStart)) / dLenPath ;
|
|
|
|
double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ;
|
|
|
|
if ( dProj > dSemiAxMin * dTest) {
|
|
// Determino l'altezza del punto sull'ellisse da cui passa la retta
|
|
double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dLenPath + dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : dLenPath) ;
|
|
double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ;
|
|
double dZ0 = ( ( dPr0 - dLenPath) * dPar) / dSemiAxMin ;
|
|
|
|
dMin = dZTip + dDelta + m_dRadius - dZ0 + ( dDelta / dLenPath) * ( dProj - dPr0) ;
|
|
}
|
|
else {
|
|
|
|
double dSqrRad = dProj * dProj + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
|
|
dMin = dZTip + m_dRadius - dH ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
// Semi-asse ellisse
|
|
double dSemiAxMin = m_dRadius * sqrt( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ;
|
|
double dSqrSemiAxMin = m_dRadius * m_dRadius * ( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ;
|
|
double dXD2 = ( dProj - dLenPath) * ( dProj - dLenPath) ;
|
|
|
|
if ( dRSqDist1 < m_dRadius * m_dRadius) {
|
|
|
|
dMin = dZheight ;
|
|
|
|
double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ;
|
|
|
|
if ( dProj < - dSemiAxMin * dTest) {
|
|
|
|
double dSqrRad = dProj * dProj + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
|
|
dMax = dZTip - m_dRadius + dH ;
|
|
}
|
|
else if ( dProj - dLenPath < - dSemiAxMin * dTest) {
|
|
// Determino l'altezza del punto sull'ellisse da cui passa la retta
|
|
double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : 0) ;
|
|
double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ;
|
|
double dZ0 = ( dPr0 * dPar) / dSemiAxMin ;
|
|
|
|
dMax = dZTip - m_dRadius + dZ0 + ( dDelta / dLenPath) * ( dProj + dPr0) ;
|
|
}
|
|
else {
|
|
|
|
double dSqrRad = dProj * dProj + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
dMax = dZTip - m_dRadius + dDelta + dH ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
dMin = dZheight + ( dDelta * ( dProj - dStart)) / dLenPath ;
|
|
|
|
double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ;
|
|
|
|
if ( dProj - dLenPath < - dSemiAxMin * dTest) {
|
|
// Determino l'altezza del punto sull'ellisse da cui passa la retta
|
|
double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : 0) ;
|
|
double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ;
|
|
double dZ0 = ( dPr0 * dPar) / dSemiAxMin ;
|
|
|
|
dMax = dZTip - m_dRadius + dZ0 + ( dDelta / dLenPath) * ( dProj + dPr0) ;
|
|
}
|
|
else {
|
|
|
|
double dSqrRad = ( dProj - dLenPath) * ( dProj - dLenPath) + dSqd ;
|
|
double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ;
|
|
dMax = dZTip + dDelta - m_dRadius + dH ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Caso di bull-nose mill
|
|
else
|
|
return true ;
|
|
|
|
return SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
|
|
// Versore utensile nel piano XY
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingDrillXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
// Punti per la determinazione del materiale asportato
|
|
Vector3d vtMove = ptLe - ptLs ;
|
|
// Punti di riferimento dell'asportazione
|
|
Point3d ptLNs ;
|
|
Point3d ptLNe ;
|
|
// Parametro relativo all'utensile altezza della parte non cilindrica e fattore determinante
|
|
// la lunghezza della parte lavorata a seconda che lavori la punta o il fondo
|
|
double dCylH ; double dFactor ;
|
|
|
|
// Caso utensile generico (al momento non gestito)
|
|
if ( m_nToolType == 0)
|
|
return false ;
|
|
// Caso Cylindrical Mill
|
|
else if ( m_nToolType == 1)
|
|
dCylH = m_dHeight ;
|
|
// Caso Ball-end Mill
|
|
else if ( m_nToolType == 2)
|
|
dCylH = m_dHeight - m_dRadius ;
|
|
// Caso Bull-nose Mill
|
|
else if ( m_nToolType == 3)
|
|
dCylH = m_dHeight - m_dRCorner ;
|
|
|
|
// Normalizzo tale vettore e ne determino la lunghezza:
|
|
double dLenPath = vtMove.Len() ; vtMove.Normalize() ;
|
|
|
|
// Prodotto scalare fra versore direzione utensile e direzione movimento
|
|
double dScProd = vtMove * vtToolDir ;
|
|
// Se lavora la punta
|
|
if ( dScProd < 0) {
|
|
// Trovo i punti di riferimento per la lavorazione
|
|
ptLNs = ptLs + ( vtMove * dCylH) ;
|
|
ptLNe = ptLe + ( vtMove * dCylH) ;
|
|
dFactor = 1 ;
|
|
}
|
|
// Se lavora il fondo
|
|
else {
|
|
ptLNs = ptLs ;
|
|
ptLNe = ptLe ;
|
|
dFactor = 0 ;
|
|
}
|
|
|
|
// Quota z dei punti iniziale e finale
|
|
double dHz = ptLNs.z ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLNs.x, ptLNe.x) - m_dRadius ;
|
|
double dMaxX = max( ptLNs.x, ptLNe.x) + m_dRadius ;
|
|
double dMinY = min( ptLNs.y, ptLNe.y) - m_dRadius ;
|
|
double dMaxY = max( ptLNs.y, ptLNe.y) + m_dRadius ;
|
|
double dMinZ = dHz - m_dRadius ;
|
|
double dMaxZ = dHz + m_dRadius ;
|
|
|
|
// Verifico se il movimento intersca lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determino i limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
//Proietto ptLNs sul piano XY:
|
|
Point3d ptStart( ptLNs.x, ptLNs.y, 0) ;
|
|
|
|
//Ciclo sui punti
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
// Punto da valutare
|
|
Point3d ptC( (i + 0.5)*m_dStep, (j + 0.5)*m_dStep, 0) ;
|
|
// Vettore spostamento da ptLe a ptC
|
|
Vector3d vtC = ( ptC - ptStart) ;
|
|
// Componenti parallela e perpendicolare a vtMove
|
|
// Vettore ortogonale a vtMove
|
|
Vector3d vtOrt = vtMove ;
|
|
// Ruoto vtOrt affinché sia ortogonale
|
|
vtOrt.Rotate( Z_AX, -90) ;
|
|
|
|
double dProj = vtC * vtOrt ;
|
|
Vector3d vtPara = vtOrt * dProj ; // Parallelo alla perpendicolare al movimento
|
|
Vector3d vtPerp = vtC - vtPara ; // Perpendicolare alla perpendicolare al movimento ( serve per unire le getminmax di drill e perp)
|
|
// Distanza di ptC dall'asse dell'untensile
|
|
double dSqDist = vtPerp.SqLen() ;
|
|
double dLimitMill = dLenPath + dFactor * ( m_dHeight - dCylH) ;
|
|
// Se dTestProj è positivo è vtC è dalla parte giusta
|
|
double dTestProj = vtC * vtMove ;
|
|
|
|
if ( dTestProj > 0 && dSqDist < dLimitMill * dLimitMill)
|
|
if ( dProj > - m_dRadius && dProj < m_dRadius)
|
|
GetMinMaxXY( i, j, dProj, dHz, dSqDist, 0, dLenPath, dScProd) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingPerpXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
// Determinazione delle posizioni iniziali e finali della punta dell'utensile
|
|
Point3d ptTLs = ptLs - vtToolDir * m_dHeight ;
|
|
Point3d ptTLe = ptLe - vtToolDir * m_dHeight ;
|
|
|
|
// Quota Z
|
|
double dZH = ptLs.z ;
|
|
|
|
// Estremi Bounding box
|
|
double dMinX = min( min( ptLs.x, ptLe.x), min( ptTLs.x, ptTLe.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptLs.x, ptLe.x), max( ptTLs.x, ptTLe.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptLs.y, ptLe.y), min( ptTLs.y, ptTLe.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptLs.y, ptLe.y), max( ptTLs.y, ptTLe.y)) + m_dRadius ;
|
|
double dMinZ = dZH - m_dRadius ;
|
|
double dMaxZ = dZH + m_dRadius ;
|
|
|
|
// Verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Proiezione sul piano XY delle grandezze di interesse
|
|
Point3d ptStart( ptLs.x, ptLs.y, 0) ;
|
|
Point3d ptEnd( ptLe.x, ptLe.y, 0) ;
|
|
Vector3d vtMove = ptEnd - ptStart ;
|
|
double dLenPath = vtMove.Len() ;
|
|
// Normalizzo il vettore vtMove congiungente le posizioni iniziale e finale della base dell'utensile
|
|
vtMove.Normalize() ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
// Punto su cui ciclare e vettore congiungente posizione iniziale della base a tale punto
|
|
Point3d ptC( (i + 0.5) * m_dStep, (j + 0.5) * m_dStep, 0) ;
|
|
Vector3d vtC = ptC - ptStart ;
|
|
// Proiezione di vtC sulla direzione del movimento
|
|
double dProj = vtC * vtMove ;
|
|
// Componente di vtC ortogonale al movimento
|
|
Vector3d vtPerp = vtC - vtMove * dProj ;
|
|
// Lunghezza quadrata del precedente vettore
|
|
double dSqDist = vtPerp.SqLen() ;
|
|
|
|
if ( dProj > - m_dRadius && dProj < dLenPath + m_dRadius && vtPerp * vtToolDir < 0 && dSqDist < m_dHeight * m_dHeight)
|
|
GetMinMaxXY( i, j, dProj, dZH, dSqDist, dLenPath, 0, 0) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYPlaneGen( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptI = ptLs ; Point3d ptF = ptLe ;
|
|
|
|
// Quote dei punti ptI e ptF
|
|
double dZ = ptI.z ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * m_dHeight ;
|
|
Point3d ptFT = ptF - vtToolDir * m_dHeight ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
Vector3d vtMove = ptF - ptI ;
|
|
|
|
if ( vtMove * vtToolDir > 0) {
|
|
Point3d ptTemp = ptI ;
|
|
ptI = ptF ;
|
|
ptF = ptTemp ;
|
|
vtMove = - vtMove ;
|
|
}
|
|
|
|
Vector3d vtMoveOrt = vtMove - ( vtMove * vtToolDir) * vtToolDir ; double dLen2 = vtMoveOrt.Len() ;
|
|
Vector3d vtMoveLong = ( vtMove * vtToolDir) * vtToolDir ; double dLen1 = vtMoveLong.Len() ;
|
|
|
|
// Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ;
|
|
|
|
// Punti iniziale e finale proiettati sul piano
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
if ( m_nToolType == 1) {
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dProj1 = vtC * vtV1 ;
|
|
double dProj2 = vtC * vtV2 ;
|
|
|
|
GetMMPlaneGenCyl( i, j, dZ, dLen1, dLen2, dProj1, dProj2) ;
|
|
}
|
|
else if ( m_nToolType == 2)
|
|
|
|
GetMMPlaneGenBall( i, j, dZ, dLen1, dLen2, ptIxy, vtMove, vtV1, vtV2) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMMPlaneGenCyl( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, double dProj1, double dProj2) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
if ( dProj2 > - m_dRadius && dProj2 < 0) {
|
|
|
|
if ( dProj1 < 0 && dProj1 > - m_dHeight) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj1 <= - m_dHeight) {
|
|
|
|
if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - m_dHeight - ( dLen1 / dLen2) * ( dProj2 + m_dRadius))
|
|
|| ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) { // In questo costrutto if-else non c'è bisogno di specificare nient'altro perché già siamo nella regione - m_dRadius < dProj2 < 0
|
|
|
|
double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ;
|
|
double dL = m_dRadius - ( dLen2 / dLen1) * dPar ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
else if ( dProj2 >= 0 && dProj2 < m_dRadius) {
|
|
|
|
if ( dProj1 < 0 && ( ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) || ( dProj2 >= dLen2 && dProj1 > - dLen1))) {
|
|
|
|
double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ;
|
|
/* Oppure
|
|
double dPar1 = ( dLen1 / dLen2) * dProj2 + dProj1 ;
|
|
double dPar2 = ( dLen2 / dLen1) * dPar1 ; */
|
|
double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2) {
|
|
|
|
if ( dProj1 > - ( dLen1 / dLen2) * dProj2 - m_dHeight) {
|
|
|
|
dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 - m_dHeight) {
|
|
|
|
if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - ( dLen1 / dLen2) * ( dProj2 + m_dRadius) - m_dHeight)
|
|
|| ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) { // modificato qui
|
|
|
|
double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ;
|
|
double dL = m_dRadius - ( dLen2 / dLen1) * dPar ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
else if ( dProj2 >= dLen2 && dProj1 < - dLen1) {
|
|
|
|
if ( dProj1 > - m_dHeight - dLen1) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dLen2) * ( dProj2 - dLen2)) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
else if ( dProj2 >= m_dRadius && dProj2 < dLen2) {
|
|
|
|
if ( dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius) && dProj1 > - ( dLen1 / dLen2) * dProj2) {
|
|
|
|
double dL = ( dLen2 / dLen1) * ( ( dLen1 / dLen2) * dProj2 + dProj1) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - m_dHeight) {
|
|
|
|
dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ;
|
|
|
|
SubtractIntervals( i, j, dMin , dMax) ;
|
|
}
|
|
else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 - m_dHeight) {
|
|
|
|
if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - ( dLen1 / dLen2) * ( dProj2 + m_dRadius) - m_dHeight)
|
|
|| ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) {
|
|
|
|
double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ;
|
|
double dL = m_dRadius - ( dLen2 / dLen1) * dPar ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
else if ( dProj2 >= dLen2 && dProj2 < dLen2 + m_dRadius) {
|
|
|
|
if ( dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius) && dProj1 >= - dLen1) {
|
|
|
|
double dL = ( dLen2 / dLen1) * ( ( dLen1 / dLen2) * dProj2 + dProj1) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj1 < - dLen1 && dProj1 > - dLen1 - m_dHeight) {
|
|
|
|
double dL = dProj2 - dLen2 ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMMPlaneGenBall( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, Point3d ptIxy, Vector3d vtMove, Vector3d vtV1, Vector3d vtV2) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dProj1 = vtC * vtV1 ; // vtV1, vtV2 sono paralleli al piano
|
|
double dProj2 = vtC * vtV2 ;
|
|
|
|
double dCH = m_dHeight - m_dRadius ;
|
|
double dLMove = vtMove.LenXY() ;
|
|
|
|
Point3d ptCS = ptIxy - dCH * vtV1 ; Point3d ptCE = ptCS + vtMove ; // vtMove è orizzontale
|
|
|
|
Vector3d vtCS = ptC - ptCS ; Vector3d vtCE = ptC - ptCE ;
|
|
|
|
double dProjMove = ( vtCS * vtMove) / dLMove ;
|
|
|
|
Vector3d vtCSP = vtCS - ( ( vtCS * vtMove) / ( dLMove * dLMove)) * vtMove ;
|
|
|
|
double dSQDist = vtCSP.SqLenXY() ;
|
|
double dSQDistS = vtCS.SqLenXY() ;
|
|
double dSQDistE = vtCE.SqLenXY() ;
|
|
|
|
// parte cilindrica
|
|
|
|
if ( dProj2 > - m_dRadius && dProj2 < 0) {
|
|
|
|
if ( dProj1 > - dCH && dProj1 < 0) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else if ( dProj2 >= 0 && dProj2 < m_dRadius) {
|
|
|
|
if ( dProj1 < 0 && ( ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) || ( dProj2 >= dLen2 && dProj1 > - dLen1))) {
|
|
|
|
double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ;
|
|
/* Oppure
|
|
double dPar1 = ( dLen1 / dLen2) * dProj2 + dProj1 ;
|
|
double dPar2 = ( dLen2 / dLen1) * dPar1 ; */
|
|
double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - dCH) {
|
|
|
|
dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj2 >= dLen2 && dProj1 <= - dLen1 && dProj1 > - dLen1 - dCH) {
|
|
|
|
double dL = dProj2 - dLen2 ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else if ( dProj2 >= m_dRadius && dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius)) {
|
|
|
|
if ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) {
|
|
|
|
double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ;
|
|
double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - dCH) {
|
|
|
|
dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj2 >= dLen2 && dProj2 < dLen2 + m_dRadius) {
|
|
|
|
if ( dProj1 > - dLen1) {
|
|
|
|
double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ;
|
|
double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj1 <= - dLen1 && dProj1 > - dLen1 - dCH) {
|
|
|
|
double dL = dProj2 - dLen2 ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
// parte non cilindrica
|
|
|
|
|
|
if ( dProjMove > - m_dRadius && dProjMove < 0) {
|
|
|
|
if ( dSQDistS < m_dRadius * m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSQDistS) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else if ( dProjMove >= 0 && dProjMove < dLMove) {
|
|
|
|
if ( dSQDist < m_dRadius * m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSQDist) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ( dSQDistE < m_dRadius * m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSQDistE) ;
|
|
|
|
dMin = dZ - dH ; dMax = dZ + dH ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYLongVert( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
// Determino posizioni punte
|
|
Point3d ptTLs = ptLs - vtToolDir * m_dHeight ;
|
|
Point3d ptTLe = ptLe - vtToolDir * m_dHeight ;
|
|
|
|
// Variabili utili
|
|
double dDelta = ptLe.z - ptLs.z ; double dMin, dMax ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptLs.x, ptLe.x), min( ptTLs.x, ptTLe.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptLs.x, ptLe.x), max( ptTLs.x, ptTLe.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptLs.y, ptLe.y), min( ptTLs.y, ptTLe.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptLs.y, ptLe.y), max( ptTLs.y, ptTLe.y)) + m_dRadius ;
|
|
double dMinZ = min( ptLs.z, ptLs.z + dDelta) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLs.z + dDelta) + m_dRadius ;
|
|
|
|
// Controllo su interferenza utensile-Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Definizione delle grandezze geometriche essenziali
|
|
Vector3d vtMove = ptLe - ptLs ;
|
|
Vector3d vtPlaneMove = ( vtMove * vtToolDir) * vtToolDir ; //( vtMove * vtToolDir < 0 ? ( - vtMove * vtToolDir) * vtToolDir : ( vtMove * vtToolDir) * vtToolDir) ;
|
|
Vector3d vtZMove = vtMove - vtPlaneMove ;
|
|
|
|
double dLenPlanePath = sqrt( vtPlaneMove * vtPlaneMove) ;
|
|
|
|
if ( m_nToolType == 1) {
|
|
|
|
if ( abs ( ( vtMove * vtToolDir) * dDelta) < EPS_SMALL) {
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
Point3d ptStart( ptLs.x, ptLs.y, 0) ;
|
|
Vector3d vtC = ptC - ptStart ;
|
|
double dProj = vtC * vtToolDir ;
|
|
Vector3d vtP = vtC - dProj * vtToolDir ;
|
|
double dSqD = vtP * vtP ;
|
|
double dZH = ptLs.z ;
|
|
|
|
if ( dSqD < m_dRadius * m_dRadius && dProj < 0 && dProj > - m_dHeight) {
|
|
|
|
double dFactor = ( dDelta > 0 ? 1 : - 1) ;
|
|
dMin = min( dZH, dZH + dDelta + dFactor * sqrt( m_dRadius * m_dRadius - dSqD)) ;
|
|
dMax = max( dZH, dZH + dDelta + dFactor * sqrt( m_dRadius * m_dRadius - dSqD)) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
Point3d ptSt ;
|
|
|
|
if ( vtMove * vtToolDir < 0 && dDelta > 0)
|
|
ptSt = ptLs ;
|
|
else if ( vtMove * vtToolDir < 0 && dDelta < 0) {
|
|
ptSt = ptTLe ; vtPlaneMove = - vtPlaneMove ; dDelta = - dDelta ;
|
|
}
|
|
else if ( vtMove * vtToolDir > 0 && dDelta < 0) {
|
|
ptSt = ptLe ; vtPlaneMove = - vtPlaneMove ; dDelta = - dDelta ;
|
|
}
|
|
else {
|
|
ptSt = ptTLs ;// vtPlaneMove = - vtPlaneMove ;
|
|
}
|
|
|
|
double dZH = ptSt.z ;
|
|
Point3d ptStart ( ptSt.x, ptSt.y, 0) ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
vtPlaneMove.Normalize() ;
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
Vector3d vtC = ptC - ptStart ;
|
|
|
|
double dProj = vtPlaneMove * vtC ;
|
|
|
|
Vector3d vtP = vtC - dProj * vtPlaneMove ;
|
|
|
|
double dSqD = vtP * vtP ;
|
|
|
|
if ( dSqD < m_dRadius * m_dRadius) {
|
|
|
|
if ( dProj > 0 && dProj < m_dHeight) {
|
|
|
|
dMin = dZH - sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
if ( dProj < dLenPlanePath)
|
|
dMax = dZH + sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * dProj ;
|
|
else
|
|
dMax = dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dProj >= m_dHeight && dProj < m_dHeight + dLenPlanePath) {
|
|
|
|
dMin = dZH - sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * ( dProj - m_dHeight) ;
|
|
|
|
if ( dProj < dLenPlanePath)
|
|
dMax = dZH + sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * dProj ;
|
|
else
|
|
dMax = dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
else if ( m_nToolType == 2) {
|
|
|
|
if ( abs ( ( vtMove * vtToolDir) * dDelta) < EPS_SMALL) {
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
Point3d ptStart( ptLs.x, ptLs.y, 0) ;
|
|
Vector3d vtC = ptC - ptStart ;
|
|
double dProj = vtC * vtToolDir ;
|
|
Vector3d vtP = vtC - dProj * vtToolDir ;
|
|
double dSqD = vtP * vtP ;
|
|
double dZH = ptLs.z ;
|
|
|
|
|
|
if ( dProj < 0 && dProj > - m_dHeight + m_dRadius) {
|
|
|
|
if ( dSqD < m_dRadius * m_dRadius) {
|
|
|
|
dMin = min( dZH - sqrt( m_dRadius * m_dRadius - dSqD), dZH + dDelta - sqrt( m_dRadius * m_dRadius - dSqD)) ;
|
|
dMax = max( dZH + sqrt( m_dRadius * m_dRadius - dSqD), dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD)) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Chiedere per =
|
|
else if ( dProj <= - m_dHeight + m_dRadius && dProj > - m_dHeight) {
|
|
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
double dL = abs( - dProj - dCylH) ;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
|
|
if ( dSqD < dR * dR) {
|
|
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt ( dR * dR - dSqD) : 0) ;
|
|
|
|
dMin = min( dZH - dH, dZH - dH + dDelta) ;
|
|
dMax = max( dZH + dH, dZH + dH + dDelta) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else { // Movimento obliquo
|
|
|
|
Point3d ptStart = ptLs ;
|
|
|
|
double dA = m_dRadius / sqrt( 1 + ( dDelta * dDelta) / (dLenPlanePath * dLenPlanePath)) ;
|
|
double dSemiAxMin = ( abs( dDelta) * dA) / dLenPlanePath ;
|
|
|
|
if ( ( vtToolDir * vtMove) * dDelta < 0) {
|
|
|
|
if ( dDelta < 0) {
|
|
vtPlaneMove = - vtPlaneMove ;
|
|
dDelta = - dDelta ;
|
|
ptStart = ptLe ;
|
|
}
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
Point3d ptS( ptStart.x, ptStart.y, 0) ;
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
Vector3d vtC = ptC - ptS ;
|
|
double dProj = vtC * vtToolDir ;
|
|
Vector3d vtP = vtC - ( vtC * vtToolDir) * vtToolDir ;
|
|
double dSqD = vtP * vtP ;
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
double dZH = ptStart.z ;
|
|
|
|
if ( dSqD < m_dRadius * m_dRadius) {
|
|
|
|
if ( dProj < 0 && dProj > - m_dHeight - dLenPlanePath) {
|
|
|
|
if ( dProj > -dCylH) {
|
|
// parte cilindrica orizzontale inferiore
|
|
double dH = ( m_dRadius * m_dRadius - dSqD > 0 ? sqrt( m_dRadius * m_dRadius - dSqD) : 0) ;
|
|
dMin = dZH - dH ;
|
|
}
|
|
else if ( dProj > - dCylH - dSemiAxMin * sqrt( 1 - dSqD / ( m_dRadius * m_dRadius))) {
|
|
// parte sferica inferiore
|
|
double dL = - dProj - dCylH ;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMin = dZH - dH ;
|
|
}
|
|
else if ( dProj > - dCylH - dLenPlanePath - dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius))) {
|
|
// parte cilindrica obliqua inferiore
|
|
double dl = dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) ;
|
|
|
|
dMin = dZH - dA * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) - ( dDelta / dLenPlanePath) * ( dProj + dCylH + dl) ;
|
|
}
|
|
else if ( dProj > - m_dHeight - dLenPlanePath) {
|
|
// seconda parte sferica inferiore
|
|
double dL = - dProj - dCylH - dLenPlanePath;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMin = dZH + dDelta - dH ;
|
|
}
|
|
|
|
if ( dProj > - dLenPlanePath) {
|
|
// parte cilindrica obliqua superiore
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
dMax = dZH + dH - ( dDelta / dLenPlanePath) * dProj ;
|
|
}
|
|
else if ( dProj > - dLenPlanePath - dCylH) {
|
|
// parte cilindrica orizzontale superiore
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
dMax = dZH + dDelta + dH ;
|
|
}
|
|
else if ( dProj > - dLenPlanePath - m_dHeight) {
|
|
// parte sferica superiore
|
|
double dL = - dProj - dCylH - dLenPlanePath;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMax = dZH + dDelta + dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
else {
|
|
|
|
if ( dDelta > 0) {
|
|
vtPlaneMove = - vtPlaneMove ;
|
|
dDelta = - dDelta ;
|
|
ptStart = ptLe ;
|
|
}
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
Point3d ptS( ptStart.x, ptStart.y, 0) ;
|
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
|
Vector3d vtC = ptC - ptS ;
|
|
double dProj = vtC * vtToolDir ;
|
|
Vector3d vtP = vtC - ( vtC * vtToolDir) * vtToolDir ;
|
|
double dSqD = vtP * vtP ;
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
double dZH = ptStart.z ;
|
|
|
|
if ( dSqD < m_dRadius * m_dRadius) {
|
|
|
|
if ( dProj < 0 && dProj > - m_dHeight - dLenPlanePath) {
|
|
|
|
if ( dProj > - dLenPlanePath) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
dMin = dZH - dH - ( dDelta / dLenPlanePath) * dProj ;
|
|
}
|
|
else if ( dProj > - dLenPlanePath - dCylH) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqD) ;
|
|
|
|
dMin = dZH + dDelta - dH ;
|
|
}
|
|
else if ( dProj > - dLenPlanePath - m_dHeight) {
|
|
|
|
double dL = - dProj - dCylH - dLenPlanePath;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMin = dZH + dDelta - dH ;
|
|
}
|
|
|
|
if ( dProj > - dCylH) {
|
|
|
|
double dH = ( m_dRadius * m_dRadius - dSqD > 0 ? sqrt( m_dRadius * m_dRadius - dSqD) : 0) ;
|
|
dMax = dZH + dH ;
|
|
}
|
|
else if ( dProj > - dCylH - dSemiAxMin * sqrt( 1 - dSqD / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dL = - dProj - dCylH ;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMax = dZH + dH ;
|
|
}
|
|
else if ( dProj > - dCylH - dLenPlanePath - dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius))) {
|
|
|
|
double dl = dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) ;
|
|
|
|
dMax = dZH + dA * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) - ( dDelta / dLenPlanePath) * ( dProj + dCylH + dl) ;
|
|
}
|
|
else if ( dProj > - m_dHeight - dLenPlanePath) {
|
|
|
|
double dL = - dProj - dCylH - dLenPlanePath;
|
|
double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ;
|
|
|
|
dMax = dZH + dDelta + dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
else if ( m_nToolType == 3)
|
|
return true ;
|
|
else
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
|
|
double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z < ptLe.z) {
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
// Quote dei punti ptI e ptF
|
|
double dZI = ptI.z ; double dZF = ptF.z ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * m_dHeight ;
|
|
Point3d ptFT = ptF - vtToolDir * m_dHeight ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
Vector3d vtMove = ptF - ptI ; //double dLenPath = vtMove.Len() ;
|
|
|
|
// Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMove ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Determinazione punti notevoli del volume spazzato dall'utensile
|
|
Point3d ptPlaneSup, ptPlaneInf ;
|
|
|
|
if ( vtV3.z > 0) {
|
|
ptPlaneInf = ptI - m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI + m_dRadius * vtV3 ;
|
|
}
|
|
else {
|
|
ptPlaneInf = ptI + m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI - m_dRadius * vtV3 ;
|
|
}
|
|
|
|
// Prodotti scalari per costruire i piani passanti per i punti notevoli
|
|
Vector3d vtR0Inf = ptPlaneInf - ORIG ;
|
|
Vector3d vtR0Sup = ptPlaneSup - ORIG ;
|
|
|
|
double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ;
|
|
|
|
// Determinazione delle proiezioni sul piano delle entità geometriche fondamentali
|
|
Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPlanePath = vtPlaneMove.Len() ; vtPlaneMove.Normalize() ;
|
|
Vector3d vtPlaneLim( m_dRadius * vtV3.x, m_dRadius * vtV3.y, 0) ; double dPlaneLim = vtPlaneLim.Len() ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
double dZInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
double dZSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dProj1 = vtC * vtV1 ; // vtV1 è vtToolDir che per il momento giace nel piano
|
|
double dProj2 = vtC * vtPlaneMove ; // vtPlaneMove è stato normalizzato dopo averne calcolato la lunghezza
|
|
|
|
if ( dProj1 < 0 && dProj1 > - m_dHeight && dProj2 > - m_dRadius && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
|
|
// Minimi
|
|
if ( dProj2 > - m_dRadius && dProj2 < dPlaneLim) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
else if ( dProj2 >= dPlaneLim && dProj2 < dPlanePath + dPlaneLim) {
|
|
|
|
dMin = dZInf ;
|
|
}
|
|
else if ( dProj2 >= dPlanePath + dPlaneLim && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
// Massimi
|
|
if ( dProj2 > - m_dRadius && dProj2 < - dPlaneLim) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
else if ( dProj2 >= - dPlaneLim && dProj2 < dPlanePath - dPlaneLim) {
|
|
|
|
dMax = dZSup ;
|
|
}
|
|
else if ( dProj2 >= dPlanePath - dPlaneLim && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z < ptLe.z) {
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
// Quote dei punti ptI e ptF e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * m_dHeight ;
|
|
Point3d ptFT = ptF - vtToolDir * m_dHeight ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
Vector3d vtMove = ptF - ptI ;
|
|
|
|
// Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMove ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Determinazione punti notevoli del volume spazzato dall'utensile
|
|
Point3d ptPlaneSup, ptPlaneInf ;
|
|
|
|
if ( vtV3.z > 0) {
|
|
ptPlaneInf = ptI - m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI + m_dRadius * vtV3 ;
|
|
}
|
|
else {
|
|
ptPlaneInf = ptI + m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI - m_dRadius * vtV3 ;
|
|
}
|
|
|
|
// Prodotti scalari per costruire i piani passanti per i punti notevoli
|
|
Vector3d vtR0Inf = ptPlaneInf - ORIG ;
|
|
Vector3d vtR0Sup = ptPlaneSup - ORIG ;
|
|
|
|
double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ;
|
|
|
|
// Determinazione delle proiezioni sul piano delle entità geometriche fondamentali
|
|
Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPlanePath = vtPlaneMove.Len() ; vtPlaneMove.Normalize() ;
|
|
Vector3d vtPlaneLim( m_dRadius * vtV3.x, m_dRadius * vtV3.y, 0) ; double dPlaneLim = vtPlaneLim.Len() ;
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
double dZInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
double dZSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
Vector3d vtC = ptC - ptIxy ;
|
|
|
|
double dProj1 = vtC * vtV1 ; // vtV1 è vtToolDir che per il momento giace nel piano
|
|
double dProj2 = vtC * vtPlaneMove ; // vtPlaneMove è stato normalizzato dopo averne calcolato la lunghezza
|
|
|
|
// Parte cilindrica
|
|
if ( dProj1 < 0 && dProj1 > - dCylH && dProj2 > - m_dRadius && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
// Minimi
|
|
if ( dProj2 > - m_dRadius && dProj2 < dPlaneLim) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
else if ( dProj2 >= dPlaneLim && dProj2 < dPlanePath + dPlaneLim) {
|
|
|
|
dMin = dZInf ;
|
|
}
|
|
else if ( dProj2 >= dPlanePath + dPlaneLim && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
// Massimi
|
|
if ( dProj2 > - m_dRadius && dProj2 < - dPlaneLim) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
else if ( dProj2 >= - dPlaneLim && dProj2 < dPlanePath - dPlaneLim) {
|
|
|
|
dMax = dZSup ;
|
|
}
|
|
else if ( dProj2 >= dPlanePath - dPlaneLim && dProj2 < dPlanePath + m_dRadius) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
// Parte sferica
|
|
else if ( ( dProj2 > - m_dRadius && dProj2 < 0 && dProj2 * dProj2 + (- dProj1 - dCylH) * (- dProj1 - dCylH) < m_dRadius * m_dRadius) ||
|
|
( dProj2 >= 0 && dProj2 < dPlanePath && dProj1 > - m_dHeight && dProj1 <= - dCylH) ||
|
|
( dProj2 >= dPlanePath && dProj2 < dPlanePath + m_dRadius && ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath) + (- dProj1 - dCylH) * (- dProj1 - dCylH) < m_dRadius * m_dRadius)) {
|
|
|
|
|
|
double dSemiMin = dPlaneLim ; double dSemiMax = m_dRadius ; // Semi-assi dell'ellisse
|
|
double dl = - dProj1 - dCylH ;
|
|
|
|
// Massimi
|
|
if ( dProj2 < - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) {
|
|
|
|
double dr = sqrt( dProj2 * dProj2 + dl * dl) ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
else if ( dProj2 < dPlanePath - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) {
|
|
|
|
double dCos = abs( vtV3 * Z_AX) ;
|
|
|
|
dMax = dZI + sqrt( m_dRadius * m_dRadius - dl * dl) * dCos + ( dDeltaZ / dPlanePath) * ( dProj2 + dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) ;
|
|
}
|
|
else {
|
|
|
|
double dL = dProj2 - dPlanePath ;
|
|
double dr = sqrt( dL * dL + dl * dl) ;
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
// Minimi
|
|
if ( dProj2 < dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) {
|
|
|
|
double dr = sqrt( dProj2 * dProj2 + dl * dl) ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
else if ( dProj2 < dPlanePath + dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) {
|
|
|
|
double dCos = abs( vtV3 * Z_AX) ;
|
|
|
|
dMin = dZI - sqrt( m_dRadius * m_dRadius - dl * dl) * dCos + ( dDeltaZ / dPlanePath) * ( dProj2 - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) ;
|
|
}
|
|
else {
|
|
|
|
double dr = sqrt( ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath) + dl * dl) ;
|
|
double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}
|
|
/*
|
|
// DA TENERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYPlusCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z <= ptLe.z) {
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
// Quote dei punti ptI e ptF e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * m_dHeight ;
|
|
Point3d ptFT = ptF - vtToolDir * m_dHeight ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Vettori di riferimento nello spazio e controllo per simmetria
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtTool = vtToolDir ;
|
|
|
|
if ( vtToolDir * vtMove > 0) {
|
|
|
|
Point3d ptTemp = ptI ;
|
|
ptI = ptIT ; ptIT = ptTemp ;
|
|
ptTemp = ptF ;
|
|
ptF = ptFT ;
|
|
ptFT = ptTemp ;
|
|
vtTool = - vtTool ;
|
|
}
|
|
|
|
Vector3d vtMoveOrt = vtMove - ( vtMove * vtTool) * vtTool ; double dLen2 = vtMoveOrt.Len() ;
|
|
Vector3d vtMoveLong = ( vtMove * vtTool) * vtTool ; double dLen1 = vtMoveLong.Len() ;
|
|
|
|
// Vettori di riferimento nel piano
|
|
Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ;
|
|
Vector3d vtPlaneMoveLong( vtMoveLong.x, vtMoveLong.y, 0) ; double dPLen1 = vtPlaneMoveLong.LenXY() ;
|
|
Vector3d vtPlaneMoveOrt( vtMoveOrt.x, vtMoveOrt.y, 0) ; double dPLen2 = vtPlaneMoveOrt.LenXY() ; vtPlaneMoveOrt.Normalize() ;
|
|
|
|
// Punti iniziale e finale proiettati sul piano
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
// Determino i sistemi di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento
|
|
Vector3d vtV1 = vtTool ;
|
|
Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Determinazione punti notevoli del volume spazzato dall'utensile
|
|
Point3d ptPlaneSup, ptPlaneInf ;
|
|
|
|
if ( vtV3.z > 0) {
|
|
ptPlaneInf = ptI - m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI + m_dRadius * vtV3 ;
|
|
}
|
|
else {
|
|
ptPlaneInf = ptI + m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI - m_dRadius * vtV3 ;
|
|
}
|
|
|
|
Point3d ptPlaneSupxy( ptPlaneSup.x, ptPlaneSup.y, 0) ;
|
|
Point3d ptPlaneInfxy( ptPlaneInf.x, ptPlaneInf.y, 0) ;
|
|
|
|
double dr = sqrt( ( ptPlaneSupxy - ptIxy) * ( ptPlaneSupxy - ptIxy)) ;
|
|
|
|
// Determinazione degli analoghi punti sulla punta dell'utensile e delle loro proiezioni sul piano XY
|
|
Point3d ptPlTInf = ptPlaneInf - m_dHeight * vtTool ; Point3d ptPlTInfxy( ptPlTInf.x, ptPlTInf.y, 0) ;
|
|
Point3d ptPlTSup = ptPlaneSup - m_dHeight * vtTool ; Point3d ptPlTSupxy( ptPlTSup.x, ptPlTSup.y, 0) ;
|
|
|
|
// Prodotti scalari per costruire i piani passanti per i punti notevoli
|
|
Vector3d vtR0Inf = ptPlaneInf - ORIG ;
|
|
Vector3d vtR0Sup = ptPlaneSup - ORIG ;
|
|
Vector3d vtR0 = ptI - ORIG ;
|
|
double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; double dP = vtR0 * vtV3 ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
double dZPInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
double dZPSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano superiore come funzione di x e y
|
|
|
|
// Punto e vettori del ciclo
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtCi = ptC - ptIxy ;
|
|
// Proiezione fondamentale
|
|
double dPro1 = vtCi * vtV1 ; double dPro2 = vtCi * vtPlaneMoveOrt ;
|
|
|
|
|
|
// Se il punto cade nella proiezione sul piano XY del volume spazzato si taglia
|
|
if ( ((dPro2 > - m_dRadius && dPro2 < m_dRadius) && (((dPro2 < dPLen2 - m_dRadius && (dPro1 > - m_dHeight - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) && dPro1 < 0))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < 0))))
|
|
|| ((dPro2 >= m_dRadius && dPro2 < dPLen2 + m_dRadius) && ((dPro2 < dPLen2 - m_dRadius && (dPro1 > - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) - m_dHeight && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius)))))) {
|
|
|
|
// Massimi //////////////////////////////////////////////////////////////////////////
|
|
// Prima zona cilindrica superiore
|
|
if ( ( dPro2 > - m_dRadius && dPro2 < - dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
|
|
// Vettore per seconda zona cilindrica superiore
|
|
Vector3d vtCf = ptC - ptFxy ;
|
|
// Proiezione per seconda zona cilindrica sueriore
|
|
double dPr1 = vtCf * vtV1 ; double dPr2 = vtCf * vtPlaneMoveOrt ;
|
|
|
|
// Seconda zona cilindrica superiore
|
|
if ( ( dPr2 >= - dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
// Vettore per Piano superiore e zona di fondo superiore
|
|
Vector3d vtCS = ptC - ptPlaneSupxy ;
|
|
// Proiezioni
|
|
double dPrS1 = vtCS * vtV1 ; double dPrS2 = vtCS * vtPlaneMoveOrt ;
|
|
|
|
// Piano superiore
|
|
if ( dPrS2 >= 0 && dPrS2 < dPLen2 && dPrS1 > - m_dHeight - ( dPLen1/dPLen2) * dPrS2 && dPrS1 <= - ( dPLen1/dPLen2) * dPrS2)
|
|
|
|
dMax = dZPSup ;
|
|
|
|
// Vettore per zona di punta superiore
|
|
Vector3d vtCTS = ptC - ptPlTSupxy ;
|
|
// Proiezioni
|
|
double dPrTS1 = vtCTS * vtV1 ; double dPrTS2 = vtCTS * vtPlaneMoveOrt ;
|
|
|
|
// Zona di punta superiore
|
|
if ( dPrTS1 <= 0 && dPrTS1 > - dPLen1)
|
|
if ( dPrTS2 <= - ( dPLen2 / dPLen1) * dPrTS1 && dPrTS2 > - ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrTS1) {
|
|
|
|
double dDist = - ( dPLen2 / dPLen1) * dPrTS1 - dPrTS2 ;
|
|
double dL = dDist + dr ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrTS1 * dPrTS1 + ( ( dPLen2 / dPLen1) * dPrTS1) * ( ( dPLen2 / dPLen1) * dPrTS1)) ;
|
|
|
|
dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ;
|
|
}
|
|
|
|
// Zona di fondo superiore
|
|
if ( dPrS1 < 0 && dPrS1 > - dPLen1)
|
|
if ( dPrS2 > - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < dr - ( dPLen2 / dPLen1) * dPrS1) {
|
|
|
|
double dL = dr - ( dPLen2 / dPLen1) * dPrS1 - dPrS2 ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ;
|
|
|
|
dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ;
|
|
}
|
|
else if ( dPrS2 >= dr - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < dr + m_dRadius - ( dPLen2 / dPLen1) * dPrS1) {
|
|
|
|
double dL = dPrS2 - ( dr - ( dPLen2 / dPLen1) * dPrS1) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ;
|
|
|
|
dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ;
|
|
}
|
|
|
|
// Minimi //////////////////////////////////////////////////////////////////////////
|
|
// Prima zona cilindrica inferiore
|
|
if ( ( dPro2 > - m_dRadius && dPro2 < dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
|
|
// Seconda zona cilindrica inferiore
|
|
if ( ( dPr2 >= dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
|
|
// Vettore per piano inferiore e zona di fondo inferiore
|
|
Vector3d vtCI = ptC - ptPlaneInfxy ;
|
|
// Proiezioni
|
|
double dPrI1 = vtCI * vtV1 ; double dPrI2 = vtCI * vtPlaneMoveOrt ;
|
|
|
|
// Piano inferiore
|
|
if ( dPrI2 >= 0 && dPrI2 < dPLen2 && dPrI1 > - m_dHeight - ( dPLen1/dPLen2) * dPrI2 && dPrI1 <= - ( dPLen1/dPLen2) * dPrI2)
|
|
|
|
dMin = dZPInf ;
|
|
|
|
// Zona di fondo inferiore
|
|
if ( dPrI1 <= 0 && dPrI1 > - dPLen1)
|
|
if ( dPrI2 > - ( dPLen2 / dPLen1) * dPrI1 && dPrI2 < ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrI1) {
|
|
|
|
double dDist = dPrI2 + ( dPLen2 / dPLen1) * dPrI1 ;
|
|
double dL = dDist + dr ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrI1 * dPrI1 + ( ( dPLen2 / dPLen1) * dPrI1) * ( ( dPLen2 / dPLen1) * dPrI1)) ;
|
|
|
|
dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ;
|
|
}
|
|
|
|
// Vettore per zona di punta inferiore
|
|
Vector3d vtCTI = ptC - ptPlTInfxy ;
|
|
// Proiezioni
|
|
double dPrTI1 = vtCTI * vtV1 ; double dPrTI2 = vtCTI * vtPlaneMoveOrt ;
|
|
|
|
// zona di punta inferiore
|
|
if ( dPrTI1 <= 0 && dPrTI1 > - dPLen1)
|
|
if ( dPrTI2 > - m_dRadius - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 <= - dr - ( dPLen2 / dPLen1) * dPrTI1) {
|
|
|
|
double dL = - dr - ( dPLen2 / dPLen1) * dPrTI1 - dPrTI2 ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ;
|
|
|
|
dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ;
|
|
}
|
|
else if ( dPrTI2 > - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 < - ( dPLen2 / dPLen1) * dPrTI1) {
|
|
|
|
double dL = dPrTI2 - ( - dr - ( dPLen2 / dPLen1) * dPrTI1 ) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ;
|
|
|
|
dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ;
|
|
}
|
|
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}*/
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYPlusCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ;
|
|
double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z <= ptLe.z) {
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
// Quote dei punti ptI e ptF e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
Point3d ptIT = ptI - vtToolDir * m_dHeight ;
|
|
Point3d ptFT = ptF - vtToolDir * m_dHeight ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ;
|
|
double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ;
|
|
double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ;
|
|
double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Vettori di riferimento nello spazio e controllo per simmetria
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtTool = vtToolDir ;
|
|
|
|
if ( vtToolDir * vtMove > 0) {
|
|
|
|
Point3d ptTemp = ptI ;
|
|
ptI = ptIT ; ptIT = ptTemp ;
|
|
ptTemp = ptF ;
|
|
ptF = ptFT ;
|
|
ptFT = ptTemp ;
|
|
vtTool = - vtTool ;
|
|
}
|
|
|
|
Vector3d vtMoveLong = ( vtMove * vtTool) * vtTool ; double dLen1 = vtMoveLong.Len() ;
|
|
Vector3d vtMoveOrt = vtMove - vtMoveLong ; double dLen2 = vtMoveOrt.Len() ;
|
|
|
|
// Vettori di riferimento nel piano
|
|
Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ;
|
|
Vector3d vtPlaneMoveLong( vtMoveLong.x, vtMoveLong.y, 0) ; double dPLen1 = vtPlaneMoveLong.LenXY() ;
|
|
Vector3d vtPlaneMoveOrt( vtMoveOrt.x, vtMoveOrt.y, 0) ; double dPLen2 = vtPlaneMoveOrt.LenXY() ; vtPlaneMoveOrt.Normalize() ;
|
|
|
|
// Punti iniziale e finale proiettati sul piano
|
|
Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ;
|
|
|
|
// Determino i sistemi di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento
|
|
Vector3d vtV1 = vtTool ;
|
|
Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Determinazione punti notevoli del volume spazzato dall'utensile
|
|
Point3d ptPlaneSup, ptPlaneInf ;
|
|
|
|
if ( vtV3.z > 0) {
|
|
ptPlaneInf = ptI - m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI + m_dRadius * vtV3 ;
|
|
}
|
|
else {
|
|
ptPlaneInf = ptI + m_dRadius * vtV3 ;
|
|
ptPlaneSup = ptI - m_dRadius * vtV3 ;
|
|
}
|
|
|
|
Point3d ptPlaneSupxy( ptPlaneSup.x, ptPlaneSup.y, 0) ;
|
|
Point3d ptPlaneInfxy( ptPlaneInf.x, ptPlaneInf.y, 0) ;
|
|
|
|
double dr = sqrt( ( ptPlaneSupxy - ptIxy) * ( ptPlaneSupxy - ptIxy)) ;
|
|
|
|
// Determinazione degli analoghi punti sulla punta dell'utensile e delle loro proiezioni sul piano XY
|
|
Point3d ptPlTInf = ptPlaneInf - m_dHeight * vtTool ; Point3d ptPlTInfxy( ptPlTInf.x, ptPlTInf.y, 0) ;
|
|
Point3d ptPlTSup = ptPlaneSup - m_dHeight * vtTool ; Point3d ptPlTSupxy( ptPlTSup.x, ptPlTSup.y, 0) ;
|
|
|
|
// Prodotti scalari per costruire i piani passanti per i punti notevoli
|
|
Vector3d vtR0Inf = ptPlaneInf - ORIG ;
|
|
Vector3d vtR0Sup = ptPlaneSup - ORIG ;
|
|
Vector3d vtR0 = ptI - ORIG ;
|
|
double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; double dP = vtR0 * vtV3 ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
double dZPInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y
|
|
double dZPSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano superiore come funzione di x e y
|
|
|
|
// Punto e vettori del ciclo
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtCi = ptC - ptIxy ;
|
|
// Proiezione fondamentale
|
|
double dPro1 = vtCi * vtV1 ; double dPro2 = vtCi * vtPlaneMoveOrt ;
|
|
|
|
|
|
// Se il punto cade nella proiezione sul piano XY del volume spazzato si taglia
|
|
if ( ((dPro2 > - m_dRadius && dPro2 < m_dRadius) && (((dPro2 < dPLen2 - m_dRadius && (dPro1 > - m_dHeight - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) && dPro1 < 0))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < 0))))
|
|
|| ((dPro2 >= m_dRadius && dPro2 < dPLen2 + m_dRadius) && ((dPro2 < dPLen2 - m_dRadius && (dPro1 > - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) - m_dHeight && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius)))))) {
|
|
|
|
// Massimi //////////////////////////////////////////////////////////////////////////
|
|
// Prima zona cilindrica superiore
|
|
if ( ( dPro2 > - m_dRadius && dPro2 < - dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
|
|
// Vettore per seconda zona cilindrica superiore
|
|
Vector3d vtCf = ptC - ptFxy ;
|
|
// Proiezione per seconda zona cilindrica sueriore
|
|
double dPr1 = vtCf * vtV1 ; double dPr2 = vtCf * vtPlaneMoveOrt ;
|
|
|
|
// Seconda zona cilindrica superiore
|
|
if ( ( dPr2 >= - dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
// Vettore per Piano superiore e zona di fondo superiore
|
|
Vector3d vtCS = ptC - ptPlaneSupxy ;
|
|
// Proiezioni
|
|
double dPrS1 = vtCS * vtV1 ; double dPrS2 = vtCS * vtPlaneMoveOrt ;
|
|
|
|
// Piano superiore
|
|
if ( dPrS2 >= 0 && dPrS2 < dPLen2 && dPrS1 > - m_dHeight - ( dPLen1/dPLen2) * dPrS2 && dPrS1 <= - ( dPLen1/dPLen2) * dPrS2)
|
|
|
|
dMax = dZPSup ;
|
|
|
|
// Vettore per zona di punta superiore
|
|
Vector3d vtCTS = ptC - ptPlTSupxy ;
|
|
// Proiezioni
|
|
double dPrTS1 = vtCTS * vtV1 ; double dPrTS2 = vtCTS * vtPlaneMoveOrt ;
|
|
|
|
// Zona di punta superiore
|
|
if ( dPrTS1 <= 0 && dPrTS1 > - dPLen1)
|
|
if ( dPrTS2 <= - ( dPLen2 / dPLen1) * dPrTS1 && dPrTS2 > - ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrTS1) {
|
|
|
|
double dDist = - ( dPLen2 / dPLen1) * dPrTS1 - dPrTS2 ;
|
|
double dL = dDist + dr ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrTS1 * dPrTS1 + ( ( dPLen2 / dPLen1) * dPrTS1) * ( ( dPLen2 / dPLen1) * dPrTS1)) ;
|
|
|
|
dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ;
|
|
}
|
|
|
|
// Zona di fondo superiore
|
|
if ( dPrS1 < 0 && dPrS1 > - dPLen1)
|
|
if ( dPrS2 > - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < m_dRadius + dr - ( dPLen2 / dPLen1) * dPrS1) {
|
|
|
|
double dL = abs( dr - ( dPLen2 / dPLen1) * dPrS1 - dPrS2) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ;
|
|
|
|
dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ;
|
|
}
|
|
|
|
// Minimi //////////////////////////////////////////////////////////////////////////
|
|
// Prima zona cilindrica inferiore
|
|
if ( ( dPro2 > - m_dRadius && dPro2 < dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
|
|
// Seconda zona cilindrica inferiore
|
|
if ( ( dPr2 >= dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
|
|
// Vettore per piano inferiore e zona di fondo inferiore
|
|
Vector3d vtCI = ptC - ptPlaneInfxy ;
|
|
// Proiezioni
|
|
double dPrI1 = vtCI * vtV1 ; double dPrI2 = vtCI * vtPlaneMoveOrt ;
|
|
|
|
// Piano inferiore
|
|
if ( dPrI2 >= 0 && dPrI2 < dPLen2 && dPrI1 > - m_dHeight - ( dPLen1/dPLen2) * dPrI2 && dPrI1 <= - ( dPLen1/dPLen2) * dPrI2)
|
|
|
|
dMin = dZPInf ;
|
|
|
|
// Zona di fondo inferiore
|
|
if ( dPrI1 <= 0 && dPrI1 > - dPLen1)
|
|
if ( dPrI2 > - ( dPLen2 / dPLen1) * dPrI1 && dPrI2 < ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrI1) {
|
|
|
|
double dDist = dPrI2 + ( dPLen2 / dPLen1) * dPrI1 ;
|
|
double dL = dDist + dr ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrI1 * dPrI1 + ( ( dPLen2 / dPLen1) * dPrI1) * ( ( dPLen2 / dPLen1) * dPrI1)) ;
|
|
|
|
dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ;
|
|
}
|
|
|
|
// Vettore per zona di punta inferiore
|
|
Vector3d vtCTI = ptC - ptPlTInfxy ;
|
|
// Proiezioni
|
|
double dPrTI1 = vtCTI * vtV1 ; double dPrTI2 = vtCTI * vtPlaneMoveOrt ;
|
|
|
|
// zona di punta inferiore
|
|
if ( dPrTI1 <= 0 && dPrTI1 > - dPLen1)
|
|
if ( dPrTI2 > - m_dRadius - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 < - ( dPLen2 / dPLen1) * dPrTI1) {
|
|
|
|
double dL = abs( - dr - ( dPLen2 / dPLen1) * dPrTI1 - dPrTI2) ;
|
|
double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ;
|
|
double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ;
|
|
|
|
dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}
|
|
|
|
/*
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYPlusBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
// Parte cilindrica
|
|
|
|
m_dHeight = m_dHeight - m_dRadius ;
|
|
|
|
MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ;
|
|
|
|
m_dHeight = m_dHeight + m_dRadius ;
|
|
////////////////////////////////////////
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z < ptLe.z) {
|
|
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
|
|
Point3d ptCI = ptI - dCylH * vtToolDir ;
|
|
Point3d ptCF = ptF - dCylH * vtToolDir ;
|
|
|
|
Point3d ptCIxy( ptCI.x, ptCI.y, 0) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptCI.x, ptCF.x) - m_dRadius ;
|
|
double dMaxX = max( ptCI.x, ptCF.x) + m_dRadius ;
|
|
double dMinY = min( ptCI.y, ptCF.y) - m_dRadius ;
|
|
double dMaxY = max( ptCI.y, ptCF.y) + m_dRadius ;
|
|
|
|
Vector3d vtMove = ptF - ptI ;
|
|
|
|
// Sistema di riferimento
|
|
Vector3d vtV2 = vtMove ; vtV2.Normalize() ;
|
|
Vector3d vtV1 ;
|
|
|
|
if ( abs( vtV2.y) < EPS_SMALL)
|
|
|
|
vtV1 = Y_AX ;
|
|
else
|
|
vtV1 = X_AX - ( vtV2.x / vtV2.y) * Y_AX ;
|
|
|
|
if ( vtV1 * vtToolDir < 0)
|
|
|
|
vtV1 = - vtV1 ;
|
|
|
|
vtV1.Normalize() ;
|
|
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
|
|
// Determino il semi-asse minore
|
|
Vector3d vtSemiMin( vtV3.x, vtV3.y, 0) ;
|
|
double dSemiAxMin = m_dRadius * vtSemiMin.LenXY() ;
|
|
|
|
Vector3d vtMovexy( vtMove.x, vtMove.y, 0) ; double dPlaneLen = vtMovexy.LenXY() ;
|
|
Vector3d vtU1 = vtV1 ;
|
|
Vector3d vtU2 ;
|
|
|
|
if ( abs( vtV2.y) < EPS_SMALL) {
|
|
|
|
if ( vtV2.x > 0)
|
|
|
|
vtU2 = X_AX ;
|
|
else
|
|
vtU2 = - X_AX ;
|
|
}
|
|
else {
|
|
|
|
vtU2 = vtMovexy ; vtU2.Normalize() ;
|
|
}
|
|
|
|
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Vector3d vtC = ptC - ptCIxy ;
|
|
|
|
double dProj1 = vtC * vtU1 ; double dProj2 = vtC * vtU2 ;
|
|
|
|
double dSqRadDistI = dProj1 * dProj1 + dProj2 * dProj2 ;
|
|
double dSqRadDistF = dProj1 * dProj1 + ( dProj2 - dPlaneLen) * ( dProj2 - dPlaneLen) ;
|
|
double dSqAxDist = dProj1 * dProj1 ;
|
|
|
|
if ( ( dProj2 < 0 && dSqRadDistI < m_dRadius * m_dRadius) ||
|
|
( dProj2 >= 0 && dProj2 < dPlaneLen && dSqAxDist < m_dRadius * m_dRadius) ||
|
|
( dProj2 >= dPlaneLen && dSqRadDistF < m_dRadius * m_dRadius)) {
|
|
|
|
// Massimi
|
|
if ( dProj2 < - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
else if ( dProj2 >= - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) &&
|
|
dProj2 < dPlaneLen - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dProj0 = - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) ;
|
|
double dZ0 = dZI + ( dPlaneLen / dDeltaZ) * ( - dProj0) ;
|
|
|
|
dMax = dZ0 + ( dDeltaZ / dPlaneLen) * ( dProj2 - dProj0) ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
// Minimi
|
|
if ( dProj2 < dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
else if ( dProj2 >= dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) &&
|
|
dProj2 < dPlaneLen + dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dProj0 = dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) ;
|
|
double dZ0 = dZI + ( dPlaneLen / dDeltaZ) * ( - dProj0) ;
|
|
|
|
dMin = dZ0 + ( dDeltaZ / dPlaneLen) * ( dProj2 - dProj0) ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
|
|
return true ;
|
|
}
|
|
*/
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::MillingXYPlusBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) {
|
|
|
|
// Parte cilindrica
|
|
|
|
double dCylH = m_dHeight - m_dRadius ;
|
|
|
|
m_dHeight = dCylH ;
|
|
|
|
MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ;
|
|
|
|
m_dHeight = m_dHeight + m_dRadius ;
|
|
////////////////////////////////////////
|
|
Point3d ptI, ptF ;
|
|
|
|
if ( ptLs.z < ptLe.z) {
|
|
|
|
ptI = ptLs ;
|
|
ptF = ptLe ;
|
|
}
|
|
else {
|
|
|
|
ptI = ptLe ;
|
|
ptF = ptLs ;
|
|
}
|
|
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
Point3d ptCI = ptI - dCylH * vtToolDir ;
|
|
Point3d ptCF = ptF - dCylH * vtToolDir ;
|
|
|
|
Point3d ptCIxy( ptCI.x, ptCI.y, 0) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptCI.x, ptCF.x) - m_dRadius ;
|
|
double dMaxX = max( ptCI.x, ptCF.x) + m_dRadius ;
|
|
double dMinY = min( ptCI.y, ptCF.y) - m_dRadius ;
|
|
double dMaxY = max( ptCI.y, ptCF.y) + m_dRadius ;
|
|
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ; vtMove.Normalize() ;
|
|
|
|
// Sistema di riferimento nel piano
|
|
Vector3d vtV2 = vtPlaneMove ; vtV2.Normalize() ; double dComp1 = vtV2 * X_AX ; double dComp2 = vtV2 * Y_AX ;
|
|
Vector3d vtV1 = dComp2 * X_AX - dComp1 * Y_AX ;
|
|
|
|
// Determino il semi-asse minore
|
|
double dOriz = vtMove * Z_AX ; double dVert = vtMove * vtV2 ;
|
|
|
|
double dSemiAxMin = m_dRadius * dOriz ;
|
|
|
|
// Determinazione limiti sugli indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
// Ciclo
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ;
|
|
|
|
Vector3d vtC = ptC - ptCIxy ;
|
|
|
|
double dProj1 = vtC * vtV1 ; double dProj2 = vtC * vtV2 ;
|
|
|
|
double dSqRadDistI = dProj1 * dProj1 + dProj2 * dProj2 ;
|
|
double dSqRadDistF = dProj1 * dProj1 + ( dProj2 - dPLen) * ( dProj2 - dPLen) ;
|
|
double dSqAxDist = dProj1 * dProj1 ;
|
|
|
|
if ( ( dProj2 < 0 && dSqRadDistI < m_dRadius * m_dRadius) ||
|
|
( dProj2 >= 0 && dProj2 < dPLen && dSqAxDist < m_dRadius * m_dRadius) ||
|
|
( dProj2 >= dPLen && dSqRadDistF < m_dRadius * m_dRadius)) {
|
|
|
|
// Massimi
|
|
if ( dProj2 < - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ;
|
|
|
|
dMax = dZI + dH ;
|
|
}
|
|
else if ( dProj2 >= - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) &&
|
|
dProj2 < dPLen - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dProj0 = - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) ;
|
|
double dZ0 = dZI + dVert * sqrt( m_dRadius * m_dRadius - dSqAxDist) ;
|
|
|
|
dMax = dZ0 + ( dDeltaZ / dPLen) * ( dProj2 - dProj0) ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ;
|
|
|
|
dMax = dZF + dH ;
|
|
}
|
|
|
|
// Minimi
|
|
if ( dProj2 < dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ;
|
|
|
|
dMin = dZI - dH ;
|
|
}
|
|
else if ( dProj2 >= dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) &&
|
|
dProj2 < dPLen + dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) {
|
|
|
|
double dProj0 = dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) ;
|
|
double dZ0 = dZI - dVert * sqrt( m_dRadius * m_dRadius - dSqAxDist) ;
|
|
|
|
dMin = dZ0 + ( dDeltaZ / dPLen) * ( dProj2 - dProj0) ;
|
|
}
|
|
else {
|
|
|
|
double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ;
|
|
|
|
dMin = dZF - dH ;
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxXY( unsigned int nI, unsigned int nJ, double dProj, double dZheight, double dSqD, double dPathPerp, double dPathPar, double dScProd) {
|
|
|
|
// Definisco la variabile altezza della parte cilindrica dell'utensile
|
|
double dCylH ;
|
|
// Definisco variabili per determinazione intervallo da sottrarre
|
|
double dL, dR, dH ;
|
|
|
|
// Caso di utensile generico ( per ora non gestito)
|
|
if ( m_nToolType == 0)
|
|
return false ;
|
|
// Se utensile standard setto altezza della parte cilindrica
|
|
else if ( m_nToolType == 1)
|
|
dCylH = m_dHeight ;
|
|
else if ( m_nToolType == 2)
|
|
dCylH = m_dHeight - m_dRadius ;
|
|
else if ( m_nToolType == 3)
|
|
dCylH = m_dHeight - m_dRCorner ;
|
|
// Caso di utensile non definito
|
|
else
|
|
return false ;
|
|
|
|
// Parametri per isolare la lavorazione della parte cilindrica comune a tutti gli utensili standard
|
|
// Limite nella direziona parallela all'asse dell'utensile e parametro perpendicolare
|
|
double dLimPar, dParPerp ;
|
|
|
|
// Tagli perpendicolari all'asse dell'utensile
|
|
if ( abs( dScProd) < EPS_SMALL) {
|
|
dLimPar = dCylH ;
|
|
dParPerp = dPathPerp ;
|
|
}
|
|
// Tagli paralleli all'asse dell'utensile
|
|
else {
|
|
dLimPar = dPathPar ;
|
|
dParPerp = 0 ;
|
|
}
|
|
|
|
// Parte cilindrica della lavorazione
|
|
if ( dSqD < dLimPar * dLimPar) {
|
|
// Qui il raggio del semicerchio è m_dRadius
|
|
if ( dProj < 0)
|
|
// dH = sqrt( m_dRadius^2 - dProj^2)
|
|
dH = sqrt( m_dRadius * m_dRadius - ( dProj * dProj)) ;
|
|
// Qui l'altezza è costante
|
|
else if ( dProj < dParPerp)
|
|
// dH = m_dRadius
|
|
dH = m_dRadius ;
|
|
// Qui il raggio del semicerchio è m_dRadius
|
|
else if ( dProj < dParPerp + m_dRadius)
|
|
// dH = sqrt( m_dRadius^2 - ( dProj - dParPerp)^2)
|
|
dH = sqrt( m_dRadius * m_dRadius - ( dProj - dParPerp) * ( dProj - dParPerp)) ;
|
|
// Eseguo il taglio
|
|
return SubtractIntervals( nI, nJ, dZheight - dH, dZheight + dH) ;
|
|
}
|
|
// Parte non cilindrica, questa parte esiste solo nei tagli (dScProd = 0) e nel foro con la punta quindi (dScProd < 0)
|
|
// e solo con frese non cilindriche
|
|
else {
|
|
if ( dScProd < EPS_SMALL) {
|
|
// Definisco variabili
|
|
// Caso fresa ball-end
|
|
if ( m_nToolType == 2) {
|
|
// Il raggio è sqrt( m_dRadius^2 - ( sqrt( dSqD) - dLimPar)^2)
|
|
if ( dProj < 0) {
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dR = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
dH = sqrt( dR * dR - (dProj * dProj)) ;
|
|
}
|
|
// Qui dH non dipende da dProj
|
|
else if ( dProj < dParPerp) {
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dH = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
}
|
|
// E' analogo al primo caso con la sostituzione di dProj con dProj - dParPerp
|
|
else if ( dProj < dParPerp + m_dRadius) { // In questo caso è equivalente a else
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dR = sqrt( m_dRadius * m_dRadius - dL * dL) ;
|
|
dH = sqrt( dR * dR - ((dProj - dParPerp) * (dProj - dParPerp))) ;
|
|
}
|
|
}
|
|
// Caso di fresa bull-nose
|
|
else if ( m_nToolType == 3) {
|
|
// Raggio semicerchio m_dRadius - m_dRCorner + sqrt( m_dRCorner^2 - ( sqrt( dSqD) - dLimPar)^2)
|
|
if ( dProj < 0) {
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dR = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ;
|
|
dH = sqrt( dR * dR - ( dProj * dProj)) ;
|
|
}
|
|
// Qui dH non dipende da dProj
|
|
else if ( dProj < dParPerp) {
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dH = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ;
|
|
}
|
|
// E' analogo al primo caso con la sostituzione di di dProj con dProj - dParPerp
|
|
else if ( dProj < dParPerp + m_dRadius) { // In questo caso equivalente a else
|
|
dL = sqrt( dSqD) - dLimPar ;
|
|
dR = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ;
|
|
dH = sqrt( dR * dR - ( ( dProj - dParPerp) * ( dProj - dParPerp))) ;
|
|
}
|
|
}
|
|
return SubtractIntervals( nI, nJ, dZheight - dH, dZheight + dH) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// Frese conus
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ConusDrillingZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) {
|
|
|
|
double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Bounding box
|
|
double dMinX = ptLs.x - dMaxRad ;
|
|
double dMaxX = ptLs.x + dMaxRad ;
|
|
double dMinY = ptLs.y - dMaxRad ;
|
|
double dMaxY = ptLs.y + dMaxRad ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
double dDeltaZ = abs( ptLe.z - ptLs.z) ;
|
|
|
|
Point3d ptO( ptLs.x, ptLs.y, 0) ;
|
|
|
|
// Limiti su indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
|
|
if ( m_dRadius < m_dTipRadius)
|
|
|
|
return GetMinMaxZSw( ptO, nStartI, nEndI, nStartJ, nEndJ, dMinZ, dMaxZ, dMinRad, dMaxRad, vtToolDir.z, dDeltaZ) ;
|
|
|
|
else
|
|
|
|
return GetMinMaxZDr( ptO, nStartI, nEndI, nStartJ, nEndJ, dMinZ, dMaxZ, dMinRad, dMaxRad, vtToolDir.z, dDeltaZ) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxZSw( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ;
|
|
|
|
double dSqDist = vtC * vtC ;
|
|
|
|
if ( dSqDist < dMaxRad * dMaxRad) {
|
|
|
|
if ( dSqDist < dMinRad * dMinRad) {
|
|
|
|
dMin = dMinZ ;
|
|
dMax = dMaxZ ;
|
|
}
|
|
else {
|
|
|
|
if ( dDir > 0) {
|
|
|
|
dMin = dMinZ ;
|
|
dMax = dMinZ + dDeltaZ + ( m_dTipHeight * ( dMaxRad - sqrt( dSqDist))) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else {
|
|
|
|
dMin = dMaxZ - dDeltaZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMaxRad)) / ( dMaxRad - dMinRad) ;
|
|
dMax = dMaxZ ;
|
|
}
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxZDr( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) {
|
|
|
|
double dMin, dMax ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ;
|
|
|
|
double dSqDist = vtC * vtC ;
|
|
|
|
if ( dSqDist < dMaxRad * dMaxRad) {
|
|
|
|
if ( dSqDist < dMinRad * dMinRad) {
|
|
|
|
dMin = dMinZ ;
|
|
dMax = dMaxZ ;
|
|
}
|
|
else {
|
|
|
|
if ( dDir > 0) {
|
|
|
|
dMin = dMinZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMinRad)) / ( dMaxRad - dMinRad) ;
|
|
dMax = dMaxZ ;
|
|
}
|
|
else {
|
|
|
|
dMin = dMinZ ;
|
|
dMax = dMaxZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMinRad)) / ( dMinRad - dMaxRad) ;
|
|
}
|
|
}
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ConusPerpZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) {
|
|
|
|
double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ; // Ricordati del caso balordo da mettere nella documentazione
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
Point3d ptO( ptLs.x, ptLs.y, 0) ;
|
|
Vector3d vtMove = ptLe - ptLs ; double dLen = vtMove.LenXY() ;
|
|
Vector3d vtV1 = vtMove ; vtV1.Normalize() ;
|
|
|
|
double dZBase = ptLs.z ;
|
|
double dZStem = ptLs.z - ( m_dHeight - m_dTipHeight) * vtToolDir.z ;
|
|
double dZTip = ptLs.z - m_dHeight * vtToolDir.z ;
|
|
|
|
// Limiti su indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
for( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ;
|
|
|
|
double dProj1 = vtC * vtV1 ;
|
|
Vector3d vtOrt = vtC - dProj1 * vtV1 ;
|
|
|
|
if ( dProj1 < 0) {
|
|
|
|
double dSqDist = vtC * vtC ;
|
|
|
|
if ( dSqDist < dMinRad * dMinRad) {
|
|
|
|
dMin = min( dZBase, dZTip) ;
|
|
dMax = max( dZBase, dZTip) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) {
|
|
|
|
if ( m_dRadius < m_dTipRadius) {
|
|
|
|
dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZTip, dZStem+ ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
else {
|
|
|
|
dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else if ( dProj1 >= 0 && dProj1 < dLen) {
|
|
|
|
double dSqDist = vtOrt * vtOrt ;
|
|
|
|
if ( dSqDist < dMinRad * dMinRad) {
|
|
|
|
dMin = min( dZBase, dZTip) ;
|
|
dMax = max( dZBase, dZTip) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) {
|
|
|
|
if ( m_dRadius < m_dTipRadius) {
|
|
|
|
dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
else {
|
|
|
|
dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
else if ( dProj1 >= dLen) {
|
|
|
|
Vector3d vtCn = vtC - vtMove ;
|
|
|
|
double dSqDist = vtCn * vtCn ;
|
|
|
|
if ( dSqDist < dMinRad * dMinRad) {
|
|
|
|
dMin = min( dZBase, dZTip) ;
|
|
dMax = max( dZBase, dZTip) ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) {
|
|
|
|
if ( m_dRadius < m_dTipRadius) {
|
|
|
|
dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
else {
|
|
|
|
dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ;
|
|
}
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
} // Fine ciclo
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ConusMillingZDr( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) {
|
|
|
|
double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Punti iniziale e finale e proiezione sul piano del punto iniziale
|
|
Point3d ptI, ptF, ptO ;
|
|
|
|
if( vtToolDir.z > 0) {
|
|
|
|
ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ;
|
|
}
|
|
else {
|
|
|
|
ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
}
|
|
|
|
|
|
// Quote iniziale e finale della base dell'utensile e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ;
|
|
|
|
// Vettori di movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ;
|
|
|
|
// Sistema di riferimento sul cono e vertice del cono
|
|
Vector3d vtV1 = vtToolDir ;
|
|
Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
Point3d ptV = ptI - ( m_dHeight + m_dTipHeight * dMinRad / ( dMaxRad - dMinRad)) * vtV1 ;
|
|
|
|
// Apertura del cono e parametri per determinare i piani
|
|
double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ;
|
|
double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ;
|
|
double dCos = dTanAlpha * dRatio ;
|
|
|
|
// Versori normali e prodotti scalari per per determinare i piani
|
|
Vector3d vtNs = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 + ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ;
|
|
Vector3d vtNd = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 - ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ;
|
|
Vector3d vtR0 = ptV - ORIG ;
|
|
double dDots = vtR0 * vtNs ;
|
|
double dDotd = vtR0 * vtNd ;
|
|
|
|
// Limiti su indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++ i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) {
|
|
|
|
double dMin, dMax ;
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; Vector3d vtCf = vtC - vtMoveXY ;
|
|
|
|
Vector3d vtUC = vtC ; Vector3d vtUCf = vtCf ; vtUC.Normalize() ; vtUCf.Normalize() ;
|
|
|
|
double dCCos = vtUC * vtV2 ; double dCCosf = vtUCf * vtV2 ;
|
|
|
|
double dProj = vtC * vtV2 ;
|
|
Vector3d vtOrt = vtC - dProj * vtV2 ;
|
|
|
|
double dSqDistI = vtC * vtC ; double dSqDistM = vtOrt * vtOrt ; double dSqDistF = vtCf * vtCf ;
|
|
|
|
if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad)
|
|
||( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad)
|
|
||( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) {
|
|
|
|
if ( vtToolDir.z > 0) {
|
|
// Massimi
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
if ( dProj < dLen - dPMaxI)
|
|
|
|
dMax = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxI) ;
|
|
else
|
|
dMax = dZF ;
|
|
|
|
// Minimi
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZI - m_dHeight ;
|
|
|
|
else {
|
|
|
|
if ( ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMin = dZI - m_dHeight + ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMin = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ;
|
|
else
|
|
dMin = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMin = dZF - m_dHeight + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
|
|
dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZI - m_dHeight + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen)
|
|
|
|
dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Massimi
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZI + m_dHeight ;
|
|
|
|
else {
|
|
|
|
if ( - ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMax = dZI + m_dHeight - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMax = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ;
|
|
else
|
|
dMax = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMax = dZF + m_dHeight - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
|
|
dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZI + m_dHeight - ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen)
|
|
|
|
dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
}
|
|
// Minimi
|
|
double dPMaxCirc = sqrt( dMaxRad * dMaxRad - dSqDistM) ;
|
|
|
|
if ( dProj > dLen - dPMaxCirc)
|
|
|
|
dMin = dZF ;
|
|
else
|
|
dMin = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxCirc) ;
|
|
}
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VolZmap::ConusMillingZSw( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) {
|
|
|
|
double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ;
|
|
|
|
// Prima verifica sull'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL)
|
|
return true ;
|
|
|
|
double dMaxRad = max( m_dRadius, m_dTipRadius) ;
|
|
double dMinRad = min( m_dRadius, m_dTipRadius) ;
|
|
|
|
// Bounding box
|
|
double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ;
|
|
double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ;
|
|
double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ;
|
|
double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ;
|
|
|
|
// Seconda verifica dell'interferenza dell'utensile con lo Zmap
|
|
if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL)
|
|
return true ;
|
|
|
|
// Punti iniziale e finale e proiezione sul piano del punto iniziale
|
|
Point3d ptI, ptF, ptO ;
|
|
|
|
if( vtToolDir.z > 0) {
|
|
|
|
ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
}
|
|
else {
|
|
|
|
ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ;
|
|
ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ;
|
|
}
|
|
|
|
Point3d ptICyl = ( ptLs.z < ptLe.z ? ptLs : ptLe) ;
|
|
|
|
double dDeltaH = m_dHeight - m_dTipHeight ;
|
|
double dMinZCyl = min( ptICyl.z, ptICyl.z - vtToolDir.z * dDeltaH) ;
|
|
|
|
|
|
// Punti contatto cono cilindro
|
|
Point3d ptIS = ptI - ( m_dHeight - m_dTipHeight) * vtToolDir ;
|
|
Point3d ptFS = ptF - ( m_dHeight - m_dTipHeight) * vtToolDir ;
|
|
|
|
// Quote iniziali e finali e DeltaZ
|
|
double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; double dADeltaZ = abs( dDeltaZ) ;
|
|
double dZIS = ptIS.z ; double dZFS = ptFS.z ;
|
|
|
|
// Vettori di movimento
|
|
Vector3d vtMove = ptF - ptI ;
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ;
|
|
|
|
// Sistema di riferimento sul cono e vertice del cono
|
|
Vector3d vtV1 = - vtToolDir ;
|
|
Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ;
|
|
Vector3d vtV3 = vtV1 ^ vtV2 ;
|
|
Point3d ptV = ptI + ( m_dHeight - m_dTipHeight * ( 1 + dMinRad / ( dMaxRad - dMinRad))) * vtV1 ;
|
|
|
|
// Apertura del cono e parametri per determinare i piani
|
|
double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ;
|
|
double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ;
|
|
double dCos = dTanAlpha * dRatio ;
|
|
|
|
// Versori normali e prodotti scalari per per determinare i piani
|
|
Vector3d vtNp = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 + ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ;
|
|
Vector3d vtNm = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 - ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ;
|
|
Vector3d vtR0 = ptV - ORIG ;
|
|
double dDotp = vtR0 * vtNp ;
|
|
double dDotm = vtR0 * vtNm ;
|
|
|
|
// Limiti su indici
|
|
unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinX / m_dStep)) ;
|
|
unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast <unsigned int> ( dMaxX / m_dStep)) ;
|
|
unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast <unsigned int> ( dMinY / m_dStep)) ;
|
|
unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast <unsigned int> ( dMaxY / m_dStep)) ;
|
|
|
|
for ( unsigned int i = nStartI ; i <= nEndI ; ++i)
|
|
for ( unsigned int j = nStartJ ; j <= nEndJ ; ++j) {
|
|
|
|
double dMin, dMax ;
|
|
double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ;
|
|
|
|
Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; Vector3d vtCf = vtC - vtMoveXY ;
|
|
|
|
Vector3d vtUC = vtC ; Vector3d vtUCf = vtCf ; vtUC.Normalize() ; vtUCf.Normalize() ;
|
|
|
|
double dCCos = vtUC * vtV2 ; double dCCosf = vtUCf * vtV2 ;
|
|
|
|
double dProj = vtC * vtV2 ;
|
|
Vector3d vtOrt = vtC - dProj * vtV2 ;
|
|
|
|
double dSqDistI = vtC * vtC ; double dSqDistM = vtOrt * vtOrt ; double dSqDistF = vtCf * vtCf ;
|
|
|
|
if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad)
|
|
||( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad)
|
|
||( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) {
|
|
|
|
if ( vtV1.z < 0) {
|
|
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
// Massimi
|
|
if ( dRatio <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS ;
|
|
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMax = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ;
|
|
else
|
|
dMax = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMax = dZFS - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMax = dZIS ;
|
|
|
|
else if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else {
|
|
|
|
if ( dProj >= dPMaxI)
|
|
|
|
dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
// Minimi
|
|
|
|
if ( dSqDistF < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZFS - m_dTipHeight ;
|
|
|
|
else if ( dProj <= dLen - dPMaxI)
|
|
|
|
dMin = dZIS - m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
} // Fine vtV1 < 0
|
|
else {
|
|
|
|
double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ;
|
|
|
|
// Massimi
|
|
if ( dSqDistF < dMaxRad * dMaxRad)
|
|
|
|
dMax = dZFS + m_dTipHeight ;
|
|
|
|
else if ( dProj <= dLen - dPMaxI)
|
|
|
|
dMax = dZIS + m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
// Minimi
|
|
if ( dRatio <= 1 / dTanAlpha) {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS ;
|
|
|
|
else {
|
|
|
|
if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos)
|
|
|
|
dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) {
|
|
|
|
double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ;
|
|
double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ;
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistM <= dMinSql)
|
|
|
|
dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
|
|
else if ( dSqDistM < dMaxSql) {
|
|
|
|
if ( vtC * vtV3 > 0)
|
|
|
|
dMin = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ;
|
|
else
|
|
dMin = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ;
|
|
}
|
|
}
|
|
else if ( dCCosf >= dCos) {
|
|
|
|
double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ;
|
|
|
|
if ( dSqDistF < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ;
|
|
else
|
|
dMin = dZFS + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ;
|
|
}
|
|
else
|
|
dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ( dSqDistI < dMinRad * dMinRad)
|
|
|
|
dMin = dZIS ;
|
|
|
|
else if ( dSqDistI < dMaxRad * dMaxRad)
|
|
|
|
dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ;
|
|
|
|
else
|
|
|
|
dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ;
|
|
|
|
}
|
|
}
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
}
|
|
|
|
// Parte cilindrica
|
|
Vector3d vtCyl = ( vtV1.z < 0 ? vtCf : vtC) ;
|
|
Vector3d vtCylf = ( vtV1.z < 0 ? vtC : vtCf) ;
|
|
Vector3d vtMot = ( vtV1.z < 0 ? - vtV2 : vtV2) ;
|
|
|
|
double dCylProj = vtCyl * vtMot ;
|
|
double dCylSqDistI = vtCyl * vtCyl ;
|
|
double dCylSqDistF = vtCylf * vtCylf ;
|
|
double dCylSqDistM = ( vtCyl - dCylProj * vtMot) * ( vtCyl - dCylProj * vtMot) ;
|
|
|
|
|
|
if ( dCylSqDistI < dMinRad * dMinRad
|
|
|| dCylSqDistF < dMinRad * dMinRad
|
|
|| ( dCylProj > 0 && dCylProj < dLen && dCylSqDistM < dMinRad * dMinRad)) {
|
|
|
|
double dSt = sqrt( dMinRad * dMinRad - dCylSqDistM) ;
|
|
|
|
// Minimi
|
|
if ( dCylSqDistI < dMinRad * dMinRad )
|
|
|
|
dMin = dMinZCyl ;
|
|
|
|
else if ( dCylProj >= dSt)
|
|
|
|
dMin = dMinZCyl + ( dCylProj - dSt) * dADeltaZ / dLen ;
|
|
|
|
// Massimi
|
|
if ( dCylSqDistF < dMinRad * dMinRad)
|
|
|
|
dMax = dMinZCyl + dDeltaH + dADeltaZ ;
|
|
|
|
else if ( dCylProj <= dLen - dSt)
|
|
|
|
dMax = dMinZCyl + dDeltaH + ( dCylProj + dSt) * dADeltaZ / dLen ;
|
|
|
|
SubtractIntervals( i, j, dMin, dMax) ;
|
|
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
|
|
|
|
// Utensile generico
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
VolZmap::GetMinMaxZGenTool( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) {
|
|
|
|
// Estremi dell'intervallo da asportare
|
|
double dMin, dMax ;
|
|
|
|
unsigned int CurveNum = m_ToolOutline.GetCurveCount() ; // Non dovrebbe servire
|
|
// Puntatore a un oggetto costante di tipo ICurve
|
|
const ICurve* pCurve ;
|
|
// L'inizio del ciclo dipende dal fatto che lavori la punta o il fondo dell'utensile
|
|
if ( vtToolDir.z * dDeltaZ < 0)
|
|
pCurve = m_ToolOutline.GetLastCurve() ;
|
|
else
|
|
pCurve = m_ToolOutline.GetFirstCurve() ;
|
|
|
|
// Ciclo
|
|
while ( pCurve != nullptr) {
|
|
|
|
int nCrvType = pCurve -> GetType() ;
|
|
|
|
const ICurve* pTest = pCurve ;
|
|
|
|
if ( vtToolDir.z * dDeltaZ < 0)
|
|
pTest = m_ToolOutline.GetNextCurve() ;
|
|
else
|
|
pTest = m_ToolOutline.GetPrevCurve() ;
|
|
|
|
// Caso di segmento
|
|
if ( nCrvType == CRV_LINE) {
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
pCurve->GetStartPoint( ptStart) ;
|
|
pCurve->GetEndPoint( ptEnd) ;
|
|
double dZStart, dMDPrev, angC, angCPrev ;
|
|
|
|
if ( abs( ptEnd.x - ptStart.x) > EPS_SMALL) {
|
|
|
|
if ( pTest == nullptr) {
|
|
|
|
if ( vtToolDir.z * dDeltaZ < 0) {
|
|
dZStart = ptEnd.y ;
|
|
angC = ( ptStart.y - ptEnd.y) / ( ptStart.x - ptEnd.x) ;
|
|
angCPrev = angC ;
|
|
}
|
|
else {
|
|
dZStart = ptStart.y ;
|
|
angC = ( ptEnd.y - ptStart.y) / ( ptEnd.x - ptStart.x) ;
|
|
angCPrev = angC ;
|
|
}
|
|
|
|
dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMDPrev = max( ptStart.x, ptEnd.x) ;
|
|
// Eseguo l'asportazione
|
|
SubtractIntervals( nI, nJ, dMin, dMax) ;
|
|
}
|
|
else {
|
|
|
|
double dMD ;
|
|
|
|
if ( vtToolDir.z * dDeltaZ < 0) {
|
|
|
|
dZStart = ptEnd.y ;
|
|
angC = ( ptStart.y - ptEnd.y) / ( ptStart.x - ptEnd.x) ;
|
|
dMD = max( ptStart.x, ptEnd.x) ;
|
|
|
|
if ( angCPrev < 0 && dMDPrev > dMD) {
|
|
dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMDPrev = max( ptStart.x, ptEnd.x) ;
|
|
}
|
|
|
|
angCPrev = angC ;
|
|
dMDPrev = dMD ;
|
|
}
|
|
else {
|
|
|
|
dZStart = ptStart.y ;
|
|
angC = ( ptEnd.y - ptStart.y) / ( ptEnd.x - ptStart.x) ;
|
|
dMD = max( ptStart.x, ptEnd.x) ;
|
|
|
|
if ( angCPrev < 0 && dMDPrev > max( ptStart.x, ptEnd.x)) {
|
|
dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ;
|
|
dMDPrev = max( ptStart.x, ptEnd.x) ;
|
|
}
|
|
|
|
angCPrev = angC ;
|
|
dMDPrev = dMD ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Caso di arco
|
|
else if ( nCrvType == CRV_ARC) {
|
|
return true ;
|
|
}
|
|
else
|
|
// Caso di Bézier et al..
|
|
return true ;
|
|
|
|
}
|
|
// Decremento/incremento il puntatore
|
|
if ( vtToolDir.z * dDeltaZ < 0)
|
|
pCurve = m_ToolOutline.GetPrevCurve() ;
|
|
else
|
|
pCurve = m_ToolOutline.GetNextCurve() ;
|
|
|
|
// Ricorda di guardare che tutti i casi abbiano il relatrivo enunciato di return
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|