//---------------------------------------------------------------------------- // 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 "CurveLine.h" #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineSurfTm.h" #include "\EgtDev\Include\EgtNumUtils.h" using namespace std ; // ------------------------- CREAZIONE MAPPA -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dPrec, bool bFlag) { // Controlli l'ammissibilità delle dimensioni lineari del grezzo e del passo if ( dPrec < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL) return false ; // Aggiorno il passo m_dStep = dPrec ; // Aggiorno la dimensione della mappa 1 o 3 m_nMapNum = ( bFlag ? 3 : 1) ; // Disponendo i sistemi di riferimento in una successione, le coordinate x,y,z // di uno si ottengono da una permutazione ciclica di quelle del precedente sistema. // es: X(n) = Z(n-1), Y(n) = X(n-1), Z(n) = Y(n-1) // Definisco i sistemi di riferimento m_MapFrame[0].Set( ptO, X_AX, Y_AX, Z_AX) ; // Definisco i vettori dei limiti su indici m_nVNx[0] = static_cast ( ceil( dLengthX / m_dStep)) ; m_nVNy[0] = static_cast ( ceil( dLengthY / m_dStep)) ; if ( m_nMapNum > 1) { m_MapFrame[1].Set( ptO, Y_AX, Z_AX, X_AX) ; m_MapFrame[2].Set( ptO, Z_AX, X_AX, Y_AX) ; m_nVNx[1] = static_cast ( ceil( dLengthY / m_dStep)) ; m_nVNy[1] = static_cast ( ceil( dLengthZ / m_dStep)) ; m_nVNx[2] = static_cast ( ceil( dLengthZ / m_dStep)) ; m_nVNy[2] = static_cast ( ceil( dLengthX / m_dStep)) ; } else { m_MapFrame[1].Set( ptO, Y_AX, Z_AX, X_AX) ; m_MapFrame[2].Set( ptO, Z_AX, X_AX, Y_AX) ; m_nVNx[1] = 0 ; m_nVNy[1] = 0 ; m_nVNx[2] = 0 ; m_nVNy[2] = 0 ; } // Definizione della mappa // Creazione delle mappe // Calcolo del numero di celle per ogni mappa for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) m_nVDim[i] = m_nVNx[i] * m_nVNy[i] ; // Creazione delle celle per ogni mappa for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) m_TriZValues[i].resize( m_nVDim[i]) ; // Riempimento delle celle for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) for ( unsigned int j = 0 ; j < m_nVDim[i] ; ++ j) { m_TriZValues[i][j].resize(2) ; m_TriZValues[i][j][0] = 0 ; if ( i == 0) m_TriZValues[i][j][1] = dLengthZ ; else if ( i == 1) m_TriZValues[i][j][1] = dLengthX ; else if ( i == 2) m_TriZValues[i][j][1] = dLengthY ; } // Definizione delle limitazioni iniziali in Z per ogni mappa for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { m_dVMinZ[i] = 0 ; if ( i == 0) m_dVMaxZ[i] = dLengthZ ; else if ( i == 1) m_dVMaxZ[i] = dLengthX ; else if ( i == 2) m_dVMaxZ[i] = dLengthY ; } // Aggiornamento dello stato m_nStatus = OK ; return true ; } bool VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dPrec, bool bFlag) { Point3d ptMapOrig, ptMapEnd ; // Aggiorno la dimensione della mappa 1 o 3 m_nMapNum = ( bFlag ? 3 : 1) ; // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL m_dStep = max( dPrec, 100 * EPS_SMALL) ; // Determino il bounding box della flat region BBox3d SurfBBox ; Surf.GetLocalBBox( SurfBBox, BBF_EXACT) ; // Determino i punti estremi del bounding box SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ; // Sistema di riferimento mappa m_MapFrame[0].Set( ptMapOrig, X_AX, Y_AX, Z_AX) ; // Determino le dimensioni lineari X Y della griglia double dLengthX = ptMapEnd.x - ptMapOrig.x ; double dLengthY = ptMapEnd.y - ptMapOrig.y ; // A partire dalle dimensioni di xy del grezzo determino il numero di colonne e righe // della griglia Zmap e da questi la dimensione del vettore di dexel m_nVNx[0] = static_cast ( ceil( dLengthX / m_dStep)) ; m_nVNy[0] = static_cast ( ceil( dLengthY / m_dStep)) ; m_nVDim[0] = m_nVNx[0] * m_nVNy[0] ; // Ridimensiono il vettore di dexel e creo lo Zmap m_TriZValues[0].resize( m_nVDim[0]) ; // Se Tridexel ridimensiono anche gli altri vettori if ( bFlag) { m_MapFrame[1].Set( ptMapOrig, Y_AX, Z_AX, X_AX) ; m_MapFrame[2].Set( ptMapOrig, Z_AX, X_AX, Y_AX) ; m_nVNx[1] = static_cast ( ceil( dLengthY / m_dStep)) ; m_nVNy[1] = static_cast ( ceil( dDimZ / m_dStep)) ; m_nVDim[1] = m_nVNx[1] * m_nVNy[1] ; m_nVNx[2] = static_cast ( ceil( dDimZ / m_dStep)) ; m_nVNy[2] = static_cast ( ceil( dLengthX / m_dStep)) ; m_nVDim[2] = m_nVNx[2] * m_nVNy[2] ; m_TriZValues[1].resize( m_nVDim[1]) ; m_TriZValues[2].resize( m_nVDim[2]) ; } else { m_MapFrame[1].Set( ptMapOrig, Y_AX, Z_AX, X_AX) ; m_MapFrame[2].Set( ptMapOrig, Z_AX, X_AX, Y_AX) ; m_nVNx[1] = 0 ; m_nVNy[1] = 0 ; m_nVDim[1] = 0 ; m_nVNx[2] = 0 ; m_nVNy[2] = 0 ; m_nVDim[2] = 0 ; } // Determinazione e ridimensionamento dei dexel // interni alla regione // Griglia 0 for ( unsigned int i = 0 ; i < m_nVNx[0] ; ++ i) { // Definisco la retta da intersecare con la regione double dX = ( i + 0.5) * m_dStep ; Point3d ptP0 = ptMapOrig + Vector3d( dX, 0, 0) ; CurveLine GridLine ; GridLine.SetPVL( ptP0, Y_AX, dLengthY) ; // Determino le intersezioni della retta con la regione CRVCVECTOR IntersectionResults ; Surf.GetCurveClassification( GridLine, IntersectionResults) ; // Parti di cui la retta analizzata è composta int nPart = int( IntersectionResults.size()) ; // Analizzo le parti for ( int k = 0 ; k < nPart ; ++ k) { // Tipo di curva int nType = IntersectionResults[k].nClass ; // Parametri iniziale e finale double dt1 = IntersectionResults[k].dParS ; double dt2 = IntersectionResults[k].dParE ; // Se la retta è interna alla regione o coincidente con parte della sua frontiera if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { // Indici corrispondenti alle coordinate dei punti int nStartJ = Clamp( int( floor( dt1 * dLengthY / m_dStep + 0.5)), 0, m_nVNy[0] - 1) ; int nEndJ = Clamp( int( floor( dt2 * dLengthY / m_dStep - 0.5)), 0, m_nVNy[0] - 1) ; // Ridimensiono e riempio i dexel for ( int j = nStartJ ; j <= nEndJ ; ++ j) { // Determino il dexel int nPos0 = j * m_nVNx[0] + i ; m_TriZValues[0][nPos0].resize( 2) ; // Aggiorno le quote estreme del segmento m_TriZValues[0][nPos0][0] = 0 ; m_TriZValues[0][nPos0][1] = dDimZ ; } // Se tridexel riempio i singoli dexel della // griglia 2 con gli intervalli if ( bFlag) { for ( size_t a = 0 ; a < m_nVNx[2] ; ++ a) { size_t nPos2 = i * m_nVNx[2] + a ; size_t nCurrentSize = m_TriZValues[2][nPos2].size( ) ; m_TriZValues[2][nPos2].resize( nCurrentSize + 2) ; m_TriZValues[2][nPos2][nCurrentSize] = dt1 * dLengthY ; m_TriZValues[2][nPos2][nCurrentSize + 1] = dt2 * dLengthY ; } } } } } // Se tridexel resta la griglia 1 if ( bFlag) { for ( unsigned int i = 0 ; i < m_nVNx[1] ; ++ i) { // Definisco la retta da intersecare con la regione double dX = ( i + 0.5) * m_dStep ; Point3d ptP0 = ptMapOrig + Vector3d( 0, dX, 0) ; CurveLine GridLine ; GridLine.SetPVL( ptP0, X_AX, dLengthX) ; // Determino le intersezioni della retta con la regione CRVCVECTOR IntersectionResults ; Surf.GetCurveClassification( GridLine, IntersectionResults) ; // Parti di cui la retta analizzata è composta int nPart = int( IntersectionResults.size()) ; // Analizzo le parti for ( int k = 0 ; k < nPart ; ++ k) { // Tipo di curva int nType = IntersectionResults[k].nClass ; // Se la retta è interna alla regione o coincidente con parte della sua frontiera if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { // Parametri iniziale e finale double dt1 = IntersectionResults[k].dParS ; double dt2 = IntersectionResults[k].dParE ; for ( size_t j = 0 ; j < m_nVNy[1] ; ++ j) { size_t nPos1 = j * m_nVNx[1] + i ; size_t nCurrentSize = m_TriZValues[1][nPos1].size( ) ; m_TriZValues[1][nPos1].resize( nCurrentSize + 2) ; m_TriZValues[1][nPos1][nCurrentSize] = dt1 * dLengthX ; m_TriZValues[1][nPos1][nCurrentSize + 1] = dt2 * dLengthX ; } } } } } m_dVMinZ[0] = 0 ; m_dVMaxZ[0] = dDimZ ; if ( bFlag) { m_dVMinZ[1] = 0 ; m_dVMaxZ[1] = dLengthX ; m_dVMinZ[2] = 0 ; m_dVMaxZ[2] = dLengthY ; } else { m_dVMinZ[1] = 0 ; m_dVMaxZ[1] = 0 ; m_dVMinZ[2] = 0 ; m_dVMaxZ[2] = 0 ; } // Aggiornamento dello stato m_nStatus = OK ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dPrec, bool bFlag) { // Se la superficie non è chiusa non ha senso continuare if ( ! Surf.IsClosed()) return false ; // Aggiorno la dimensione della mappa 1 o 3 m_nMapNum = ( bFlag ? 3 : 1) ; // Determino il bounding box della TriMesh BBox3d SurfBBox ; Surf.GetLocalBBox( SurfBBox) ; // Determino i punti estremi del bounding box Point3d ptMapOrig, ptMapEnd ; SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ; // Sistema di riferimento mappa m_MapFrame[0].Set( ptMapOrig, Frame3d::TOP) ; // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL m_dStep = max( dPrec, 100 * EPS_SMALL) ; // Determino le dimensioni lineari del BBox double dLengthX = ptMapEnd.x - ptMapOrig.x ; double dLengthY = ptMapEnd.y - ptMapOrig.y ; double dLengthZ = ptMapEnd.z - ptMapOrig.z ; // A partire dalle dimensioni di xy del grezzo determino il numero di colonne e righe // della griglia Zmap e da questi la dimensione del vettore di dexel m_nVNx[0] = static_cast ( ceil( dLengthX / m_dStep)) ; m_nVNy[0] = static_cast ( ceil( dLengthY / m_dStep)) ; m_nVDim[0] = m_nVNx[0] * m_nVNy[0] ; // Ridimensiono il vettore di dexel e creo lo Zmap m_TriZValues[0].resize( m_nVDim[0]) ; // Se Tridexel ridimensiono anche gli altri vettori if ( bFlag) { m_MapFrame[1].Set( ptMapOrig, Y_AX, Z_AX, X_AX) ; // Sarà Front Left m_MapFrame[2].Set( ptMapOrig, Z_AX, X_AX, Y_AX) ; m_nVNx[1] = static_cast ( ceil( dLengthY / m_dStep)) ; m_nVNy[1] = static_cast ( ceil( dLengthZ / m_dStep)) ; m_nVDim[1] = m_nVNx[1] * m_nVNy[1] ; m_nVNx[2] = static_cast ( ceil( dLengthZ / m_dStep)) ; m_nVNy[2] = static_cast ( ceil( dLengthX / m_dStep)) ; m_nVDim[2] = m_nVNx[2] * m_nVNy[2] ; m_TriZValues[1].resize( m_nVDim[1]) ; m_TriZValues[2].resize( m_nVDim[2]) ; } // Oggetto per calcolo massivo intersezioni IntersParLinesSurfTm intPLSTM( m_MapFrame[0], Surf) ; // Determinazione e ridimensionamento dei dexel interni alla trimesh for ( unsigned int i = 0 ; i < m_nVNx[0] ; ++ i) { for ( unsigned int j = 0 ; j < m_nVNy[0] ; ++ j) { // Definisco la retta da intersecare con la trimesh double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptP0( dX, dY, 0) ; // Determino le intersezioni della retta con la TriMesh ILSIVECTOR IntersectionResults ; intPLSTM.GetInters( ptP0, dLengthZ, IntersectionResults) ; int nInt = int( IntersectionResults.size()) ; unsigned int nPos = j * m_nVNx[0] + i ; bool bInside = false ; Point3d ptIn ; for ( int k = 0 ; k < nInt ; ++ k) { int nIntType = IntersectionResults[k].nILTT ; // Se c'è intersezione if ( nIntType != ILTT_NO) { double dCos = IntersectionResults[k].dCosDN ; // entro nella superficie trimesh if ( dCos < - EPS_SMALL) { ptIn = IntersectionResults[k].ptI ; bInside = true ; } // esco dalla superficie trimesh else if ( dCos > EPS_SMALL && bInside) { Point3d ptOut = IntersectionResults[k].ptI ; unsigned int nCurrentSize = unsigned int( m_TriZValues[0][nPos].size()) ; m_TriZValues[0][nPos].resize( nCurrentSize + 2) ; m_TriZValues[0][nPos][nCurrentSize] = ptIn.z - ptMapOrig.z ; m_TriZValues[0][nPos][nCurrentSize + 1] = ptOut.z - ptMapOrig.z ; bInside = false ; } } } } } if ( bFlag) { IntersParLinesSurfTm intPLSTM1( m_MapFrame[1], Surf) ; // Determinazione e ridimensionamento dei dexel interni alla trimesh for ( unsigned int i = 0 ; i < m_nVNx[1] ; ++ i) { for ( unsigned int j = 0 ; j < m_nVNy[1] ; ++ j) { // Definisco la retta da intersecare con la trimesh double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptP0( dX, dY, 0) ; // Determino le intersezioni della retta con la TriMesh ILSIVECTOR IntersectionResults ; intPLSTM1.GetInters( ptP0, dLengthX, IntersectionResults) ; int nInt = int( IntersectionResults.size()) ; unsigned int nPos = j * m_nVNx[1] + i ; bool bInside = false ; Point3d ptIn ; for ( int k = 0 ; k < nInt ; ++ k) { int nIntType = IntersectionResults[k].nILTT ; // Se c'è intersezione if ( nIntType != ILTT_NO) { double dCos = IntersectionResults[k].dCosDN ; // entro nella superficie trimesh if ( dCos < - EPS_SMALL) { ptIn = IntersectionResults[k].ptI ; bInside = true ; } // esco dalla superficie trimesh else if ( dCos > EPS_SMALL && bInside) { Point3d ptOut = IntersectionResults[k].ptI ; unsigned int nCurrentSize = unsigned int( m_TriZValues[1][nPos].size()) ; m_TriZValues[1][nPos].resize( nCurrentSize + 2) ; m_TriZValues[1][nPos][nCurrentSize] = ptIn.x - ptMapOrig.x ; m_TriZValues[1][nPos][nCurrentSize + 1] = ptOut.x - ptMapOrig.x ; bInside = false ; } } } } } IntersParLinesSurfTm intPLSTM2( m_MapFrame[2], Surf) ; // Determinazione e ridimensionamento dei dexel interni alla trimesh for ( unsigned int i = 0 ; i < m_nVNx[2] ; ++ i) { for ( unsigned int j = 0 ; j < m_nVNy[2] ; ++ j) { // Definisco la retta da intersecare con la trimesh double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptP0( dX, dY, 0) ; // Determino le intersezioni della retta con la TriMesh ILSIVECTOR IntersectionResults ; intPLSTM2.GetInters( ptP0, dLengthY, IntersectionResults) ; int nInt = int( IntersectionResults.size()) ; unsigned int nPos = j * m_nVNx[2] + i ; bool bInside = false ; Point3d ptIn ; for ( int k = 0 ; k < nInt ; ++ k) { int nIntType = IntersectionResults[k].nILTT ; // Se c'è intersezione if ( nIntType != ILTT_NO) { double dCos = IntersectionResults[k].dCosDN ; // entro nella superficie trimesh if ( dCos < - EPS_SMALL) { ptIn = IntersectionResults[k].ptI ; bInside = true ; } // esco dalla superficie trimesh else if ( dCos > EPS_SMALL && bInside) { Point3d ptOut = IntersectionResults[k].ptI ; unsigned int nCurrentSize = unsigned int( m_TriZValues[2][nPos].size()) ; m_TriZValues[2][nPos].resize( nCurrentSize + 2) ; m_TriZValues[2][nPos][nCurrentSize] = ptIn.y - ptMapOrig.y ; m_TriZValues[2][nPos][nCurrentSize + 1] = ptOut.y - ptMapOrig.y ; bInside = false ; } } } } } } // Assegno il minimo e massimo valore di Z della mappa m_dVMinZ[0] = 0 ; m_dVMaxZ[0] = dLengthZ ; if ( bFlag) { m_dVMinZ[1] = 0 ; m_dVMaxZ[1] = dLengthX ; m_dVMinZ[2] = 0 ; m_dVMaxZ[2] = dLengthY ; } else { m_dVMinZ[1] = 0 ; m_dVMaxZ[1] = 0 ; m_dVMinZ[2] = 0 ; m_dVMaxZ[2] = 0 ; } m_nStatus = OK ; return true ; }