//---------------------------------------------------------------------------- // 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( 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( 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 ( ceil( dLengthX / m_dStep)) ; m_nNy = static_cast ( 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_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 = dMax ; } // 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 (integerPartX) ; // Indici del punto di griglia più vicino. unsigned int j = static_cast (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 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 = dMax ; } // 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 (integerPartX) ; // Indici del punto di griglia più vicino. unsigned int j = static_cast (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 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, unsigned int nToolType, const CurveComposite* pToolOutline) { m_sToolName = pToolName ; m_nToolType = nToolType ; m_ToolOutline.CopyFrom( pToolOutline) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtDe) { // Dimensioni dell'utensile BBox3d Bounding ; m_ToolOutline.GetLocalBBox( Bounding) ; double dHeight = Bounding.GetMax().y - Bounding.GetMin().y ; double dRadius = Bounding.GetMax().x - Bounding.GetMin().x ; // 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) ; // Direzione utensile costante e come asse Z dello Zmap if ( AreSameVectorApprox( vtLs, vtLe) && vtLs.IsZplus()) { // Movimento diretto come direzione utensile if ( AreSamePointXYApprox( ptLs, ptLe)) return MillingDrill(ptLs, ptLe, dHeight, dRadius) ; // Movimento perpendicolare a direzione utensile else if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) return MillingPerp(ptLs, ptLe, dHeight, dRadius) ; // Movimento generico (per ora non gestito) else return false ; } // Altri casi, non gestiti else return false ; } //---------------------------------------------------------------------------- bool VolZmap::MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, double dRadius) { // Bounding box double dMinX = min( ptLs.x, ptLe.x) - dRadius ; double dMinY = min( ptLs.y, ptLe.y) - dRadius ; double dMaxX = max( ptLs.x, ptLe.x) + dRadius ; double dMaxY = max( ptLs.y, ptLe.y) + 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 ( dMinX / m_dStep)) ; unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; // Determino quote estreme del tagliente double dMax = ptLs.z - dHeight ; double dMin = ptLe.z - dHeight ; // Limite sul quadrato del raggio double dSqRad = ( dRadius + EPS_SMALL) * ( 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) SubtractIntervals( i, j, dMin, dMax) ; } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingPerp( Point3d& ptLs, Point3d& ptLe, double dHeight, double dRadius) { // Bounding box double dMinX = min( ptLs.x, ptLe.x) - dRadius ; double dMinY = min( ptLs.y, ptLe.y) - dRadius ; double dMaxX = max( ptLs.x, ptLe.x) + dRadius ; double dMaxY = max( ptLs.y, ptLe.y) + 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 ( dMinX / m_dStep)) ; unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; // Determino quote estreme del tagliente double dMax = ptLs.z ; double dMin = ptLs.z - dHeight ; // Questa andrà eliminata in futuro oppure la teniamo e la usiamo al bisogno // Limite sul quadrato del raggio double dSqRad = ( dRadius + EPS_SMALL) * ( 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) SubtractIntervals( i, j, dMin, dMax) ; } } return true ; }