//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // Contenuto : Implementazione della classe Volume Zmap (tre griglie) // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "VolZmap.h" #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkStringUtils3d.h" using namespace std ; //---------------------------------------------------------------------------- GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ; //---------------------------------------------------------------------------- VolZmap::VolZmap(void) : m_nStatus( TO_VERIFY), m_dStep( EPS_SMALL), m_nTempProp( 0), m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG), m_nVoxNumPerBlock( N_VOXBLOCK) { m_nMapNum = 0 ; m_nNumBlock = 0 ; m_nConnectedCompoCount = 0 ; for ( int i = 0 ; i < N_MAPS ; ++ i) { m_nNx[i] = 0 ; m_nNy[i] = 0 ; m_nDim[i] = 0 ; m_dMinZ[i] = 0 ; m_dMaxZ[i] = 0 ; m_nFracLin[i] = 0 ; } } //---------------------------------------------------------------------------- VolZmap::~VolZmap( void) { } //---------------------------------------------------------------------------- bool VolZmap::Clear( void) { m_nStatus = TO_VERIFY ; m_nMapNum = 0 ; m_nNumBlock = 0 ; m_nConnectedCompoCount = 0 ; m_MapFrame.Reset() ; for ( int i = 0 ; i < N_MAPS ; ++ i) { m_nNx[i] = 0 ; m_nNy[i] = 0 ; m_nDim[i] = 0 ; m_dMinZ[i] = 0 ; m_dMaxZ[i] = 0 ; m_Values[i].clear() ; } m_dStep = EPS_SMALL ; m_dLinTol = LIN_TOL_STD ; m_dAngTolDeg = ANG_TOL_APPROX_DEG; m_nTempProp = 0 ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- 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_nMapNum = vzmSrc.m_nMapNum ; m_nNumBlock = vzmSrc.m_nNumBlock ; m_nVoxNumPerBlock = vzmSrc.m_nVoxNumPerBlock ; m_nFracLin[0] = vzmSrc.m_nFracLin[0] ; m_nFracLin[1] = vzmSrc.m_nFracLin[1] ; m_nFracLin[2] = vzmSrc.m_nFracLin[2] ; m_nConnectedCompoCount = vzmSrc.m_nConnectedCompoCount ; m_MapFrame = vzmSrc.m_MapFrame ; for ( int i = 0 ; i < int ( m_nMapNum) ; ++ i) { m_nNx[i] = vzmSrc.m_nNx[i] ; m_nNy[i] = vzmSrc.m_nNy[i] ; m_nDim[i] = vzmSrc.m_nDim[i] ; m_dMinZ[i] = vzmSrc.m_dMinZ[i] ; m_dMaxZ[i] = vzmSrc.m_dMaxZ[i] ; m_Values[i] = vzmSrc.m_Values[i] ; } m_dStep = vzmSrc.m_dStep ; m_nStatus = vzmSrc.m_nStatus ; m_nTempProp = vzmSrc.m_nTempProp ; // dimensiono membri legati ai blocchi m_BlockToUpdate.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; // imposto ricalcolo grafica ResetGraphics() ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::ResetGraphics( void) { m_OGrMgr.Reset() ; for ( unsigned int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount) m_BlockToUpdate[nCount] = true ; return true ; } //---------------------------------------------------------------------------- GeoObjType VolZmap::GetType( void) const { return static_cast( GEOOBJ_GETTYPE( VolZmap)) ; } //---------------------------------------------------------------------------- const string& VolZmap::GetTitle( void) const { static const string sTitle = "VolZm" ; return sTitle ; } //---------------------------------------------------------------------------- bool VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const { // tipo sOut += "Type=" + string( m_nMapNum == 1 ? "dexel" : "tridexel") + szNewLine ; // passo sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 3) + szNewLine ; // dimensioni if ( m_nMapNum == 1) sOut += "Dim=" + ToString( m_nDim[0]) + "(" + ToString( m_nNx[0]) + "x" + ToString( m_nNy[0]) + ")" + szNewLine ; else { for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) sOut += "Dim" + ToString( i+1) + "=" + ToString( m_nDim[i]) + "(" + ToString( m_nNx[i]) + "x" + ToString( m_nNy[i]) + ")" + szNewLine ; } // numero di blocchi sOut += "Blocks=" + ToString( m_nNumBlock) + " (" + ToString( m_nFracLin[0]) + "x" + ToString( m_nFracLin[1]) + "x" + ToString( m_nFracLin[2]) + ")" + szNewLine ; return true ; } //---------------------------------------------------------------------------- int VolZmap::GetNgeId( void) const { return GEOOBJ_GETNGEID( VolZmap) ; } //---------------------------------------------------------------------------- bool VolZmap::Save( NgeWriter& ngeOut) const { // numero di mappe if ( ! ngeOut.WriteInt( m_nMapNum, ",", false)) return false ; // numero di blocchi if ( ! ngeOut.WriteInt( m_nNumBlock, ",", false)) return false ; // numero di dexel per blocco if ( ! ngeOut.WriteInt( m_nVoxNumPerBlock, ",", false)) return false ; // numero di blocchi per ogni asse for ( int i = 0 ; i < 3 ; ++ i) { if ( ! ngeOut.WriteInt( m_nFracLin[i], ",", false)) return false ; } // numero di componenti connesse if ( ! ngeOut.WriteInt( m_nConnectedCompoCount, ",", false)) return false ; // passo di campionamento (distanza tra spilloni) if ( ! ngeOut.WriteDouble( m_dStep, ";", true)) return false ; // sistema di riferimento if ( ! ngeOut.WriteFrame( m_MapFrame, ";", true)) return false ; // per ogni mappa : numero di passi in X e Y e quote z estremali for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { if ( ! ngeOut.WriteInt( m_nNx[i], ",", false)) return false ; if ( ! ngeOut.WriteInt( m_nNy[i], ",", false)) return false ; if ( ! ngeOut.WriteDouble( m_dMinZ[i], ",", false)) return false ; if ( ! ngeOut.WriteDouble( m_dMaxZ[i], ";", true)) return false ; } // ciclo sulle mappe for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { // ciclo sui dexel for ( unsigned int j = 0 ; j < m_nDim[i] ; ++ j) { // numero di estremi unsigned int nDim = unsigned int( m_Values[i][j].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 < nDim ; ++ k) { if ( ! ngeOut.WriteDouble( m_Values[i][j][k].dMin, ",", false)) return false ; if ( ! ngeOut.WriteInt( m_Values[i][j][k].nToolMin, ";", false)) return false ; if ( ! ngeOut.WriteVector( m_Values[i][j][k].vtMinN, ";", false)) return false ; if ( ! ngeOut.WriteDouble( m_Values[i][j][k].dMax, ",", false)) return false ; if ( ! ngeOut.WriteInt( m_Values[i][j][k].nToolMax, ";", false)) return false ; if ( ! ngeOut.WriteVector( m_Values[i][j][k].vtMaxN, ";", false)) return false ; if ( ! ngeOut.WriteInt( m_Values[i][j][k].nCompo, ";", true)) return false ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Load( NgeReader& ngeIn) { Clear() ; // numero di mappe if ( ! ngeIn.ReadInt( m_nMapNum, ",", false)) return false ; // numero di blocchi if ( ! ngeIn.ReadInt( m_nNumBlock, ",", false)) return false ; // numero di dexel per blocco if ( ! ngeIn.ReadInt( m_nVoxNumPerBlock, ",", false)) return false ; // numero di blocchi per ogni asse for ( int i = 0 ; i < 3 ; ++ i) { if ( ! ngeIn.ReadInt( m_nFracLin[i], ",", false)) return false ; } // numero di componenti connesse if ( ! ngeIn.ReadInt( m_nConnectedCompoCount, ",", false)) return false ; // passo di campionamento (distanza tra spilloni) if ( ! ngeIn.ReadDouble( m_dStep, ";", true)) return false ; // sistema di riferimento if ( ! ngeIn.ReadFrame( m_MapFrame, ";", true)) return false ; // per ogni mappa : numero di passi in X e Y e quote z estremali for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { if ( ! ngeIn.ReadInt( m_nNx[i], ",", false)) return false ; if ( ! ngeIn.ReadInt( m_nNy[i], ",", false)) return false ; m_nDim[i] = m_nNx[i] * m_nNy[i] ; if ( ! ngeIn.ReadDouble( m_dMinZ[i], ",", false)) return false ; if ( ! ngeIn.ReadDouble( m_dMaxZ[i], ";", true)) return false ; } // ciclo sulle mappe for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { // dimensiono i vettori m_Values[i].resize( m_nDim[i]) ; // ciclo sui dexel for ( unsigned int j = 0 ; j < m_nDim[i] ; ++ j) { // leggo il numero di estremi nel dexel unsigned int nDim ; if ( ! ngeIn.ReadInt( nDim, ":", false)) return false ; // se dexel nullo if ( nDim == 0) { // leggo un valore dummy double dDummy ; if ( ! ngeIn.ReadDouble( dDummy, ";", true)) return false ; } // altrimenti else { // dimensiono l'array m_Values[i][j].resize( nDim) ; // leggo i valori for ( unsigned int k = 0 ; k < nDim ; ++ k) { if ( ! ngeIn.ReadDouble( m_Values[i][j][k].dMin, ",", false)) return false ; if ( ! ngeIn.ReadInt( m_Values[i][j][k].nToolMin, ";", false)) return false ; if ( ! ngeIn.ReadVector( m_Values[i][j][k].vtMinN, ";", false)) return false ; if ( ! ngeIn.ReadDouble( m_Values[i][j][k].dMax, ",", false)) return false ; if ( ! ngeIn.ReadInt( m_Values[i][j][k].nToolMax, ";", false)) return false ; if ( ! ngeIn.ReadVector( m_Values[i][j][k].vtMaxN, ";", false)) return false ; if ( ! ngeIn.ReadInt( m_Values[i][j][k].nCompo, ";", true)) return false ; } } } } // imposto aggiornamento obbligatorio su tutti i blocchi m_BlockToUpdate.resize( m_nNumBlock) ; for ( unsigned int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount) m_BlockToUpdate[nCount] = true ; // per triangoli di feature di frontiera tra blocchi m_InterBlockTria.resize( m_nNumBlock) ; 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() ; // se richiesto approssimato if ( ( nFlag & BBF_EXACT) == 0) { b3Loc.Add( ORIG) ; b3Loc.Add( Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; b3Loc.ToGlob( m_MapFrame) ; return true ; } // calcolo preciso // ciclo sui dexel (punti in basso con ciclo aggiunto per punti in alto di ultima riga) double dY = 0 ; for ( size_t j = 0 ; j <= m_nNy[0] ; ++ j) { size_t jc = ( ( j != m_nNy[0]) ? j : m_nNy[0] - 1) ; double dX = 0 ; // punto a sinistra di ogni dexel (aggiungo un ciclo per fare punto a destra di ultimo) for ( size_t i = 0 ; i <= m_nNx[0] ; ++ i) { size_t ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ; size_t nPos = ic + jc * m_nNx[0] ; if ( m_Values[0][nPos].size() > 0) { Point3d ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersX() + dY * m_MapFrame.VersY() ; b3Loc.Add( ptP + m_Values[0][nPos][0].dMin * m_MapFrame.VersZ()) ; b3Loc.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * m_MapFrame.VersZ()) ; } // passo al punto successivo dX += m_dStep ; } // passo alla riga successiva 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_MapFrame ; frUse.ToGlob( frRef) ; // se richiesto approssimato if ( ( nFlag & BBF_EXACT) == 0) { b3Ref.Add( ORIG) ; b3Ref.Add( Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; b3Ref.ToGlob( frUse) ; return true ; } // calcolo preciso // ciclo sui dexel (punti in basso con ciclo aggiunto per punti in alto di ultima riga) double dY = 0 ; for ( size_t j = 0 ; j <= m_nNy[0] ; ++ j) { size_t jc = ( ( j != m_nNy[0]) ? j : m_nNy[0] -1) ; double dX = 0 ; // punto a sinistra di ogni dexel (aggiungo un ciclo per fare punto a destra di ultimo) for ( size_t i = 0 ; i <= m_nNx[0] ; ++ i) { size_t ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] -1) ; size_t nPos = ic + jc * m_nNx[0] ; if ( m_Values[0][nPos].size() > 0) { Point3d ptP = frUse.Orig() + dX * frUse.VersX() + dY * frUse.VersY() ; b3Ref.Add( ptP + m_Values[0][nPos][0].dMin * frUse.VersZ()) ; b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ; } // passo al punto successivo dX += m_dStep ; } // passo alla riga successiva dY += m_dStep ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Translate( const Vector3d& vtMove) { // verifico lo stato if ( m_nStatus != OK) return false ; // imposto ricalcolo della grafica ResetGraphics() ; // traslo il riferimento m_MapFrame.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 ResetGraphics() ; // ruoto il riferimento m_MapFrame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; return true ; } //---------------------------------------------------------------------------- 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 ; // imposto ricalcolo della grafica ResetGraphics() ; // trasformo il riferimento m_MapFrame.ToGlob( frRef) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::ToLoc( const Frame3d& frRef) { // verifico lo stato if ( m_nStatus != OK) return false ; // imposto ricalcolo della grafica ResetGraphics() ; // trasformo il riferimento m_MapFrame.ToLoc( frRef) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { // verifico lo stato if ( m_nStatus != OK) return false ; // imposto ricalcolo della grafica ResetGraphics() ; // trasformo il riferimento m_MapFrame.LocToLoc( frOri, frDest) ; return true ; } //---------------------------------------------------------------------------- int VolZmap::GetPartCount( void) const { // Se mono-dexel la connessione è incalcolabile. if ( m_nMapNum == 1) return - 1 ; // Se il numero delle componenti è indefinito // lo ricalcolo e restituisco il risultato. if ( m_nConnectedCompoCount == - 1) { const_cast(this)->CheckMapConnection() ; return m_nConnectedCompoCount ; } // Altrimenti restituisco direttamente il numero di componenti. else return m_nConnectedCompoCount ; } //---------------------------------------------------------------------------- bool VolZmap::CheckMapConnection( void) { // Imposto il numero di componenti connesse a 0 m_nConnectedCompoCount = 0 ; // Imposto a 0 tutti il valore del numero della componente // connessa di ciascun tratto di ciascun dexel. for ( size_t tMap = 0 ; tMap < m_nMapNum ; ++ tMap) { for ( size_t tDex = 0 ; tDex < m_nDim[tMap] ; ++ tDex) { for ( size_t tInt = 0 ; tInt < m_Values[tMap][tDex].size() ; ++ tInt) { m_Values[tMap][tDex][tInt].nCompo = 0 ; // Controlli sui tratti di dexel non incidenti su nodi del reticolo if ( tMap == 0) { // Z degli estremi del segmento double dZMin = m_Values[tMap][tDex][tInt].dMin ; double dZMax = m_Values[tMap][tDex][tInt].dMax ; // Indici k dei voxels in cui cadono le Z int nKmin = int( floor( ( dZMin - EPS_SMALL) / m_dStep - 0.5)) ; int nKmax = int( floor( ( dZMax + EPS_SMALL) / m_dStep - 0.5)) ; // Se cadono nello stesso voxel imposto a -1 il valore della componente connessa if ( nKmax - nKmin == 0) m_Values[tMap][tDex][tInt].nCompo = -1 ; } else if ( tMap == 1) { // X degli estremi del segmento double dXMin = m_Values[tMap][tDex][tInt].dMin ; double dXMax = m_Values[tMap][tDex][tInt].dMax ; // Indici i dei voxels in cui cadono le X int nImin = int( floor( ( dXMin - EPS_SMALL) / m_dStep - 0.5)) ; int nImax = int( floor( ( dXMax + EPS_SMALL) / m_dStep - 0.5)) ; // Se cadono nello stesso voxel imposto a -1 il valore della componente connessa if ( nImax - nImin == 0) m_Values[tMap][tDex][tInt].nCompo = -1 ; } else { // Y degli estremi del segmento double dYMin = m_Values[tMap][tDex][tInt].dMin ; double dYMax = m_Values[tMap][tDex][tInt].dMax ; // Indici j dei voxels in cui cadono le X int nJmin = int( floor( ( dYMin - EPS_SMALL) / m_dStep - 0.5)) ; int nJmax = int( floor( ( dYMax + EPS_SMALL) / m_dStep - 0.5)) ; // Se cadono nello stesso voxel imposto a -1 il valore della componente connessa if ( nJmax - nJmin == 0) m_Values[tMap][tDex][tInt].nCompo = -1 ; } } } } // Ciclo sui dexel lungo Z for ( size_t tI = 0 ; tI < m_nNx[0] ; ++ tI) { for ( size_t tJ = 0 ; tJ < m_nNy[0] ; ++ tJ) { // Numero del dexel lungo Z size_t tDexZ = tJ * m_nNx[0] + tI ; // Numero di intervalli nel dexel size_t tStopIntZ = m_Values[0][tDexZ].size() ; // Ciclo sugli intervalli del dexel for ( size_t tIntZ = 0 ; tIntZ < tStopIntZ ; ++ tIntZ) { if ( m_Values[0][tDexZ][tIntZ].nCompo == 0) { ++ m_nConnectedCompoCount ; m_Values[0][tDexZ][tIntZ].nCompo = m_nConnectedCompoCount ; // Espando in tutta la componente // Segmento corrente IntervalIndexes NewInt ; NewInt.tMap = 0 ; NewInt.tDex = tJ * m_nNx[0] + tI ; NewInt.tInt = tIntZ ; // Stack di segmenti IntContaier IntervalsToProcess ; // Aggiungo il segmento corrente IntervalsToProcess.push( NewInt) ; // Processo gli intervalli trovati while ( ! IntervalsToProcess.empty()) { switch ( IntervalsToProcess.top().tMap) { case 0 : ExpandFromZInterval( IntervalsToProcess) ; break ; case 1 : ExpandFromXInterval( IntervalsToProcess) ; break ; case 2 : ExpandFromYInterval( IntervalsToProcess) ; break ; } } } // Se l'intervallo non attraversa un nodo o ha già // un indice assegnato salto questa iterazione. else continue ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::ExpandFromXInterval( IntContaier& IntCont) { // Copio i dati dell'intervallo corrente IntervalIndexes CurrInterval = IntCont.top() ; IntCont.pop() ; size_t tDex = CurrInterval.tDex ; size_t tGrIndex1 = CurrInterval.tDex % m_nNx[1] ; size_t tGrIndex2 = CurrInterval.tDex / m_nNx[1] ; size_t tInt = CurrInterval.tInt ; // Quote estreme del segmento lungo X double dMinX = m_Values[1][tDex][tInt].dMin ; double dMaxX = m_Values[1][tDex][tInt].dMax ; double dMinDX = max( floor( ( dMinX - EPS_SMALL) / m_dStep - 0.5), 0.) ; double dMaxDX = max( floor( ( dMaxX + EPS_SMALL) / m_dStep - 0.5), 0.) ; // Indici estremi dei dei dexel ortogonali // che possono intersecare il segmento di partenza size_t tStartI = min( size_t( dMinDX), size_t( m_nNx[0] - 1)) ; size_t tStopI = min( size_t( dMaxDX), size_t( m_nNx[0] - 1)) ; // Posizione YZ del dexel double dY = ( tGrIndex1 + 0.5) * m_dStep ; double dZ = ( tGrIndex2 + 0.5) * m_dStep ; // Ciclo sugli indici dei dexel che potrebbero // intersecare il segmento di partenza for ( size_t tI = tStartI ; tI <= tStopI ; ++ tI) { // Analizzo i dexel della griglia 0. size_t tStopZ = m_Values[0][tGrIndex1 * m_nNx[0] + tI].size() ; for ( size_t tIntZ = 0 ; tIntZ < tStopZ ; ++ tIntZ) { // Estremi del dexel lunog Z double dZmin = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMin ; double dZmax = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dZmin - EPS_SMALL < dZ && dZmax + EPS_SMALL > dZ && m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].nCompo == 0) { m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].nCompo = m_Values[1][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 0 ; NewInterval.tDex = tGrIndex1 * m_nNx[0] + tI ; NewInterval.tInt = tIntZ ; IntCont.push( NewInterval) ; } } // Analizzo i dexel della griglia 2 size_t tStopY = m_Values[2][tI * m_nNx[2] + tGrIndex2].size() ; for ( size_t tIntY = 0 ; tIntY < tStopY ; ++ tIntY) { // Estremi del segmento del dexel lungo Y double dYmin = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMin ; double dYmax = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dYmin - EPS_SMALL < dY && dYmax + EPS_SMALL > dY && m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].nCompo == 0) { m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].nCompo = m_Values[1][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 2 ; NewInterval.tDex = tI * m_nNx[2] + tGrIndex2 ; NewInterval.tInt = tIntY ; IntCont.push( NewInterval) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::ExpandFromYInterval( IntContaier& IntCont) { // Copio i dati dell'intervallo corrente IntervalIndexes CurrInterval = IntCont.top() ; IntCont.pop() ; size_t tDex = CurrInterval.tDex ; size_t tGrIndex1 = CurrInterval.tDex % m_nNx[2] ; size_t tGrIndex2 = CurrInterval.tDex / m_nNx[2] ; size_t tInt = CurrInterval.tInt ; // Quote estreme del segmento lungo Y double dMinY = m_Values[2][tDex][tInt].dMin ; double dMaxY = m_Values[2][tDex][tInt].dMax ; double dMinDY = max( floor( ( dMinY - EPS_SMALL) / m_dStep - 0.5), 0.) ; double dMaxDY = max( floor( ( dMaxY + EPS_SMALL) / m_dStep - 0.5), 0.) ; // Indici estremi dei dei dexel ortogonali // che possono intersecare il segmento di partenza size_t tStartJ = min( size_t( dMinDY), size_t( m_nNy[0] - 1)) ; size_t tStopJ = min( size_t( dMaxDY), size_t( m_nNy[0] - 1)) ; // Posizione XZ del dexel double dX = ( tGrIndex2 + 0.5) * m_dStep ; double dZ = ( tGrIndex1 + 0.5) * m_dStep ; // Ciclo sugli indici dei dexel che potrebbero // intersecare il segmento di partenza for ( size_t tJ = tStartJ ; tJ <= tStopJ ; ++ tJ) { // Analizzo i dexel della griglia 0. size_t tStopZ = m_Values[0][tJ * m_nNx[0] + tGrIndex2].size() ; for ( size_t tIntZ = 0 ; tIntZ < tStopZ ; ++ tIntZ) { // Estremi del dexel lunog Z double dZmin = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMin ; double dZmax = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dZmin - EPS_SMALL < dZ && dZmax + EPS_SMALL > dZ && m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].nCompo == 0) { m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].nCompo = m_Values[2][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 0 ; NewInterval.tDex = tJ * m_nNx[0] + tGrIndex2 ; NewInterval.tInt = tIntZ ; IntCont.push( NewInterval) ; } } // Analizzo i dexel della griglia 1 size_t tStopX = m_Values[1][tGrIndex1 * m_nNx[1] + tJ].size() ; for ( size_t tIntX = 0 ; tIntX < tStopX ; ++ tIntX) { // Estremi del segmento del dexel lungo X double dXmin = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMin ; double dXmax = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dXmin - EPS_SMALL < dX && dXmax + EPS_SMALL > dX && m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].nCompo == 0) { m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].nCompo = m_Values[2][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 1 ; NewInterval.tDex = tGrIndex1 * m_nNx[1] + tJ ; NewInterval.tInt = tIntX ; IntCont.push( NewInterval) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::ExpandFromZInterval( IntContaier& IntCont) { // Copio i dati dell'intervallo corrente IntervalIndexes CurrInterval = IntCont.top() ; IntCont.pop() ; size_t tDex = CurrInterval.tDex ; size_t tGrIndex1 = CurrInterval.tDex % m_nNx[0] ; size_t tGrIndex2 = CurrInterval.tDex / m_nNx[0] ; size_t tInt = CurrInterval.tInt ; // Quote estreme del segmento lungo Z double dMinZ = m_Values[0][tDex][tInt].dMin ; double dMaxZ = m_Values[0][tDex][tInt].dMax ; double dMinDZ = max( floor( ( dMinZ - EPS_SMALL) / m_dStep - 0.5), 0.) ; double dMaxDZ = max( floor( ( dMaxZ + EPS_SMALL) / m_dStep - 0.5), 0.) ; // Indici estremi dei dexel ortogonali // che possono intersecare il segmento di partenza size_t tStartK = min( size_t( dMinDZ), size_t( m_nNy[1] - 1)) ; size_t tStopK = min( size_t( dMaxDZ), size_t( m_nNy[1] - 1)) ; // Posizione XY del dexel double dX = ( tGrIndex1 + 0.5) * m_dStep ; double dY = ( tGrIndex2 + 0.5) * m_dStep ; // Ciclo sugli indici dei dexel che potrebbero // intersecare il segmento di partenza for ( size_t tK = tStartK ; tK <= tStopK ; ++ tK) { // Analizzo i dexel della griglia 1. size_t tStopX = m_Values[1][tK * m_nNx[1] + tGrIndex2].size() ; for ( size_t tIntX = 0 ; tIntX < tStopX ; ++ tIntX) { // Estremi del segmento del dexel lungo X double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ; double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dXmin - EPS_SMALL < dX && dXmax + EPS_SMALL > dX && m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo == 0) { m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo = m_Values[0][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 1 ; NewInterval.tDex = tK * m_nNx[1] + tGrIndex2 ; NewInterval.tInt = tIntX ; IntCont.push( NewInterval) ; } } // Analizzo i dexel della griglia 2 size_t tStopY = m_Values[2][tGrIndex1 * m_nNx[2] + tK].size() ; for ( size_t tIntY = 0 ; tIntY < tStopY ; ++ tIntY) { // Estremi del segmento del dexel lungo Y double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ; double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ; // Se i segmenti si incrociano e il nuovo trovato non // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dYmin - EPS_SMALL < dY && dYmax + EPS_SMALL > dY && m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo == 0) { m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo = m_Values[0][tDex][tInt].nCompo ; IntervalIndexes NewInterval ; NewInterval.tMap = 2 ; NewInterval.tDex = tGrIndex1 * m_nNx[2] + tK ; NewInterval.tInt = tIntY ; IntCont.push( NewInterval) ; } } } return true ; } //---------------------------------------------------------------------------- VolZmap* VolZmap::ClonePart( int nPart) const { // verifico lo stato if ( m_nStatus != OK) return nullptr ; // Se è definita una sola griglia non sono definibili le parti, errore if ( m_nMapNum == 1) return nullptr ; // Se è richiesta una componente fuori intervallo, errore if ( nPart < 0 || nPart >= m_nConnectedCompoCount) return nullptr ; // Se il numero di componenti è indefinito, lo ricalcolo. if ( m_nConnectedCompoCount == - 1) const_cast(this)->CheckMapConnection() ; // Se non vi sono componenti, errore if ( m_nConnectedCompoCount == 0) return nullptr ; // Creo nuovo oggetto Zmap PtrOwner pVolume( CreateBasicVolZmap()) ; if ( IsNull( pVolume)) return nullptr ; // Setto per il nuovo Zmap le seguenti variabili pVolume->m_nConnectedCompoCount = 1 ; pVolume->m_dStep = m_dStep ; pVolume->m_nMapNum = m_nMapNum ; // Minimi e massimi indici i,j della componente per le tre griglie int nMinIndI[N_MAPS] ; int nMaxIndI[N_MAPS] ; int nMinIndJ[N_MAPS] ; int nMaxIndJ[N_MAPS] ; // Coordinate dell'origine del sistema di riferimento // del nuovo Zmap double dNewOx, dNewOy, dNewOz ; // Ciclo sulle mappe for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { nMinIndI[nMap] = m_nNx[nMap] ; nMinIndJ[nMap] = m_nNy[nMap] ; nMaxIndI[nMap] = 0 ; nMaxIndJ[nMap] = 0 ; pVolume->m_dMinZ[nMap] = m_dMaxZ[nMap] ; pVolume->m_dMaxZ[nMap] = m_dMinZ[nMap] ; // Della componente connessa in questione calcolo indici i e j massimi e minimi. // Inoltre cerco la minima e massima Z. for ( int nIndI = 0 ; nIndI < int( m_nNx[nMap]) ; ++ nIndI) { for ( int nIndJ = 0 ; nIndJ < int( m_nNy[nMap]) ; ++ nIndJ) { int nDex = nIndJ * m_nNx[nMap] + nIndI ; for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) { if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) { if ( nIndI < nMinIndI[nMap]) nMinIndI[nMap] = nIndI ; if ( nIndJ < nMinIndJ[nMap]) nMinIndJ[nMap] = nIndJ ; if ( nIndI > nMaxIndI[nMap]) nMaxIndI[nMap] = nIndI ; if ( nIndJ > nMaxIndJ[nMap]) nMaxIndJ[nMap] = nIndJ ; if ( m_Values[nMap][nDex][nInt].dMin < pVolume->m_dMinZ[nMap]) pVolume->m_dMinZ[nMap] = m_Values[nMap][nDex][nInt].dMin ; if ( m_Values[nMap][nDex][nInt].dMax > pVolume->m_dMaxZ[nMap]) pVolume->m_dMaxZ[nMap] = m_Values[nMap][nDex][nInt].dMax ; } } } } } for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { if ( nMinIndI[nMap] > 0) -- nMinIndI[nMap] ; if ( nMaxIndI[nMap] < int( m_nNx[nMap]) - 1) ++ nMaxIndI[nMap] ; if ( nMinIndJ[nMap] > 0) -- nMinIndJ[nMap] ; if ( nMaxIndJ[nMap] < int( m_nNy[nMap]) - 1) ++ nMaxIndJ[nMap] ; pVolume->m_nNx[nMap] = nMaxIndI[nMap] - nMinIndI[nMap] + 1 ; pVolume->m_nNy[nMap] = nMaxIndJ[nMap] - nMinIndJ[nMap] + 1 ; pVolume->m_nDim[nMap] = pVolume->m_nNx[nMap] * pVolume->m_nNy[nMap] ; pVolume->m_Values[nMap].resize( pVolume->m_nDim[nMap]) ; } // Copio gli intervalli nelle griglie del nuovo oggetto: // Griglia 0 for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[0]) ; ++ nIndJ) { for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[0]) ; ++ nIndI) { int nNewDex = nIndJ * pVolume->m_nNx[0] + nIndI ; int nOldDex = ( nIndJ + nMinIndJ[0]) * m_nNx[0] + nIndI + nMinIndI[0] ; for ( int nInt = 0 ; nInt < int( m_Values[0][nOldDex].size()) ; ++ nInt) { if ( m_Values[0][nOldDex][nInt].nCompo == nPart + 1) { pVolume->m_Values[0][nNewDex].emplace_back( m_Values[0][nOldDex][nInt]) ; pVolume->m_Values[0][nNewDex].back().nCompo = 1 ; } } } } // Griglia 1 for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[1]) ; ++ nIndJ) { for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[1]) ; ++ nIndI) { int nNewDex = nIndJ * pVolume->m_nNx[1] + nIndI ; int nOldDex = ( nIndJ + nMinIndJ[1]) * m_nNx[1] + nIndI + nMinIndI[1] ; for ( int nInt = 0 ; nInt < int( m_Values[1][nOldDex].size()) ; ++ nInt) { if ( m_Values[1][nOldDex][nInt].nCompo == nPart + 1) { pVolume->m_Values[1][nNewDex].emplace_back( m_Values[1][nOldDex][nInt]) ; pVolume->m_Values[1][nNewDex].back().nCompo = 1 ; } } } } // Griglia 2 for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[2]) ; ++ nIndJ) { for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[2]) ; ++ nIndI) { int nNewDex = nIndJ * pVolume->m_nNx[2] + nIndI ; int nOldDex = ( nIndJ + nMinIndJ[2]) * m_nNx[2] + nIndI + nMinIndI[2] ; for ( int nInt = 0 ; nInt < int( m_Values[2][nOldDex].size()) ; ++ nInt) { if ( m_Values[2][nOldDex][nInt].nCompo == nPart + 1) { pVolume->m_Values[2][nNewDex].emplace_back( m_Values[2][nOldDex][nInt]) ; pVolume->m_Values[2][nNewDex].back().nCompo = 1 ; } } } } // Coordinate x,y dell'origine del sistema di riferimento dNewOx = nMinIndI[0] * m_dStep ; dNewOy = nMinIndJ[0] * m_dStep ; dNewOz = nMinIndJ[1] * m_dStep ; // Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali, // infatti i sistemi di riferimento in gioco differiscono al più per una traslazione. for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { // Quote estreme Z switch ( nMap) { case 0 : pVolume->m_dMinZ[nMap] -= dNewOz ; pVolume->m_dMaxZ[nMap] -= dNewOz ; break ; case 1 : pVolume->m_dMinZ[nMap] -= dNewOx ; pVolume->m_dMaxZ[nMap] -= dNewOx ; break ; case 2 : pVolume->m_dMinZ[nMap] -= dNewOy ; pVolume->m_dMaxZ[nMap] -= dNewOy ; break ; } // Dexel for ( int nDex = 0 ; nDex < int( pVolume->m_nDim[nMap]) ; ++ nDex) { for ( int nInt = 0 ; nInt < int( pVolume->m_Values[nMap][nDex].size()) ; ++ nInt) { switch ( nMap) { case 0 : pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOz ; pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOz ; break ; case 1 : pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOx ; pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOx ; break ; case 2 : pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOy ; pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOy ; break ; } } } } // Calcolo il numero di voxel lungo x,y e z unsigned int nVoxNumX = pVolume->m_nNx[0] / pVolume->N_DEXVOXRATIO + ( pVolume->m_nNx[0] % pVolume->N_DEXVOXRATIO == 0 ? 1 : 2) ; unsigned int nVoxNumY = pVolume->m_nNy[0] / pVolume->N_DEXVOXRATIO + ( pVolume->m_nNy[0] / pVolume->N_DEXVOXRATIO == 0 ? 1 : 2) ; unsigned int nVoxNumZ = pVolume->m_nNy[1] / pVolume->N_DEXVOXRATIO + ( pVolume->m_nNy[1] % pVolume->N_DEXVOXRATIO == 0 ? 1 : 2) ; // Definisco il numero di blocchi lungo x,y e z pVolume->m_nFracLin[0] = max( 1u, nVoxNumX / pVolume->m_nVoxNumPerBlock + ( nVoxNumX % pVolume->m_nVoxNumPerBlock >= pVolume->m_nVoxNumPerBlock / 2 ? 1 : 0)) ; pVolume->m_nFracLin[1] = max( 1u, nVoxNumY / pVolume->m_nVoxNumPerBlock + ( nVoxNumY % pVolume->m_nVoxNumPerBlock >= pVolume->m_nVoxNumPerBlock / 2 ? 1 : 0)) ; pVolume->m_nFracLin[2] = max( 1u, nVoxNumZ / pVolume->m_nVoxNumPerBlock + ( nVoxNumZ % pVolume->m_nVoxNumPerBlock >= pVolume->m_nVoxNumPerBlock / 2 ? 1 : 0)) ; // Dimensiono il vettore dei blocchi pVolume->m_nNumBlock = pVolume->m_nFracLin[0] * pVolume->m_nFracLin[1] * pVolume->m_nFracLin[2] ; pVolume->m_BlockToUpdate.resize( pVolume->m_nNumBlock) ; // Setto tutti i blocchi come da aggiornare per la grafica for ( unsigned int nCount = 0 ; nCount < pVolume->m_nNumBlock ; ++ nCount) pVolume->m_BlockToUpdate[nCount] = true ; // Dimensiono raccolta triangoli di feature tra blocchi pVolume->m_InterBlockTria.resize( pVolume->m_nNumBlock) ; // Sistema di riferimento intrinseco del nuovo solido Point3d ptNewO( dNewOx, dNewOy, dNewOz) ; pVolume->m_MapFrame.Set( ptNewO, X_AX, Y_AX, Z_AX) ; // Setto lo stato del nuovo Solido pVolume->m_nStatus = m_nStatus ; // Restituisco il nuovo solido return Release( pVolume) ; } //---------------------------------------------------------------------------- bool VolZmap::RemovePart( int nPart) { // verifico lo stato if ( m_nStatus != OK) return false ; // Se è definita una sola griglia non sono definibili le parti, errore if ( m_nMapNum == 1) return false ; // Se il numero di componenti è indefinito, lo ricalcolo if ( m_nConnectedCompoCount == - 1) CheckMapConnection() ; // Se non vi sono componenti, abbiamo finito if ( m_nConnectedCompoCount == 0) return true ; // Elimino i segmenti con indice nPart + 1 e aggiorno quelli con indice superiore // Ciclo sulle mappe. for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { // Ciclo sui dexel della mappa. for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) { // Ciclo sugli intervalli del dexel. for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) { // Se l'intervallo appartiene alla componente da eliminare, lo cancello. if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) { m_Values[nMap][nDex].erase( m_Values[nMap][nDex].begin() + nInt) ; -- nInt ; } else if ( m_Values[nMap][nDex][nInt].nCompo > nPart + 1) m_Values[nMap][nDex][nInt].nCompo -= 1 ; } } } // Decremento il numero di componenti. m_nConnectedCompoCount -= 1 ; // Imposto ricalcolo grafica m_OGrMgr.Reset() ; return true ; }