//---------------------------------------------------------------------------- // 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/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EgtNumUtils.h" using namespace std ; //---------------------------------------------------------------------------- GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ; //---------------------------------------------------------------------------- VolZmap::VolZmap(void) : m_nStatus( TO_VERIFY), m_nMapNum( 0), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_dStep( 10.0), m_nVoxNumPerBlock( N_VOXBLOCK), m_nShape( GENERIC), m_nTempProp( 0), m_Tool( true) { 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 ; } m_Tool.SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ; } //---------------------------------------------------------------------------- VolZmap::~VolZmap( void) { } //---------------------------------------------------------------------------- bool VolZmap::Clear( void) { m_nStatus = TO_VERIFY ; m_nMapNum = 0 ; m_nShape = GENERIC ; 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_nTempProp = 0 ; m_Tool.Clear() ; // 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_nShape = vzmSrc.m_nShape ; 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 = vzmSrc.m_BlockToUpdate ; m_BlockUpdatingCounter = vzmSrc.m_BlockUpdatingCounter ; m_InterBlockVox = vzmSrc.m_InterBlockVox ; m_InterBlockOriginalSharpTria = vzmSrc.m_InterBlockOriginalSharpTria ; m_InterBlockSharpTria = vzmSrc.m_InterBlockSharpTria ; m_BlockSharpTria = vzmSrc.m_BlockSharpTria ; m_BlockSmoothTria = vzmSrc.m_BlockSmoothTria ; m_BlockBigTria = vzmSrc.m_BlockBigTria ; m_SingleMapTria = vzmSrc.m_SingleMapTria ; m_SliceXY = vzmSrc.m_SliceXY ; m_SliceXZ = vzmSrc.m_SliceXZ ; m_SliceYZ = vzmSrc.m_SliceYZ ; // imposto ricalcolo grafica ResetGraphics() ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::ResetGraphics( void) { m_OGrMgr.Reset() ; for ( 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 ; // forma switch ( m_nShape) { default : sOut += "Shape=generic" ; break ; case BOX : sOut += "Shape=box" ; break ; case EXTRUSION : sOut += "Shape=extrusion" ; break ; } sOut += 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 ( 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 ; // forma if ( ! ngeOut.WriteInt( m_nShape, ";", 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 ( 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 ( int i = 0 ; i < m_nMapNum ; ++ i) { // ciclo sui dexel for ( int j = 0 ; j < m_nDim[i] ; ++ j) { // numero di estremi int nDim = 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 ( 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 ; // da versione 1014 : aggiunto flag Shape if ( ngeIn.GetFileVersion() >= NGE_VER_1014) { if ( ! ngeIn.ReadInt( m_nShape, ";", 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 ( 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 ( int i = 0 ; i < m_nMapNum ; ++ i) { // dimensiono i vettori m_Values[i].resize( m_nDim[i]) ; // ciclo sui dexel for ( int j = 0 ; j < m_nDim[i] ; ++ j) { // leggo il numero di estremi nel dexel 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 ( 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, true) ; m_BlockUpdatingCounter.resize( m_nNumBlock + ( m_nMapNum == 1 ? 0 : 1), 0) ; // per triangoli di feature di frontiera tra blocchi m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockOriginalSharpTria.resize( m_nNumBlock) ; m_InterBlockSharpTria.resize( m_nNumBlock) ; m_BlockSharpTria.resize( m_nNumBlock) ; m_BlockSmoothTria.resize( m_nNumBlock) ; m_BlockBigTria.resize( m_nNumBlock) ; m_SingleMapTria.resize( m_nNumBlock) ; m_SliceXY.resize( m_nNumBlock) ; m_SliceXZ.resize( m_nNumBlock) ; m_SliceYZ.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 ( int j = 0 ; j <= m_nNy[0] ; ++ j) { int 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 ( int i = 0 ; i <= m_nNx[0] ; ++ i) { int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ; int 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 ( int j = 0 ; j <= m_nNy[0] ; ++ j) { int 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 ( int i = 0 ; i <= m_nNx[0] ; ++ i) { int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] -1) ; int 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 ( int tMap = 0 ; tMap < m_nMapNum ; ++ tMap) { for ( int tDex = 0 ; tDex < m_nDim[tMap] ; ++ tDex) { for ( int tInt = 0 ; tInt < int( 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 ( int tI = 0 ; tI < m_nNx[0] ; ++ tI) { for ( int tJ = 0 ; tJ < m_nNy[0] ; ++ tJ) { // Numero del dexel lungo Z int tDexZ = tJ * m_nNx[0] + tI ; // Numero di intervalli nel dexel int tStopIntZ = int( m_Values[0][tDexZ].size()) ; // Ciclo sugli intervalli del dexel for ( int 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() ; int tDex = CurrInterval.tDex ; int tGrIndex1 = CurrInterval.tDex % m_nNx[1] ; int tGrIndex2 = CurrInterval.tDex / m_nNx[1] ; int 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 int tStartI = min( int( dMinDX), ( m_nNx[0] - 1)) ; int tStopI = min( int( dMaxDX), ( 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 ( int tI = tStartI ; tI <= tStopI ; ++ tI) { // Analizzo i dexel della griglia 0. int tStopZ = int( m_Values[0][tGrIndex1 * m_nNx[0] + tI].size()) ; for ( int 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 int tStopY = int( m_Values[2][tI * m_nNx[2] + tGrIndex2].size()) ; for ( int 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() ; int tDex = CurrInterval.tDex ; int tGrIndex1 = CurrInterval.tDex % m_nNx[2] ; int tGrIndex2 = CurrInterval.tDex / m_nNx[2] ; int 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 int tStartJ = min( int( dMinDY), ( m_nNy[0] - 1)) ; int tStopJ = min( int( dMaxDY), ( 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 ( int tJ = tStartJ ; tJ <= tStopJ ; ++ tJ) { // Analizzo i dexel della griglia 0. int tStopZ = int( m_Values[0][tJ * m_nNx[0] + tGrIndex2].size()) ; for ( int 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 int tStopX = int( m_Values[1][tGrIndex1 * m_nNx[1] + tJ].size()) ; for ( int 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() ; int tDex = CurrInterval.tDex ; int tGrIndex1 = CurrInterval.tDex % m_nNx[0] ; int tGrIndex2 = CurrInterval.tDex / m_nNx[0] ; int 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 int tStartK = min( int( dMinDZ), ( m_nNy[1] - 1)) ; int tStopK = min( int( dMaxDZ), ( 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 ( int tK = tStartK ; tK <= tStopK ; ++ tK) { // Analizzo i dexel della griglia 1. int tStopX = int( m_Values[1][tK * m_nNx[1] + tGrIndex2].size()) ; for ( int 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 int tStopY = int( m_Values[2][tGrIndex1 * m_nNx[2] + tK].size()) ; for ( int 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 int nVoxNumX = pVolume->m_nNx[0] / pVolume->N_DEXVOXRATIO + ( pVolume->m_nNx[0] % pVolume->N_DEXVOXRATIO == 0 ? 1 : 2) ; int nVoxNumY = pVolume->m_nNy[0] / pVolume->N_DEXVOXRATIO + ( pVolume->m_nNy[0] % pVolume->N_DEXVOXRATIO == 0 ? 1 : 2) ; 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( 1, nVoxNumX / pVolume->m_nVoxNumPerBlock + ( nVoxNumX % pVolume->m_nVoxNumPerBlock >= pVolume->m_nVoxNumPerBlock / 2 ? 1 : 0)) ; pVolume->m_nFracLin[1] = max( 1, nVoxNumY / pVolume->m_nVoxNumPerBlock + ( nVoxNumY % pVolume->m_nVoxNumPerBlock >= pVolume->m_nVoxNumPerBlock / 2 ? 1 : 0)) ; pVolume->m_nFracLin[2] = max( 1, 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, true) ; // Dimensiono il vettore dei contatori degli aggiornamenti della grafica dei blocchi pVolume->m_BlockUpdatingCounter.resize( pVolume->m_nNumBlock + 1, 0) ; // Dimensiono raccolta di voxel di confine pVolume->m_InterBlockVox.resize( pVolume->m_nNumBlock) ; // Dimensiono raccolta triangoli di feature tra blocchi pVolume->m_InterBlockOriginalSharpTria.resize( pVolume->m_nNumBlock) ; pVolume->m_BlockSharpTria.resize( pVolume->m_nNumBlock) ; pVolume->m_BlockSmoothTria.resize( pVolume->m_nNumBlock) ; pVolume->m_BlockBigTria.resize( pVolume->m_nNumBlock) ; pVolume->m_SliceXY.resize( pVolume->m_nNumBlock) ; pVolume->m_SliceXZ.resize( pVolume->m_nNumBlock) ; pVolume->m_SliceYZ.resize( pVolume->m_nNumBlock) ; // Sistema di riferimento intrinseco del nuovo solido Point3d ptNewO = m_MapFrame.Orig() + Vector3d( dNewOx, dNewOy, dNewOz) ; pVolume->m_MapFrame.Set( ptNewO, X_AX, Y_AX, Z_AX) ; // Determino la forma pVolume->m_nShape = ( pVolume->IsBox() ? BOX : GENERIC) ; // 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 < 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) { SetToModifyDexelBlocks( nMap, nDex, nInt) ; 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 ; } //---------------------------------------------------------------------------- bool VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) { // Controllo sulla validità della griglia if ( nGrid < 0 || nGrid > 2) return false ; // Controllo sulla validità del dexel if ( nDex <= - 1 || nDex >= int( m_Values[nGrid].size())) return false ; // Controllo sulla validità dell'intervallo if ( nInt <= - 1 || nInt >= int( m_Values[nGrid][nDex].size())) return false ; // Determino quali blocchi sono stati modificati int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ; // Indici del dexel int nI = nDex % m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ; // Quote estreme del dexel double dMin = m_Values[nGrid][nDex][nInt].dMin ; double dMax = m_Values[nGrid][nDex][nInt].dMax ; if ( nGrid == 0) { int nXStop = 1 ; int nYStop = 1 ; int nXBlock[2] ; int nYBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Numero di voxel lungo Z int nVoxNumZ = int( m_nNy[1] / N_DEXVOXRATIO + ( m_nNy[1] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ; int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nXStop ; ++ tI) { for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { int nBlockNum = k * nLayerBlock + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 1) { int nYStop = 1 ; int nZStop = 1 ; int nYBlock[2] ; int nZBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Numero di voxel lungo X int nVoxNumX = int( m_nNx[0] / N_DEXVOXRATIO + ( m_nNx[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ; int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ; int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nYStop ; ++ tI) { for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) { for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) { int nBlockNum = nZBlock[tJ] * nLayerBlock + nYBlock[tI] * m_nFracLin[0] + k ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 2) { int nXStop = 1 ; int nZStop = 1 ; int nXBlock[2] ; int nZBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Numero di voxel lungo Y int nVoxNumY = int( m_nNy[0] / N_DEXVOXRATIO + ( m_nNy[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ; int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ; int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nZStop ; ++ tI) { for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) { for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) { int nBlockNum = nZBlock[tI] * nLayerBlock + k * m_nFracLin[0] + nXBlock[tJ] ; m_BlockToUpdate[nBlockNum] = true ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IsBox( void) { for ( int nMap = 0 ; nMap < 3 ; ++ nMap) { double dMinZ = m_dMaxZ[nMap] ; double dMaxZ = m_dMinZ[nMap] ; for ( int n = 0 ; n < int( m_nDim[nMap]) ; ++ n) { int nSize = int( m_Values[nMap][n].size()) ; if ( nSize > 1) return false ; else if ( nSize > 0) { if ( dMinZ > dMaxZ) { dMinZ = m_Values[nMap][n][0].dMin ; dMaxZ = m_Values[nMap][n][0].dMax ; } else { if ( abs( m_Values[nMap][n][0].dMin - dMinZ) > EPS_SMALL || abs( m_Values[nMap][n][0].dMax - dMaxZ) > EPS_SMALL) return false ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Cut( const Plane3d& plPlane) { // Porto il piano nel riferimento intrinseco Plane3d plMyPlane = plPlane ; plMyPlane.ToLoc( m_MapFrame) ; // Imposto numero fittizio di utensile per avere il colore di sezione opportuno int nToolNumOld = m_Tool.GetCurrentToolNum() ; m_Tool.SetToolNum( 1) ; // Interseco lo Zmap col piano, ciclando sulle griglie bool bModified = false ; for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { // Porto il piano nel riferimento di griglia if ( nMap == 1) { Frame3d frGrid ; frGrid.Set( ORIG, Y_AX, Z_AX, X_AX) ; plMyPlane.ToLoc( frGrid) ; } else if (nMap == 2) { Frame3d frGrid ; frGrid.Set( ORIG, Y_AX, Z_AX, X_AX) ; plMyPlane.ToLoc( frGrid) ; } // Ciclo sui dexel della mappa for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) { // Se spillone già vuoto, passo al successivo if ( m_Values[nMap][nD].empty()) continue ; // Indici di spillone int nI = nD % m_nNx[nMap] ; int nJ = nD / m_nNx[nMap] ; // Recupero estremi spillone double dMin = m_Values[nMap][nD][0].dMin ; double dMax = m_Values[nMap][nD][m_Values[nMap][nD].size() - 1].dMax ; Point3d ptSt( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, dMin) ; Point3d ptEn( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, dMax) ; // Distanze degli estremi del segmento dal piano double dStDist = DistPointPlane( ptSt, plMyPlane) ; double dEnDist = DistPointPlane( ptEn, plMyPlane) ; // Se entrambi sotto il piano if ( dStDist < EPS_SMALL && dEnDist < EPS_SMALL) // Non devo fare alcunché ; // se altrimenti entrambi gli estremi sono oltre il piano else if ( dStDist > -EPS_SMALL && dEnDist > -EPS_SMALL) { // Si elimina tutto SubtractIntervals( nMap, nI, nJ, dMin, dMax, V_NULL, V_NULL) ; } // se altrimenti è da tenere il punto iniziale else if ( dStDist < 0) { // Si elimina la parte tra intersezione e punto finale double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ; SubtractIntervals( nMap, nI, nJ, dInt, dMax, plMyPlane.GetVersN(), V_NULL) ; } // se altrimenti è da tenere il punto finale else if (dEnDist < 0) { // Si elimina la parte tra punto iniziale e intersezione double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ; SubtractIntervals( nMap, nI, nJ, dMin, dInt, V_NULL, plMyPlane.GetVersN()) ; } } } // Ripristino numero utensile m_Tool.SetToolNum( nToolNumOld) ; if ( bModified == true) { // Imposto forma generica m_nShape = GENERIC ; // Imposto ricalcolo grafica m_OGrMgr.Reset() ; // Imposto numero di componenti connesse da ricalcolare m_nConnectedCompoCount = - 1 ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Compact( void) { // Determino i nuovi estremi sugli indici e sulle quote Z e copio i dexel i cui indici sono compresi fra gli estremi int nMinI[N_MAPS] ; int nMinJ[N_MAPS] ; int nMaxI[N_MAPS] ; int nMaxJ[N_MAPS] ; int nNx[N_MAPS] ; int nNy[N_MAPS] ; int nDim[N_MAPS] ; double dMinZ[N_MAPS] ; double dMaxZ[N_MAPS] ; vector> Values[N_MAPS] ; bool bNotEmptyGrid = true ; for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { nMinI[nMap] = m_nNx[nMap] - 1 ; nMinJ[nMap] = m_nNy[nMap] - 1 ; nMaxI[nMap] = 0 ; nMaxJ[nMap] = 0 ; dMinZ[nMap] = m_dMaxZ[nMap] ; dMaxZ[nMap] = m_dMinZ[nMap] ; // Determino estremi degli indici e delle quote Z for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) { int nDexDim = int( m_Values[nMap][nD].size()) ; if ( nDexDim > 0) { int nI = nD % m_nNx[nMap] ; int nJ = nD / m_nNx[nMap] ; if ( nI < nMinI[nMap]) nMinI[nMap] = nI ; if ( nJ < nMinJ[nMap]) nMinJ[nMap] = nJ ; if ( nI > nMaxI[nMap]) nMaxI[nMap] = nI ; if ( nJ > nMaxJ[nMap]) nMaxJ[nMap] = nJ ; if ( m_Values[nMap][nD][0].dMin < dMinZ[nMap]) dMinZ[nMap] = m_Values[nMap][nD][0].dMin ; if ( m_Values[nMap][nD][nDexDim - 1].dMax > dMaxZ[nMap]) dMaxZ[nMap] = m_Values[nMap][nD][nDexDim - 1].dMax ; } } if ( nMinI[nMap] > nMaxI[nMap] || nMinJ[nMap] > nMaxJ[nMap]) { bNotEmptyGrid = false ; break ; } // Se necessario espando la griglia if ( nMinI[nMap] > 0) -- nMinI[nMap] ; if ( nMinJ[nMap] > 0) -- nMinJ[nMap] ; if ( nMaxI[nMap] < int( m_nNx[nMap]) - 1) ++ nMaxI[nMap] ; if ( nMaxJ[nMap] < int( m_nNy[nMap]) - 1) ++ nMaxJ[nMap] ; nNx[nMap] = nMaxI[nMap] - nMinI[nMap] + 1 ; nNy[nMap] = nMaxJ[nMap] - nMinJ[nMap] + 1 ; nDim[nMap] = nNx[nMap] * nNy[nMap] ; // Copio i dexel i cui indici sono compresi fra gli estremi for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) { int nI = nD % m_nNx[nMap] ; int nJ = nD / m_nNx[nMap] ; if ( nI >= nMinI[nMap] && nI <= nMaxI[nMap] && nJ >= nMinJ[nMap] && nJ <= nMaxJ[nMap]) { Values[nMap].emplace_back( m_Values[nMap][nD]) ; } } } // Se non vi è materiale if ( ! bNotEmptyGrid) { m_nStatus = TO_VERIFY ; m_nNumBlock = 0 ; m_nConnectedCompoCount = 0 ; m_nShape = GENERIC ; 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 ; } return true ; } // Coordinate x,y dell'origine del sistema di riferimento double dNewOx = nMinI[0] * m_dStep ; double dNewOy = nMinJ[0] * m_dStep ; double dNewOz = nMinJ[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 : dMinZ[nMap] -= dNewOz ; dMaxZ[nMap] -= dNewOz ; break ; case 1 : dMinZ[nMap] -= dNewOx ; dMaxZ[nMap] -= dNewOx ; break ; case 2 : dMinZ[nMap] -= dNewOy ; dMaxZ[nMap] -= dNewOy ; break ; } // Dexel for ( int nD = 0 ; nD < int( nDim[nMap]) ; ++ nD) { for ( int nS = 0 ; nS < int( Values[nMap][nD].size()) ; ++ nS) { switch ( nMap) { case 0 : Values[nMap][nD][nS].dMin -= dNewOz ; Values[nMap][nD][nS].dMax -= dNewOz ; break ; case 1 : Values[nMap][nD][nS].dMin -= dNewOx ; Values[nMap][nD][nS].dMax -= dNewOx ; break ; case 2 : Values[nMap][nD][nS].dMin -= dNewOy ; Values[nMap][nD][nS].dMax -= dNewOy ; break ; } } } } // Ricopio i dexel con gli indici compresi fra gli estremi for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { m_nNx[nMap] = nNx[nMap] ; m_nNy[nMap] = nNy[nMap] ; m_nDim[nMap] = nDim[nMap] ; m_Values[nMap].resize( 0) ; for ( int nD = 0 ; nD < int( Values[nMap].size()) ; ++ nD) { m_Values[nMap].emplace_back( Values[nMap][nD]) ; } } // Calcolo il numero di voxel lungo x,y e z int nVoxNumX = m_nNx[0] / N_DEXVOXRATIO + ( m_nNx[0] % N_DEXVOXRATIO == 0 ? 1 : 2) ; int nVoxNumY = m_nNy[0] / N_DEXVOXRATIO + ( m_nNy[0] % N_DEXVOXRATIO == 0 ? 1 : 2) ; int nVoxNumZ = m_nNy[1] / N_DEXVOXRATIO + ( m_nNy[1] % N_DEXVOXRATIO == 0 ? 1 : 2) ; // Definisco il numero di blocchi lungo x,y e z m_nFracLin[0] = max( 1, nVoxNumX / m_nVoxNumPerBlock + ( nVoxNumX % m_nVoxNumPerBlock >= m_nVoxNumPerBlock / 2 ? 1 : 0)) ; m_nFracLin[1] = max( 1, nVoxNumY / m_nVoxNumPerBlock + ( nVoxNumY % m_nVoxNumPerBlock >= m_nVoxNumPerBlock / 2 ? 1 : 0)) ; m_nFracLin[2] = max( 1, nVoxNumZ / m_nVoxNumPerBlock + ( nVoxNumZ % m_nVoxNumPerBlock >= m_nVoxNumPerBlock / 2 ? 1 : 0)) ; // Dimensiono il vettore dei blocchi m_nNumBlock = m_nFracLin[0] * m_nFracLin[1] * m_nFracLin[2] ; m_BlockToUpdate.resize( m_nNumBlock, true) ; // Dimensiono il vettore dei contatori di aggiornamenti dei blocchi m_BlockUpdatingCounter.resize( m_nNumBlock, 0) ; // Dimensiono raccolta di voxel di confine m_InterBlockVox.resize( m_nNumBlock) ; // Dimensiono raccolta triangoli di feature tra blocchi m_InterBlockOriginalSharpTria.resize( m_nNumBlock) ; m_BlockSharpTria.resize( m_nNumBlock) ; m_BlockSmoothTria.resize( m_nNumBlock) ; m_BlockBigTria.resize( m_nNumBlock) ; m_SliceXY.resize( m_nNumBlock) ; m_SliceXZ.resize( m_nNumBlock) ; m_SliceYZ.resize( m_nNumBlock) ; // Sistema di riferimento intrinseco del nuovo solido Point3d ptNewO = m_MapFrame.Orig() + Vector3d( dNewOx, dNewOy, dNewOz) ; m_MapFrame.Set( ptNewO, X_AX, Y_AX, Z_AX) ; // Imposto ricalcolo grafica m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::SetTolerances( double dLinTol, double dAngTolDeg) { return m_Tool.SetTolerances( dLinTol, dAngTolDeg) ; } //---------------------------------------------------------------------------- bool VolZmap::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, int nFlag) { return m_Tool.SetStdTool( sToolName, dH, dR, dCornR, nFlag) ; } //---------------------------------------------------------------------------- bool VolZmap::SetAdvTool( const string& sToolName, double dH, double dR, double dTipH, double dTipR, double dCornR, int nFlag) { return m_Tool.SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, nFlag) ; } //---------------------------------------------------------------------------- bool VolZmap::SetSawTool( const string& sToolName, double dH, double dR, double dThick, double dStemR, double dCornR, int nFlag) { return m_Tool.SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ; } //---------------------------------------------------------------------------- bool VolZmap::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline, int nFlag) { return m_Tool.SetGenTool( sToolName, pToolOutline, nFlag) ; } //---------------------------------------------------------------------------- bool VolZmap::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag) { return m_Tool.SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ; } //---------------------------------------------------------------------------- bool VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nFlag) { return m_Tool.SetChiselTool( sToolName, dH, dW, dTh, nFlag) ; }