Files
EgtGeomKernel/VolTriZmapGraphics.cpp
T
Dario Sassi fccd791ef6 EgtGeomKernel :
- modifiche a Zmap per gestione visualizzazione a blocchi.
2017-02-02 19:59:49 +00:00

1448 lines
51 KiB
C++

//----------------------------------------------------------------------------
// 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 "MC_Tables.h"
#include "\EgtDev\Include\EGkIntervals.h"
#include "\EgtDev\Include\EgtNumUtils.h"
#include "\EgtDev\Extern\Eigen\Core"
#include "\EgtDev\Extern\Eigen\SVD"
using namespace std ;
// ------------------------- STRUTTURA VERTICE TRIANGOLO - NORMALE ALLA SUPERFICIE ------------------------------------------------
struct VectorField {
Point3d ptInt ;
Vector3d vtNorm ;
} ;
// ------------------------- TABELLA BLOCCHI ADIACENTI ----------------------------------------------------------------------------
static int NeighbourTable[8][4] = {
{0, -1, -1, -1},
{1, 1, -1, -1},
{1, 1, 2, -1},
{2, 1, 2, -1},
{1, 3, -1, -1},
{2, 1, 3, -1},
{2, 2, 3, -1},
{3, 1, 2, 3}
} ;
// ------------------------- FUNZIONE TEST SULLE NORMALI --------------------------------------------------------------------------
enum FatureType { NoFeature = 0, Corner = 1, Edge = 2} ;
//----------------------------------------------------------------------------
bool
TestOnNormal( const VectorField CompoVert[], int nCompoElem, int& FeatureType)
{
int nI, nJ ;
double dMinCosTheta = 1.001 ;
double dCosThetaSharp = 0.9 ;
// Nota 0-esimo indice è vuoto
for ( int i = 0 ; i < nCompoElem ; ++ i) {
for ( int j = i + 1 ; j < nCompoElem ; ++ j) {
double dCurrentCos = CompoVert[i].vtNorm * CompoVert[j].vtNorm ;
if ( dCurrentCos < dMinCosTheta) {
nI = i ;
nJ = j ;
dMinCosTheta = dCurrentCos ;
}
}
}
if ( dMinCosTheta >= dCosThetaSharp) {
FeatureType = NoFeature ;
return false ;
}
Vector3d vtI = CompoVert[nI].vtNorm ;
Vector3d vtJ = CompoVert[nJ].vtNorm ;
Vector3d vtK = vtI ^ vtJ ;
double dMaxAbsCosPhi = 0 ;
double dCosPhiCorner = 0.7 ;
for ( int i = 0 ; i < nCompoElem ; ++ i) {
double dAbsCurrentCos = abs( CompoVert[i].vtNorm * vtK) ;
if ( dAbsCurrentCos > dCosPhiCorner) {
// nI = i ;
dMaxAbsCosPhi = dAbsCurrentCos ;
}
}
if ( dMaxAbsCosPhi <= dCosPhiCorner)
FeatureType = Edge ;
else
FeatureType = Corner ;
return true ;
}
// ------------------------- VISUALIZZAZIONE --------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
VolZmap::GetDexelLines( int nDir, int nPos1, int nPos2, POLYLINELIST& lstPL) const
{
// Controllo l'ammissibilità della griglia
if ( nDir < 0 || nDir > 2)
return false ;
// Verifiche sugli indici
if ( nPos1 < 0 || nPos1 >= int( m_nNx[nDir]) || nPos2 < 0 || nPos2 >= int( m_nNy[nDir]))
return false ;
int nPos = nPos1 + nPos2 * m_nNx[nDir] ;
if ( nPos < 0 || nPos >= int( m_Values[nDir].size()))
return false ;
// Calcolo coordinate punto
double dX = m_dStep * ( 0.5 + nPos1) ;
double dY = m_dStep * ( 0.5 + nPos2) ;
// Determino il punto di partensa sulla griglia
Point3d ptP = m_MapFrame[nDir].Orig() + dX * m_MapFrame[nDir].VersX() + dY * m_MapFrame[nDir].VersY() ;
// Creo le polilinee
for ( int j = 1 ; j < int( m_Values[nDir][nPos].size()) ; j += 2) {
// aggiungo polilinea a lista
lstPL.emplace_back() ;
// inserisco punti estremi
lstPL.back().AddUPoint( 0, ptP + m_Values[nDir][nPos][j-1].dZVal * m_MapFrame[nDir].VersZ()) ;
lstPL.back().AddUPoint( 1, ptP + m_Values[nDir][nPos][j].dZVal * m_MapFrame[nDir].VersZ()) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetAllTriangles( TRIA3DLIST& lstTria) const
{
if ( m_nMapNum == 1) {
const int MAX_DIM_CHUNK = 128 ;
for ( int i = 0 ; i < int( m_nNx[0]) ; i += MAX_DIM_CHUNK) {
int nDimChunkX = min( MAX_DIM_CHUNK, int( m_nNx[0]) - i) ;
for ( int j = 0 ; j < int( m_nNy[0]) ; j += MAX_DIM_CHUNK) {
int nDimChunkY = min( MAX_DIM_CHUNK, int( m_nNy[0]) - j) ;
GetChunkPrisms( i, j, nDimChunkX, nDimChunkY, MAX_DIM_CHUNK, lstTria) ;
}
}
}
//else {
//
// //std::vector <TriHolder> vecTria ;
// //vecTria.resize( int( m_BlockToUpdate.size())) ;
// //for ( int i = 0 ; i < int( m_BlockToUpdate.size()) ; ++ i) {
//
// //if ( m_BlockToUpdate[i])
// // ExtMarchingCubes( i, lstTria, vecTria[i]) ; }
// TriHolder triHold ;
// ExtMarchingCubes( 0, lstTria, triHold) ;
// FlipEdges( triHold) ;
//
// for ( int i = 0 ; i < int( triHold.size()) ; ++ i)
// for ( int j = 0 ; j < int( triHold[i].vecTria.size()) ; ++ j)
// lstTria.emplace_back( triHold[i].vecTria[j]) ;
//}
else
MarchingCubes( lstTria) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetBlockTriangles( int nBlock, TRIA3DLIST& lstTria) const
{
if ( m_nMapNum == 1) {
const int MAX_DIM_CHUNK = 128 ;
// Calcolo posizione del blocco nella griglia
int nIBlock = nBlock % int( m_nFracLin[0]) ;
int nJBlock = nBlock / int( m_nFracLin[0]) ;
// Calcolo limiti per l'indice i
int nStartI = nIBlock * int( m_nDexNumPBlock) ;
int nEndI = ( nIBlock + 1 == int( m_nFracLin[0]) ?
int( m_nNx[0]) : ( nIBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice j
int nStartJ = nJBlock * int( m_nDexNumPBlock) ;
int nEndJ = ( nJBlock + 1 == int( m_nFracLin[1]) ?
int( m_nNy[0]) : ( nJBlock + 1) * int( m_nDexNumPBlock)) ;
// Ciclo su i e j
for ( int i = nStartI ; i < nEndI ; i += MAX_DIM_CHUNK) {
int nDimChunkX = min( MAX_DIM_CHUNK, nEndI - i) ;
for ( int j = nStartJ ; j < nEndJ ; j += MAX_DIM_CHUNK) {
int nDimChunkY = min( MAX_DIM_CHUNK, nEndJ - j) ;
GetChunkPrisms( i, j, nDimChunkX, nDimChunkY, MAX_DIM_CHUNK, lstTria) ;
}
}
}
else
//ExtMarchingCubes( nBlock, lstTria, triHold) ;
MarchingCubes( nBlock, lstTria) ;
m_BlockToUpdate[nBlock] = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetBlockInfo( std::vector<bool> & bModified) const
{
bModified = m_BlockToUpdate ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetBlockCount( void) const
{
return m_nNumBlock ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetChunkPrisms( int nPos1, int nPos2, int nDim1, int nDim2, int nDimChk, TRIA3DLIST& lstTria) const
{
// determino se è un semplice parallelepipedo
bool bIsSimple = true ;
double dBotZ ;
double dTopZ ;
for ( int i = 0 ; i < nDim1 && bIsSimple ; ++ i) {
for ( int j = 0 ; j < nDim2 && bIsSimple ; ++ j) {
int nPos = ( nPos1 + i) + ( nPos2 + j) * m_nNx[0] ;
if ( nPos > int( m_nDim[0]) ||
int( m_Values[0][nPos].size()) != 2)
bIsSimple = false ;
else if ( i == 0 && j == 0) {
dBotZ = m_Values[0][nPos][0].dZVal ;
dTopZ = m_Values[0][nPos][1].dZVal ;
}
else if ( abs( m_Values[0][nPos][0].dZVal - dBotZ) > EPS_SMALL ||
abs( m_Values[0][nPos][1].dZVal - dTopZ) > EPS_SMALL)
bIsSimple = false ;
}
}
// se semplice parallelepipedo
if ( bIsSimple) {
CalcChunkPrisms( nPos1, nPos2, nDim1, nDim2, lstTria) ;
}
// se chunk di dimensioni accettabili
else if ( nDimChk >= 4) {
int nNewDimChk = nDimChk / 2 ;
for ( int i = nPos1 ; i < int( nPos1 + nDim1) ; i += nNewDimChk) {
int nDimChunkX = min( nNewDimChk, int( nPos1 + nDim1) - i) ;
for ( int j = nPos2 ; j < int( nPos2 + nDim2) ; j += nNewDimChk) {
int nDimChunkY = min( nNewDimChk, int( nPos2 + nDim2) - j) ;
GetChunkPrisms( i, j, nDimChunkX, nDimChunkY, nNewDimChk, lstTria) ;
}
}
}
// altrimenti
else {
// elaboro ogni singolo dexel
for ( int i = 0 ; i < nDim1 ; ++ i) {
for ( int j = 0 ; j < nDim2 ; ++ j) {
CalcDexelPrisms( nPos1 + i, nPos2 + j, lstTria) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CalcChunkPrisms( int nPos1, int nPos2, int nDim1, int nDim2, TRIA3DLIST& lstTria) const
{
// verifiche sugli indici
if ( nPos1 < 0 || nPos1 + nDim1 > int( m_nNx[0]) || nPos2 < 0 || nPos2 + nDim2 > int( m_nNy[0]))
return false ;
int nPos = nPos1 + nPos2 * m_nNx[0] ;
if ( nPos < 0 || nPos >= int( m_nDim[0]))
return false ;
// calcolo coordinate punti
double dX = m_dStep * nPos1 ;
double dY = m_dStep * nPos2 ;
Point3d ptP1 = m_MapFrame[0].Orig() + dX * m_MapFrame[0].VersX() + dY * m_MapFrame[0].VersY() ;
Point3d ptP2 = ptP1 + nDim1 * m_dStep * m_MapFrame[0].VersX() ;
Point3d ptP3 = ptP2 + nDim2 * m_dStep * m_MapFrame[0].VersY() ;
Point3d ptP4 = ptP1 + nDim2 * m_dStep * m_MapFrame[0].VersY() ;
// creo le facce sopra e sotto
Vector3d vtDZt = m_Values[0][nPos][1].dZVal * m_MapFrame[0].VersZ() ;
Vector3d vtDZb = m_Values[0][nPos][0].dZVal * m_MapFrame[0].VersZ() ;
// faccia superiore P1t->P2t->P3t->P4t : sempre visibile
lstTria.emplace_back() ;
lstTria.back().Set( ptP1 + vtDZt, ptP2 + vtDZt, ptP3 + vtDZt, m_MapFrame[0].VersZ()) ;
lstTria.emplace_back() ;
lstTria.back().Set( ptP3 + vtDZt, ptP4 + vtDZt, ptP1 + vtDZt, m_MapFrame[0].VersZ()) ;
// faccia inferiore P1b->P4b->P3b->P2b : sempre visibile
lstTria.emplace_back() ;
lstTria.back().Set( ptP1 + vtDZb, ptP4 + vtDZb, ptP3 + vtDZb, - m_MapFrame[0].VersZ()) ;
lstTria.emplace_back() ;
lstTria.back().Set( ptP3 + vtDZb, ptP2 + vtDZb, ptP1 + vtDZb, - m_MapFrame[0].VersZ()) ;
// creo le facce laterali
for ( int j = 0 ; j < nDim2 ; ++ j) {
int nPosD = nPos + nDim1 - 1 + j * m_nNx[0] ;
int nPosEst = ( nPos1 + nDim1 - 1 < int( m_nNx[0] - 1) ? nPosD + 1 : - 1) ;
Point3d ptP2D = ptP2 + j * m_dStep * m_MapFrame[0].VersY() ;
Point3d ptP3D = ptP2D + m_dStep * m_MapFrame[0].VersY() ;
AddDexelSideFace( nPosD, nPosEst, ptP2D, ptP3D, m_MapFrame[0].VersZ(), m_MapFrame[0].VersX(), lstTria) ;
}
for ( int i = 0 ; i < nDim1 ; ++ i) {
int nPosD = nPos + ( nDim2 - 1) * m_nNx[0] + i ;
int nPosNord = ( nPos2 + nDim2 - 1 < int( m_nNy[0] - 1) ? nPosD + m_nNx[0] : - 1) ;
Point3d ptP4D = ptP4 + i * m_dStep * m_MapFrame[0].VersX() ;
Point3d ptP3D = ptP4D + m_dStep * m_MapFrame[0].VersX() ;
AddDexelSideFace( nPosD, nPosNord, ptP3D, ptP4D, m_MapFrame[0].VersZ(), m_MapFrame[0].VersY(), lstTria) ;
}
for ( int j = 0 ; j < nDim2 ; ++ j) {
int nPosD = nPos + j * m_nNx[0] ;
int nPosWest = ( nPos1 > 0 ? nPosD - 1 : - 1) ;
Point3d ptP1D = ptP1 + j * m_dStep * m_MapFrame[0].VersY() ;
Point3d ptP4D = ptP1D + m_dStep * m_MapFrame[0].VersY() ;
AddDexelSideFace( nPosD, nPosWest, ptP4D, ptP1D, m_MapFrame[0].VersZ(), - m_MapFrame[0].VersX(), lstTria) ;
}
for ( int i = 0 ; i < nDim1 ; ++ i) {
int nPosD = nPos + i ;
int nPosSud = ( nPos2 > 0 ? nPosD - m_nNx[0] : - 1) ;
Point3d ptP1D = ptP1 + i * m_dStep * m_MapFrame[0].VersX() ;
Point3d ptP2D = ptP1D + m_dStep * m_MapFrame[0].VersX() ;
AddDexelSideFace( nPosD, nPosSud, ptP1D, ptP2D, m_MapFrame[0].VersZ(), - m_MapFrame[0].VersY(), lstTria) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CalcDexelPrisms( int nPos1, int nPos2, TRIA3DLIST& lstTria) const
{
// verifiche sugli indici
if ( nPos1 < 0 || nPos1 >= int( m_nNx[0]) || nPos2 < 0 || nPos2 >= int( m_nNy[0]))
return false ;
int nPos = nPos1 + nPos2 * m_nNx[0] ;
if ( nPos < 0 || nPos >= int( m_nDim[0]))
return false ;
// calcolo coordinate punto
double dX = m_dStep * nPos1 ;
double dY = m_dStep * nPos2 ;
Point3d ptP1 = m_MapFrame[0].Orig() + dX * m_MapFrame[0].VersX() + dY * m_MapFrame[0].VersY() ;
Point3d ptP2 = ptP1 + m_dStep * m_MapFrame[0].VersX() ;
Point3d ptP3 = ptP2 + m_dStep * m_MapFrame[0].VersY() ;
Point3d ptP4 = ptP1 + m_dStep * m_MapFrame[0].VersY() ;
// creo le facce sopra e sotto di ogni intervallo (sempre visibili)
for ( int i = 1 ; i < int( m_Values[0][nPos].size()) ; i += 2) {
Vector3d vtDZt = m_Values[0][nPos][i].dZVal * m_MapFrame[0].VersZ() ;
Vector3d vtDZb = m_Values[0][nPos][i-1].dZVal * m_MapFrame[0].VersZ() ;
// faccia superiore P1t->P2t->P3t->P4t : sempre visibile
lstTria.emplace_back() ;
lstTria.back().Set( ptP1 + vtDZt, ptP2 + vtDZt, ptP3 + vtDZt, m_MapFrame[0].VersZ()) ;
lstTria.emplace_back() ;
lstTria.back().Set( ptP3 + vtDZt, ptP4 + vtDZt, ptP1 + vtDZt, m_MapFrame[0].VersZ()) ;
// faccia inferiore P1b->P4b->P3b->P2b : sempre visibile
lstTria.emplace_back() ;
lstTria.back().Set( ptP1 + vtDZb, ptP4 + vtDZb, ptP3 + vtDZb, - m_MapFrame[0].VersZ()) ;
lstTria.emplace_back() ;
lstTria.back().Set( ptP3 + vtDZb, ptP2 + vtDZb, ptP1 + vtDZb, - m_MapFrame[0].VersZ()) ;
}
// creo le facce laterali
int nPosEst = ( nPos1 < int( m_nNx[0] - 1) ? nPos + 1 : - 1) ;
AddDexelSideFace( nPos, nPosEst, ptP2, ptP3, m_MapFrame[0].VersZ(), m_MapFrame[0].VersX(), lstTria) ;
int nPosNord = ( nPos2 < int( m_nNy[0] - 1) ? nPos + m_nNx[0] : - 1) ;
AddDexelSideFace( nPos, nPosNord, ptP3, ptP4, m_MapFrame[0].VersZ(), m_MapFrame[0].VersY(), lstTria) ;
int nPosWest = ( nPos1 > 0 ? nPos - 1 : - 1) ;
AddDexelSideFace( nPos, nPosWest, ptP4, ptP1, m_MapFrame[0].VersZ(), - m_MapFrame[0].VersX(), lstTria) ;
int nPosSud = ( nPos2 > 0 ? nPos - m_nNx[0] : - 1) ;
AddDexelSideFace( nPos, nPosSud, ptP1, ptP2, m_MapFrame[0].VersZ(), - m_MapFrame[0].VersY(), lstTria) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AddDexelSideFace( int nPos, int nPosAdj, const Point3d& ptP, const Point3d& ptQ,
const Vector3d& vtZ, const Vector3d& vtNorm, TRIA3DLIST& lstTria) const
{
Intervals intFace ;
for ( int i = 1 ; i < int( m_Values[0][nPos].size()) ; i += 2)
intFace.Add( m_Values[0][nPos][i-1].dZVal, m_Values[0][nPos][i].dZVal) ;
if ( nPosAdj > 0) {
for ( int i = 1 ; i < int( m_Values[0][nPosAdj].size()) ; i += 2)
intFace.Subtract( m_Values[0][nPosAdj][i-1].dZVal, m_Values[0][nPosAdj][i].dZVal) ;
}
double dMin, dMax ;
bool bFound = intFace.GetFirst( dMin, dMax) ;
while ( bFound) {
Vector3d vtDZt = dMax * vtZ ;
Vector3d vtDZb = dMin * vtZ ;
lstTria.emplace_back() ;
lstTria.back().Set( ptP + vtDZb, ptQ + vtDZb, ptQ + vtDZt, vtNorm) ;
lstTria.emplace_back() ;
lstTria.back().Set( ptQ + vtDZt, ptP + vtDZt, ptP + vtDZb, vtNorm) ;
bFound = intFace.GetNext( dMin, dMax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MarchingCubes( TRIA3DLIST& lstTria) const
{
// Ciclo su tutti i voxel dello Zmap
for ( int i = - 1 ; i < int( m_nNx[0]) ; ++ i) {
for ( int j = - 1 ; j < int( m_nNy[0]) ; ++ j) {
for ( int k = - 1 ; k < int( m_nNy[1]) ; ++ k) {
// Indici i,j,k dei vertici
int IndexCorner[8][3] = {
{ i, j, k},
{ i + 1, j, k},
{ i + 1, j + 1, k},
{ i, j + 1, k},
{ i, j, k + 1},
{ i + 1, j, k + 1},
{ i + 1, j + 1, k + 1},
{ i, j + 1, k + 1}
} ;
// Classificazione dei vertici: interni o esterni al materiale
int nIndex = 0 ;
if ( IsThereMat( i, j, k))
nIndex |= ( 1 << 0) ;
if ( IsThereMat( i + 1, j, k))
nIndex |= ( 1 << 1) ;
if ( IsThereMat( i + 1, j + 1, k))
nIndex |= ( 1 << 2) ;
if ( IsThereMat( i, j + 1, k))
nIndex |= ( 1 << 3) ;
if ( IsThereMat( i, j, k + 1))
nIndex |= ( 1 << 4) ;
if ( IsThereMat( i + 1, j, k + 1))
nIndex |= ( 1 << 5) ;
if ( IsThereMat( i + 1, j + 1, k + 1))
nIndex |= ( 1 << 6) ;
if ( IsThereMat( i, j + 1, k + 1))
nIndex |= ( 1 << 7) ;
// Se vi è qualche intersezione fra segmenti e superficie
// continuo altrimenti passo al prossimo voxel
if ( EdgeTable[nIndex] == 0)
continue ;
static int intersections[12][2] = {
{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 },
{ 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
} ;
Point3d ptIntPoint[12] ;
// Ciclo sui segmenti
for ( int EdgeIndex = 0 ; EdgeIndex < 12 ; ++ EdgeIndex) {
// Se il segmento non attraversa la superficie
// passo al successivo
if ( ! ( EdgeTable[nIndex] & ( 1 << EdgeIndex)))
continue ;
int n1 = intersections[EdgeIndex][0] ;
int n2 = intersections[EdgeIndex][1] ;
// Determino con precisione il punto di intersezione sullo spigolo
IntersPos( IndexCorner[n1], IndexCorner[n2], ptIntPoint[EdgeIndex]) ;
ptIntPoint[EdgeIndex].ToGlob( m_MapFrame[0]) ;
}
// Costruzione dei triangoli
for ( int TriIndex = 0 ; TriangleTableEn[nIndex][0][TriIndex] != - 1 ; TriIndex += 3) {
// Costruzione triangolo
int i0 = TriangleTableEn[nIndex][0][TriIndex + 2] ;
int i1 = TriangleTableEn[nIndex][0][TriIndex + 1] ;
int i2 = TriangleTableEn[nIndex][0][TriIndex] ;
// Il triangolo è pronto
Triangle3d CurrentTriangle ;
CurrentTriangle.Set( ptIntPoint[i0], ptIntPoint[i1], ptIntPoint[i2]) ;
CurrentTriangle.Validate() ;
// Aggiungo triangolo
lstTria.emplace_back( CurrentTriangle) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MarchingCubes( int nBlock, TRIA3DLIST& lstTria) const
{
if ( nBlock < 0 || nBlock >= int( m_BlockToUpdate.size()))
return false ;
Point3d ptMapOrig = m_MapFrame[0].Orig() ;
// Calcolo posizione del blocco nel reticolo
int nIBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) % int( m_nFracLin[0]) ;
int nJBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) / int( m_nFracLin[0]) ;
int nKBlock = ( nBlock / int( m_nFracLin[0] * m_nFracLin[1])) ;
// Calcolo limiti per l'indice i
int nStartI = nIBlock * int( m_nDexNumPBlock) - 1 ; //( nIBlock > 0 ? nIBlock * int( m_nDexNumPBlock) : - 1) ;
int nEndI = ( nIBlock + 1 == int( m_nFracLin[0]) ?
int( m_nNx[0]) : ( nIBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice j
int nStartJ = nJBlock * int( m_nDexNumPBlock) - 1 ; //( nJBlock > 0 ? nJBlock * int( m_nDexNumPBlock) : - 1) ;
int nEndJ = ( nJBlock + 1 == int( m_nFracLin[1]) ?
int( m_nNy[0]) : ( nJBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice k
int nStartK = nKBlock * int( m_nDexNumPBlock) - 1 ; //( nKBlock > 0 ? nKBlock * int( m_nDexNumPBlock) : - 1) ;
int nEndK = ( nKBlock + 1 == int( m_nFracLin[2]) ?
int( m_nNy[1]) : ( nKBlock + 1) * int( m_nDexNumPBlock)) ;
// Ciclo su tutti i voxel dello Zmap
for ( int i = nStartI ; i < nEndI ; ++ i) {
for ( int j = nStartJ ; j < nEndJ ; ++ j) {
for ( int k = nStartK ; k < nEndK ; ++ k) {
// Indici i,j,k dei vertici
int IndexCorner[8][3] = {
{ i, j, k},
{ i + 1, j, k},
{ i + 1, j + 1, k},
{ i, j + 1, k},
{ i, j, k + 1},
{ i + 1, j, k + 1},
{ i + 1, j + 1, k + 1},
{ i, j + 1, k + 1}
} ;
int nIndex = 0 ;
// Classificazione dei vertici: interni o esterni al materiale
if ( IsThereMat( i, j, k))
nIndex |= ( 1 << 0) ;
if ( IsThereMat( i + 1, j, k))
nIndex |= ( 1 << 1) ;
if ( IsThereMat( i + 1, j + 1, k))
nIndex |= ( 1 << 2) ;
if ( IsThereMat( i, j + 1, k))
nIndex |= ( 1 << 3) ;
if ( IsThereMat( i, j, k + 1))
nIndex |= ( 1 << 4) ;
if ( IsThereMat( i + 1, j, k + 1))
nIndex |= ( 1 << 5) ;
if ( IsThereMat( i + 1, j + 1, k + 1))
nIndex |= ( 1 << 6) ;
if ( IsThereMat( i, j + 1, k + 1))
nIndex |= ( 1 << 7) ;
// Se vi è qualche intersezione fra segmenti e superficie
// continuo altrimenti passo al prossimo voxel
if ( EdgeTable[nIndex] == 0)
continue ;
static int intersections[12][2] = {
{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 },
{ 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
} ;
Point3d ptIntPoint[12] ;
// Ciclo sui segmenti
for ( int EdgeIndex = 0 ; EdgeIndex < 12 ; ++ EdgeIndex) {
// Se il segmento non attraversa la superficie
// passo al successivo
if ( ! ( EdgeTable[nIndex] & ( 1 << EdgeIndex)))
continue ;
int n1 = intersections[EdgeIndex][0] ;
int n2 = intersections[EdgeIndex][1] ;
// Determino con precisione il punto di intersezione sullo spigolo
IntersPos( IndexCorner[n1], IndexCorner[n2], ptIntPoint[EdgeIndex]) ;
ptIntPoint[EdgeIndex].ToGlob( m_MapFrame[0]) ;
}
// Costruzione dei triangoli
for ( int TriIndex = 0 ; TriangleTableEn[nIndex][0][TriIndex] != - 1 ; TriIndex += 3) {
// Costruzione triangolo
int i0 = TriangleTableEn[nIndex][0][TriIndex + 2] ;
int i1 = TriangleTableEn[nIndex][0][TriIndex + 1] ;
int i2 = TriangleTableEn[nIndex][0][TriIndex] ;
Triangle3d CurrentTriangle ;
Vector3d vtN = ( ptIntPoint[i1] - ptIntPoint[i0]) ^ ( ptIntPoint[i2] - ptIntPoint[i1]) ;
vtN.Normalize() ;
vtN.ToGlob( m_MapFrame[0]) ;
// Il triangolo è pronto
CurrentTriangle.Set( ptIntPoint[i0], ptIntPoint[i1], ptIntPoint[i2], vtN) ;
// Aggiungo triangolo
lstTria.emplace_back( CurrentTriangle) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ExtMarchingCubes( int nBlock, TRIA3DLIST& lstTria, TriHolder& triHold) const
{
if ( nBlock < 0 || nBlock >= int( m_BlockToUpdate.size()))
return false ;
Point3d ptMapOrig = m_MapFrame[0].Orig() ;
// Calcolo posizione del blocco nel reticolo
int nIBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) % int( m_nFracLin[0]) ;
int nJBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) / int( m_nFracLin[0]) ;
int nKBlock = ( nBlock / int( m_nFracLin[0] * m_nFracLin[1])) ;
// Calcolo limiti per l'indice i
int nStartI = nIBlock * int( m_nDexNumPBlock) - 1 ;
int nEndI = ( nIBlock + 1 == int( m_nFracLin[0]) ?
int( m_nNx[0]) : ( nIBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice j
int nStartJ = nJBlock * int( m_nDexNumPBlock) - 1 ;
int nEndJ = ( nJBlock + 1 == int( m_nFracLin[1]) ?
int( m_nNy[0]) : ( nJBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice k
int nStartK = nKBlock * int( m_nDexNumPBlock) - 1 ;
int nEndK = ( nKBlock + 1 == int( m_nFracLin[2]) ?
int( m_nNy[1]) : ( nKBlock + 1) * int( m_nDexNumPBlock)) ;
// Ciclo su tutti i voxel dello Zmap
for ( int i = nStartI ; i < nEndI ; ++ i) {
for ( int j = nStartJ ; j < nEndJ ; ++ j) {
for ( int k = nStartK ; k < nEndK ; ++ k) {
// Indici i,j,k dei vertici
int IndexCorner[8][3] = {
{ i, j, k},
{ i + 1, j, k},
{ i + 1, j + 1, k},
{ i, j + 1, k},
{ i, j, k + 1},
{ i + 1, j, k + 1},
{ i + 1, j + 1, k + 1},
{ i, j + 1, k + 1}
} ;
int nIndex = 0 ;
// Classificazione dei vertici: interni o esterni al materiale
if ( IsThereMat( i, j, k)) nIndex |= ( 1 << 0) ;
if ( IsThereMat( i + 1, j, k)) nIndex |= ( 1 << 1) ;
if ( IsThereMat( i + 1, j + 1, k)) nIndex |= ( 1 << 2) ;
if ( IsThereMat( i, j + 1, k)) nIndex |= ( 1 << 3) ;
if ( IsThereMat( i, j, k + 1)) nIndex |= ( 1 << 4) ;
if ( IsThereMat( i + 1, j, k + 1)) nIndex |= ( 1 << 5) ;
if ( IsThereMat( i + 1, j + 1, k + 1)) nIndex |= ( 1 << 6) ;
if ( IsThereMat( i, j + 1, k + 1)) nIndex |= ( 1 << 7) ;
// Se vi è qualche intersezione fra segmenti e superficie
// continuo altrimenti passo al prossimo voxel
if ( EdgeTable[nIndex] == 0)
continue ;
static int intersections[12][2] = {
{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 },
{ 6, 7 }, { 7, 4 }, { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }
} ;
// Arrey di strutture punto di intersezione
// e normale alla superficie in esso.
VectorField VecField[12] ;
// Ciclo sui segmenti
for ( int EdgeIndex = 0 ; EdgeIndex < 12 ; ++ EdgeIndex) {
// Se il segmento non attraversa la superficie
// passo al successivo
if ( ! ( EdgeTable[nIndex] & ( 1 << EdgeIndex)))
continue ;
int n1 = intersections[EdgeIndex][0] ;
int n2 = intersections[EdgeIndex][1] ;
// Determino con precisione il punto di intersezione sullo spigolo
IntersPos( IndexCorner[n1], IndexCorner[n2],
VecField[EdgeIndex].ptInt,
VecField[EdgeIndex].vtNorm) ;
VecField[EdgeIndex].ptInt.ToGlob( m_MapFrame[0]) ;
VecField[EdgeIndex].vtNorm.ToGlob( m_MapFrame[0]) ;
}
// Determino il numero di componenti connesse
int nComponents = TriangleTableEn[nIndex][1][0] ;
// Serve nel ciclo che salva i punti e vettori di
// una componente nell'arrey di compentenza: La tabella
// fornisce numero di componenti, numero di vertici per
// componenti per OGNUNA delle componenti e in fine
// elenca i vertici della prima componente, seguiti da quelli
// della seconda e così via.
int nTableOffset = nComponents ;
// Ciclo sulle componenti
for ( int nCompCount = 1 ; nCompCount <= nComponents ; ++ nCompCount) {
// Numero vertici per componenti
int nVertComp = TriangleTableEn[nIndex][1][nCompCount] ;
// Vettore di Vector3d
VectorField CompoVert[12] ;
// Riempio il vettore
for ( int nVertCount = 0 ; nVertCount < nVertComp ; ++ nVertCount)
// Nota che il primo elemento dell'arrey
// (0-esimo) non viene iniziallizzato
CompoVert[nVertCount] = VecField[TriangleTableEn[nIndex][1][nVertCount + nTableOffset + 1]] ;
int nFeatureType ;
// Valuto le relazioni reciproche fra le normali
bool bExt = TestOnNormal( CompoVert, nVertComp, nFeatureType) ;
// Extended MC
if ( bExt) {
// Ridimensiono il vettore che contiene i
triHold.resize( triHold.size() + 1) ;
int nCurrent = int( triHold.size()) - 1 ;
triHold[nCurrent].i = i ;
triHold[nCurrent].j = j ;
triHold[nCurrent].k = k ;
Point3d ptGravityCenter( 0, 0, 0) ;
for ( int i = 0 ; i < nVertComp ; ++ i)
ptGravityCenter += CompoVert[i].ptInt ;
ptGravityCenter /= nVertComp ;
Vector3d vtO = ptGravityCenter - ORIG ;
Point3d ptTrasf[12] ;
for ( int i = 0 ; i < nVertComp ; ++ i)
ptTrasf[i] = CompoVert[i].ptInt - vtO ;
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> dSystemMatrix ;
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> dSystemVector ;
dSystemMatrix dMatrixN ;
dSystemVector dKnownVector ;
dSystemVector dUnknownVector ;
dMatrixN.resize( nVertComp, 3) ;
dKnownVector.resize( nVertComp, 1) ;
for ( int i = 0 ; i < nVertComp ; ++ i) {
dMatrixN( i, 0) = CompoVert[i].vtNorm.x ;
dMatrixN( i, 1) = CompoVert[i].vtNorm.y ;
dMatrixN( i, 2) = CompoVert[i].vtNorm.z ;
dKnownVector( i) = CompoVert[i].vtNorm * ( ptTrasf[i] - ORIG) ;
}
typedef Eigen::JacobiSVD<dSystemMatrix> DecomposerSVD ;
#define ComputeU Eigen::ComputeThinU
#define ComputeV Eigen::ComputeThinV
DecomposerSVD svd( dMatrixN, ComputeU | ComputeV) ;
#undef ComputeU
#undef ComputeV
dSystemVector dSingularValue = svd.singularValues( ) ;
if ( nFeatureType == 2) {
int nIMin = 0 ;
int nRank = min( nVertComp, 3) ;
double dMinVal = DBL_MAX ;
for ( int i = 0 ; i < nRank ; ++ i) {
if ( dSingularValue( i) < dMinVal) {
nIMin = i ;
dMinVal = dSingularValue( i) ;
}
}
dSingularValue( nIMin) = 0 ;
}
dUnknownVector = svd.solve( dKnownVector) ;
Point3d ptSol( dUnknownVector( 0) + vtO.x,
dUnknownVector( 1) + vtO.y,
dUnknownVector( 2) + vtO.z) ;
for ( int i = 0 ; i < nVertComp ; ++ i)
ptTrasf[i] = ptTrasf[i] + vtO ;
//ptSol += vtO ;
Triangle3d CurrentTriangle ;
for ( int i = 0 ; i < nVertComp - 1 ; ++ i) {
// Il triangolo è pronto
CurrentTriangle.Set( ptSol, CompoVert[i+1].ptInt, CompoVert[i].ptInt) ;
CurrentTriangle.Validate( true) ;
// Aggiungo triangolo
triHold[nCurrent].vecTria.emplace_back( CurrentTriangle) ;
}
// Ultimo triangolo
CurrentTriangle.Set( ptSol, CompoVert[0].ptInt, CompoVert[nVertComp - 1].ptInt) ;
CurrentTriangle.Validate( true) ;
// Aggiungo ultimo triangolo
triHold[nCurrent].vecTria.emplace_back( CurrentTriangle) ;
triHold[nCurrent].ptVert = ptSol ;
}
// Standard MC
else {
// Costruzione dei triangoli
for ( int TriIndex = 0 ; TriangleTableEn[nIndex][0][TriIndex] != - 1 ; TriIndex += 3) {
// Costruzione triangolo
int i0 = TriangleTableEn[nIndex][0][TriIndex + 2] ;
int i1 = TriangleTableEn[nIndex][0][TriIndex + 1] ;
int i2 = TriangleTableEn[nIndex][0][TriIndex] ;
Triangle3d CurrentTriangle ;
// Il triangolo è pronto
CurrentTriangle.Set( VecField[i0].ptInt, VecField[i1].ptInt, VecField[i2].ptInt) ;
CurrentTriangle.Validate( true) ;
// Aggiungo triangolo
lstTria.emplace_back( CurrentTriangle) ;
}
}
nTableOffset += nVertComp ;
}
}
}
}
m_BlockToUpdate[nBlock] = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::FlipEdges( TriHolder& triHold) const
{
int nVoxelNum = int( triHold.size()) ;
for ( int n = 0 ; n < nVoxelNum ; ++ n) {
for ( int m = n + 1 ; m < nVoxelNum ; ++ m) {
if ( ( triHold[m].i < int( m_nNx[0]) &&
triHold[m].j < int( m_nNy[0]) &&
triHold[m].k < int( m_nNy[1])) &&
( ( triHold[m].i == triHold[n].i + 1) ||
( triHold[m].j == triHold[n].j + 1) ||
( triHold[m].k == triHold[n].k + 1))) {
int nNumN = int( triHold[n].vecTria.size()) ;
int nNumM = int( triHold[m].vecTria.size()) ;
for ( int triN = 0 ; triN < nNumN ; ++ triN) {
bool bModified = false ;
for ( int triM = 0 ; triM < nNumM ; ++ triM) {
std::vector <int> SharedIndex ;
for ( int vertN = 0 ; vertN < 3 ; ++ vertN) {
for ( int vertM = 0 ; vertM < 3 ; ++ vertM) {
Point3d ptN = triHold[n].vecTria[triN].GetP( vertN) ;
Point3d ptM = triHold[m].vecTria[triM].GetP( vertM) ;
if ( SqDist( ptN, ptM) < EPS_SMALL * EPS_SMALL) {
SharedIndex.emplace_back( vertN) ;
SharedIndex.emplace_back( vertM) ;
}
if ( SharedIndex.size() > 2)
break ;
}
if ( SharedIndex.size() > 2)
break ;
}
// Si deve operare la modifica dei triangoli
if ( SharedIndex.size() > 2) {
// Modifico i triangoli
triHold[n].vecTria[triN].SetP( SharedIndex[0], triHold[m].ptVert) ;
triHold[m].vecTria[triM].SetP( SharedIndex[3], triHold[n].ptVert) ;
triHold[n].vecTria[triN].Validate( true) ;
triHold[m].vecTria[triM].Validate( true) ;
bModified = true ;
break ;
}
}
if( bModified)
break ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::FlipEdges( int nBlock, TriHolder& triHold)
{
// Controllo sulla validità del blocco
if ( nBlock < 0 || nBlock > int( m_nNumBlock))
return false ;
// Calcolo posizione del blocco nel reticolo
int nIBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) % int( m_nFracLin[0]) ;
int nJBlock = ( nBlock % int( m_nFracLin[0] * m_nFracLin[1])) / int( m_nFracLin[0]) ;
int nKBlock = ( nBlock / int( m_nFracLin[0] * m_nFracLin[1])) ;
// Calcolo limiti per l'indice i
//int nStartI = nIBlock * int( m_nDexNumPBlock) - 1 ;
int nEndI = ( nIBlock + 1 == int( m_nFracLin[0]) ?
int( m_nNx[0]) : ( nIBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice j
//int nStartJ = nJBlock * int( m_nDexNumPBlock) - 1 ;
int nEndJ = ( nJBlock + 1 == int( m_nFracLin[1]) ?
int( m_nNy[0]) : ( nJBlock + 1) * int( m_nDexNumPBlock)) ;
// Calcolo limiti per l'indice k
//int nStartK = nKBlock * int( m_nDexNumPBlock) - 1 ;
int nEndK = ( nKBlock + 1 == int( m_nFracLin[2]) ?
int( m_nNy[1]) : ( nKBlock + 1) * int( m_nDexNumPBlock)) ;
int nFirstVoxelLim = int( triHold.size()) ;
int nSecondVoxelLim ;
for ( int n = 0 ; n < nFirstVoxelLim ; ++ n) {
// Determino se il voxel è di frontiera
// per qualche blocco adiacente.
int nNeighbour = 0 ;
if ( triHold[n].i == nEndI - 1) nNeighbour |= ( 1 << 0) ;
if ( triHold[n].j == nEndJ - 1) nNeighbour |= ( 1 << 1) ;
if ( triHold[n].k == nEndK - 1) nNeighbour |= ( 1 << 2) ;
int nNumAdjBlocks = NeighbourTable[nNeighbour][0] ;
//
for ( int nTabInd = 0 ; nTabInd <= nNumAdjBlocks ; ++ nTabInd) {
if ( ( ! nTabInd) && ( ! nNumAdjBlocks))
nSecondVoxelLim = nFirstVoxelLim ;
else if ( nTabInd && ( NeighbourTable[nNeighbour][nTabInd] == 1)) {
;
}
else if ( nTabInd && ( NeighbourTable[nNeighbour][nTabInd] == 2)) {
;
}
else if ( nTabInd && ( NeighbourTable[nNeighbour][nTabInd] == 3)) {
;
}
// metti l'intero for dopo con gli aggiustamenti
}
for ( int m = n + 1 ; m < nSecondVoxelLim ; ++ m) {
int nNumN = int( triHold[n].vecTria.size()) ;
int nNumM = int( triHold[m].vecTria.size()) ;
bool bFlag = false ;
std::vector <int> SharedIndex ;
for ( int triN = 0 ; triN < nNumN ; ++ triN) {
for ( int triM = 0 ; triM < nNumM ; ++ triM) {
int nSharedVertex = 0 ;
for ( int vertN = 0 ; vertN < 3 ; ++ vertN) {
for ( int vertM = 0 ; vertM < 3 ; ++ vertM) {
Point3d ptN = triHold[n].vecTria[triN].GetP( vertN) ;
Point3d ptM = triHold[m].vecTria[triM].GetP( vertM) ;
if ( SqDist( ptN, ptM) < EPS_SMALL * EPS_SMALL) {
nSharedVertex ++ ;
SharedIndex.emplace_back( vertN) ;
SharedIndex.emplace_back( vertM) ;
}
if ( nSharedVertex > 1)
break ;
}
if ( nSharedVertex > 1)
break ;
}
if ( nSharedVertex > 1) {
triHold[n].vecTria[triN].SetP( SharedIndex[3], triHold[m].ptVert) ;
triHold[m].vecTria[triM].SetP( SharedIndex[2], triHold[n].ptVert) ;
bFlag = true ;
break ;
}
}
if ( bFlag)
break ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::FlipEdges( int nNumBlocks, int nBlocks[], TriHolder triHold[])
{
// Controllo sulla validità dei blocchi
for ( int i = 0 ; i < nNumBlocks ; ++ i)
if ( nBlocks[i] < 0 || nBlocks[i] > int( m_nNumBlock))
return false ;
// Dispongo i blocchi in ordine crescente
for ( int i = 0 ; i < nNumBlocks ; ++ i)
for ( int j = i + 1 ; j < nNumBlocks ; ++ j)
if ( nBlocks[i] > nBlocks[j])
swap( nBlocks[i], nBlocks[j]) ;
// Ciclo sui blocchi
for ( int i = 0 ; i < nNumBlocks ; ++ i) {
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::IsThereMat( int nI, int nJ, int nK) const
{
if ( nI == - 1 || nI == m_nNx[0] ||
nJ == - 1 || nJ == m_nNy[0] ||
nK == - 1 || nK == m_nNy[1])
return false ;
double dZ[3] ;
dZ[0] = ( nK + 0.5) * m_dStep ;
dZ[1] = ( nI + 0.5) * m_dStep ;
dZ[2] = ( nJ + 0.5) * m_dStep ;
int nCount = 0 ;
for ( int nGrid = 0 ; nGrid < int ( m_nMapNum) ; ++ nGrid) {
unsigned int nGrI, nGrJ ;
if ( nGrid == 0) {
nGrI = nI ;
nGrJ = nJ ;
}
else if ( nGrid == 1) {
nGrI = nJ ;
nGrJ = nK ;
}
else {
nGrI = nK ;
nGrJ = nI ;
}
unsigned int nPos = nGrJ * m_nNx[nGrid] + nGrI ;
size_t nDexSize = m_Values[nGrid][nPos].size() ;
size_t nIndex = 0 ;
while ( nIndex < nDexSize) {
if ( dZ[nGrid] > m_Values[nGrid][nPos][nIndex].dZVal - EPS_SMALL &&
dZ[nGrid] < m_Values[nGrid][nPos][nIndex + 1].dZVal + EPS_SMALL) {
++ nCount ;
break ;
}
nIndex += 2 ;
}
}
return ( nCount == 3) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::IntersPos( int nVec1[], int nVec2[], Point3d& ptInt) const
{
if ( nVec1[0] != nVec2[0]) {
ptInt.y = ( nVec1[1] + 0.5) * m_dStep ;
ptInt.z = ( nVec1[2] + 0.5) * m_dStep ;
int nMinI = min( nVec1[0], nVec2[0]) ;
int nMaxI = max( nVec1[0], nVec2[0]) ;
double dMinX = ( nMinI + 0.5) * m_dStep ;
double dMaxX = ( nMaxI + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[2] * m_nNx[1] + nVec1[1] ;
size_t nSize = m_Values[1][nDexel].size() ;
bool bFound = false ;
for ( size_t i = 0 ; i < nSize ; i += 2) {
double dx1 = m_Values[1][nDexel][i].dZVal ;
double dx2 = m_Values[1][nDexel][i+1].dZVal ;
if ( dx1 < dMinX - EPS_SMALL && dx2 > dMinX - EPS_SMALL && dx2 < dMaxX + EPS_SMALL) {
ptInt.x = dx2 ;
bFound = true ;
break ;
}
else if ( dx1 > dMinX - EPS_SMALL && dx1 < dMaxX + EPS_SMALL && dx2 > dMaxX + EPS_SMALL) {
ptInt.x = dx1 ;
bFound = true ;
break ;
}
}
if ( ! bFound)
ptInt.x = ( dMinX + dMaxX) / 2 ;
}
else if ( nVec1[1] != nVec2[1]) {
ptInt.x = ( nVec1[0] + 0.5) * m_dStep ;
ptInt.z = ( nVec1[2] + 0.5) * m_dStep ;
int nMinJ = min( nVec1[1], nVec2[1]) ;
int nMaxJ = max( nVec1[1], nVec2[1]) ;
double dMinY = ( nMinJ + 0.5) * m_dStep ;
double dMaxY = ( nMaxJ + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[0] * m_nNx[2] + nVec1[2] ;
size_t nSize = m_Values[2][nDexel].size() ;
bool bFound = false ;
for ( size_t j = 0 ; j < nSize ; j += 2) {
double dy1 = m_Values[2][nDexel][j].dZVal ;
double dy2 = m_Values[2][nDexel][j+1].dZVal ;
if ( dy1 < dMinY - EPS_SMALL && dy2 > dMinY - EPS_SMALL && dy2 < dMaxY + EPS_SMALL) {
ptInt.y = dy2 ;
bFound = true ;
break ;
}
else if ( dy1 > dMinY - EPS_SMALL && dy1 < dMaxY + EPS_SMALL && dy2 > dMaxY + EPS_SMALL) {
ptInt.y = dy1 ;
bFound = true ;
break ;
}
}
if ( ! bFound)
ptInt.y = ( dMinY + dMaxY) / 2 ;
}
else if ( nVec1[2] != nVec2[2]) {
ptInt.x = ( nVec1[0] + 0.5) * m_dStep ;
ptInt.y = ( nVec1[1] + 0.5) * m_dStep ;
int nMinK = min( nVec1[2], nVec2[2]) ;
int nMaxK = max( nVec1[2], nVec2[2]) ;
double dMinZ = ( nMinK + 0.5) * m_dStep ;
double dMaxZ = ( nMaxK + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[1] * m_nNx[0] + nVec1[0] ;
size_t nSize = m_Values[0][nDexel].size() ;
bool bFound = false ;
for ( size_t k = 0 ; k < nSize ; k += 2) {
double dz1 = m_Values[0][nDexel][k].dZVal ;
double dz2 = m_Values[0][nDexel][k+1].dZVal ;
if ( dz1 < dMinZ - EPS_SMALL && dz2 > dMinZ - EPS_SMALL && dz2 < dMaxZ + EPS_SMALL) {
ptInt.z = dz2 ;
bFound = true ;
break ;
}
else if ( dz1 > dMinZ - EPS_SMALL && dz1 < dMaxZ + EPS_SMALL && dz2 > dMaxZ + EPS_SMALL) {
ptInt.z = dz1 ;
bFound = true ;
break ;
}
}
if ( ! bFound)
ptInt.z = ( dMinZ + dMaxZ) / 2 ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::IntersPos( int nVec1[], int nVec2[], Point3d& ptInt, Vector3d& vtNormal) const
{
if ( nVec1[0] != nVec2[0]) {
int nMinI = min( nVec1[0], nVec2[0]) ;
int nMaxI = max( nVec1[0], nVec2[0]) ;
double dMinX = ( nMinI + 0.5) * m_dStep ;
double dMaxX = ( nMaxI + 0.5) * m_dStep ;
ptInt.y = ( nVec1[1] + 0.5) * m_dStep ;
ptInt.z = ( nVec1[2] + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[2] * m_nNx[1] + nVec1[1] ;
size_t nSize = m_Values[1][nDexel].size() ;
bool bFound = false ;
for ( size_t i = 0 ; i < nSize ; i += 2) {
double dx1 = m_Values[1][nDexel][i].dZVal ;
double dx2 = m_Values[1][nDexel][i+1].dZVal ;
if ( dx1 < dMinX - EPS_SMALL && dx2 > dMinX - EPS_SMALL && dx2 < dMaxX + EPS_SMALL) {
ptInt.x = dx2 ;
vtNormal = m_Values[1][nDexel][i+1].vtN ;
bFound = true ;
break ;
}
else if ( dx1 > dMinX - EPS_SMALL && dx1 < dMaxX + EPS_SMALL && dx2 > dMaxX + EPS_SMALL) {
ptInt.x = dx1 ;
vtNormal = m_Values[1][nDexel][i].vtN ;
bFound = true ;
break ;
}
}
if ( ! bFound) {
ptInt.x = ( dMinX + dMaxX) / 2 ;
// Versore Normale ???
}
}
else if ( nVec1[1] != nVec2[1]) {
int nMinJ = min( nVec1[1], nVec2[1]) ;
int nMaxJ = max( nVec1[1], nVec2[1]) ;
double dMinY = ( nMinJ + 0.5) * m_dStep ;
double dMaxY = ( nMaxJ + 0.5) * m_dStep ;
ptInt.x = ( nVec1[0] + 0.5) * m_dStep ;
ptInt.z = ( nVec1[2] + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[0] * m_nNx[2] + nVec1[2] ;
size_t nSize = m_Values[2][nDexel].size() ;
bool bFound = false ;
for ( size_t j = 0 ; j < nSize ; j += 2) {
double dy1 = m_Values[2][nDexel][j].dZVal ;
double dy2 = m_Values[2][nDexel][j+1].dZVal ;
if ( dy1 < dMinY - EPS_SMALL && dy2 > dMinY - EPS_SMALL && dy2 < dMaxY + EPS_SMALL) {
ptInt.y = dy2 ;
vtNormal = m_Values[2][nDexel][j+1].vtN ;
bFound = true ;
break ;
}
else if ( dy1 > dMinY - EPS_SMALL && dy1 < dMaxY + EPS_SMALL && dy2 > dMaxY + EPS_SMALL) {
ptInt.y = dy1 ;
vtNormal = m_Values[2][nDexel][j].vtN ;
bFound = true ;
break ;
}
}
if ( ! bFound) {
ptInt.y = ( dMinY + dMaxY) / 2 ;
// Versore Normale ???
}
}
else if ( nVec1[2] != nVec2[2]) {
int nMinK = min( nVec1[2], nVec2[2]) ;
int nMaxK = max( nVec1[2], nVec2[2]) ;
double dMinZ = ( nMinK + 0.5) * m_dStep ;
double dMaxZ = ( nMaxK + 0.5) * m_dStep ;
ptInt.x = ( nVec1[0] + 0.5) * m_dStep ;
ptInt.y = ( nVec1[1] + 0.5) * m_dStep ;
unsigned int nDexel = nVec1[1] * m_nNx[0] + nVec1[0] ;
size_t nSize = m_Values[0][nDexel].size() ;
bool bFound = false ;
for ( size_t k = 0 ; k < nSize ; k += 2) {
double dz1 = m_Values[0][nDexel][k].dZVal ;
double dz2 = m_Values[0][nDexel][k+1].dZVal ;
if ( dz1 < dMinZ - EPS_SMALL && dz2 > dMinZ - EPS_SMALL && dz2 < dMaxZ + EPS_SMALL) {
ptInt.z = dz2 ;
vtNormal = m_Values[0][nDexel][k+1].vtN ;
bFound = true ;
break ;
}
else if ( dz1 > dMinZ - EPS_SMALL && dz1 < dMaxZ + EPS_SMALL && dz2 > dMaxZ + EPS_SMALL) {
ptInt.z = dz1 ;
vtNormal = m_Values[0][nDexel][k].vtN ;
bFound = true ;
break ;
}
}
if ( ! bFound) {
ptInt.z = ( dMinZ + dMaxZ) / 2 ;
// Versore Normale ???
}
}
return true ;
}