EgtGeomKernel 2.1e3 :

- modifiche a Zmap per intersezioni con linee e piani.
This commit is contained in:
Dario Sassi
2019-05-13 06:36:58 +00:00
parent 4e8508f731
commit 90df6d3a7a
7 changed files with 758 additions and 768 deletions
+368 -540
View File
@@ -19,11 +19,47 @@
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSphere.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
#include "/EgtDev/Include/EgtNumUtils.h"
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
static bool
TestIntersPlaneBox( const BBox3d& b3Box, const Plane3d& plPlane)
{
// Calcolo le distanze con segno dei punti dal piano
Point3d ptE0 = b3Box.GetMin() ;
double dDist0 = DistPointPlane( ptE0, plPlane) ;
Point3d ptE1( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMin().z) ;
double dDist1 = DistPointPlane( ptE1, plPlane) ;
Point3d ptE2( b3Box.GetMax().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist2 = DistPointPlane( ptE2, plPlane) ;
Point3d ptE3( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist3 = DistPointPlane( ptE3, plPlane) ;
Point3d ptE4( b3Box.GetMin().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist4 = DistPointPlane( ptE4, plPlane) ;
Point3d ptE5( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist5 = DistPointPlane( ptE5, plPlane) ;
Point3d ptE6 = b3Box.GetMax() ;
double dDist6 = DistPointPlane( ptE6, plPlane) ;
Point3d ptE7( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMax().z) ;
double dDist7 = DistPointPlane( ptE7, plPlane) ;
// Distanze tutte positive
if ( dDist0 > EPS_SMALL && dDist1 > EPS_SMALL && dDist2 > EPS_SMALL && dDist3 > EPS_SMALL &&
dDist4 > EPS_SMALL && dDist5 > EPS_SMALL && dDist6 > EPS_SMALL && dDist7 > EPS_SMALL)
return false ;
// Distanze tutte negative
if ( dDist0 < - EPS_SMALL && dDist1 < - EPS_SMALL && dDist2 < - EPS_SMALL && dDist3 < - EPS_SMALL &&
dDist4 < - EPS_SMALL && dDist5 < - EPS_SMALL && dDist6 < - EPS_SMALL && dDist7 < - EPS_SMALL)
return false ;
// Il piano interseca il box
return true ;
}
//----------------------------------------------------------------------------
// Punti e vettore devono esse espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di tale sistema di riferimento.
@@ -31,7 +67,6 @@ using namespace std ;
bool
VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const
{
// Il box è allineato agli assi
double dU1, dU2 ;
return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ;
}
@@ -219,7 +254,7 @@ VolZmap::GetDepth( const Point3d& ptPLoc, const Vector3d& vtDLoc, double& dInLen
vtD.ToLoc( m_MapFrame) ;
if ( bExact && m_nMapNum == 3)
return GetDepthWithVoxel( ptP, vtD, dInLength, dOutLength, true) ;
return GetDepthWithVoxel( ptP, vtD, dInLength, dOutLength) ;
else
return GetDepthWithDexel( ptP, vtD, dInLength, dOutLength) ;
}
@@ -385,286 +420,73 @@ VolZmap::GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtV, double& dIn
//----------------------------------------------------------------------------
// Calcola la profondità del materiale usando i triangoli della rappresentazione grafica.
// Punto e versore devono essere espressi nel sistema di riferimento Zmap.
// Se si vuole che vengano utilizzati i triangoli con sharp-featue bEnh deve valere true, false altrimenti.
// InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap)
// OutLength = distanza di uscita.
bool
VolZmap::GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bEnh) const
VolZmap::GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength) const
{
// Serve che punto e vettore siano espressi sia nel sistema intrinseco dello Zmap (m_MapFrame) sia in quello
// in cui esso è immerso; questo perché i dexel sono espressi in quello intrinseco e i triangoli in quello
// in cui esso è immerso.
Point3d ptOutP = ptP ;
Vector3d vtOutD = vtD ;
ptOutP.ToGlob( m_MapFrame) ;
vtOutD.ToGlob( m_MapFrame) ;
// Intersezione fra semiretta e BBox dello Zmap
double dU1, dU2 ;
bool bLineBBoxInters = IntersLineZMapBBox( ptP, vtD, dU1, dU2) && ( dU1 > 0 || dU2 > 0) ;
ILZIVECTOR vIntersInfo ;
if ( ! GetLineIntersection( ptP, vtD, vIntersInfo))
return false ;
// Semiretta esterna al box dello Zmap quindi esterna anche allo Zmap
if ( ! bLineBBoxInters) {
dInLength = - 2 ;
dOutLength = - 2 ;
if ( vIntersInfo.empty()) {
dInLength = - 2. ;
dOutLength = - 2. ;
return true ;
}
// Lancio eventuale aggiornamento pendente della grafica
if ( m_nMapNum == 1)
UpdateSingleMapGraphics() ;
else
UpdateTripleMapGraphics() ;
// Determino il voxel di partenza
int nVoxI, nVoxJ, nVoxK ;
if ( ! GetPointVoxel( ptP, nVoxI, nVoxJ, nVoxK)) {
if ( ! GetPointVoxel( ptP + dU1 * vtD, nVoxI, nVoxJ, nVoxK))
return false ;
}
// Incrementi degli indici per seguire la retta
int nDeltaI = ( vtD.x > 0 ? 1 : ( vtD.x < 0 ? - 1 : 0)) ;
int nDeltaJ = ( vtD.y > 0 ? 1 : ( vtD.y < 0 ? - 1 : 0)) ;
int nDeltaK = ( vtD.z > 0 ? 1 : ( vtD.z < 0 ? - 1 : 0)) ;
// Scelgo i piani del voxel con cui intersecare la retta, per determinare il voxel successivo
int nPlaneI = ( vtD.x >= 0 ? 1 : 0) ;
int nPlaneJ = ( vtD.y >= 0 ? 1 : 0) ;
int nPlaneK = ( vtD.z >= 0 ? 1 : 0) ;
// Ciclo sui voxel
vector<VoxelIndexes> vVox ;
while ( IsValidVoxel( nVoxI, nVoxJ, nVoxK)) {
// Estremi della diagonale del voxel corrente
Point3d ptMin( ( nVoxI * N_DEXVOXRATIO + 0.5) * m_dStep,
( nVoxJ * N_DEXVOXRATIO + 0.5) * m_dStep,
( nVoxK * N_DEXVOXRATIO + 0.5) * m_dStep) ;
Point3d ptMax( ( ( nVoxI + 1) * N_DEXVOXRATIO + 0.5) * m_dStep,
( ( nVoxJ + 1) * N_DEXVOXRATIO + 0.5) * m_dStep,
( ( nVoxK + 1) * N_DEXVOXRATIO + 0.5) * m_dStep) ;
// Studio il voxel corrente
if ( IntersLineBox( ptP, vtD, ptMin, ptMax)) {
int nCurVoxIndex = CalcIndex( nVoxI, nVoxJ, nVoxK) ;
if ( nCurVoxIndex != 0 && nCurVoxIndex != 255) {
VoxelIndexes NewVox ;
NewVox.nI = nVoxI ;
NewVox.nJ = nVoxJ ;
NewVox.nK = nVoxK ;
vVox.emplace_back( NewVox) ;
}
}
// Interseco la retta con i piani frontiera del voxel
double dMaxTX = ( abs( vtD.x) > EPS_ZERO ?
abs( ( ( ( nVoxI + nPlaneI) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.x) / vtD.x) : INFINITO) ;
double dMaxTY = ( abs( vtD.y) > EPS_ZERO ?
abs( ( ( ( nVoxJ + nPlaneJ) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.y) / vtD.y) : INFINITO) ;
double dMaxTZ = ( abs( vtD.z) > EPS_ZERO ?
abs( ( ( ( nVoxK + nPlaneK) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.z) / vtD.z) : INFINITO) ;
// Determino gli incrementi
if ( dMaxTX < dMaxTY) {
if ( dMaxTX < dMaxTZ)
nVoxI += nDeltaI ;
else
nVoxK += nDeltaK ;
}
else {
if ( dMaxTY < dMaxTZ)
nVoxJ += nDeltaJ ;
else
nVoxK += nDeltaK ;
}
}
// Dati dell'intersezione
struct LineTriaInt {
int nNum ;
double dPar1 ;
double dPar2 ;
double dDot ;
LineTriaInt( void) : nNum( 0) {}
LineTriaInt( double dP, double dD) : nNum( 1), dPar1( dP), dDot( dD) {}
LineTriaInt( double dP1, double dP2, double dD)
: nNum( 2), dPar1( dP1), dPar2( dP2), dDot( dD) {}
} ;
vector<LineTriaInt> vInt ;
int nPrevBlockN = - 1 ;
// Ciclo sui voxel
for ( int nVx = 0 ; nVx < int( vVox.size()) ; ++ nVx) {
int nCurVoxIJK[3] = { vVox[nVx].nI, vVox[nVx].nJ, vVox[nVx].nK} ;
int nCurBlockIJK[3] ;
if ( GetVoxelBlockIJK( nCurVoxIJK, nCurBlockIJK)) {
int nCurBlockN ;
GetBlockNFromIJK( nCurBlockIJK, nCurBlockN) ;
// Triangoli sharp fra blocchi
for ( int nBlVx = 0 ; nBlVx < int( m_InterBlockSharpTria[nCurBlockN].size()) ; ++ nBlVx) {
if ( m_InterBlockSharpTria[nCurBlockN][nBlVx].i == nCurVoxIJK[0] &&
m_InterBlockSharpTria[nCurBlockN][nBlVx].j == nCurVoxIJK[1] &&
m_InterBlockSharpTria[nCurBlockN][nBlVx].k == nCurVoxIJK[2]) {
for ( int nBlCm = 0 ; nBlCm < int( m_InterBlockSharpTria[nCurBlockN][nBlVx].vCompoTria.size()) ; ++ nBlCm) {
for ( int nBlTr = 0 ; nBlTr < int( m_InterBlockSharpTria[nCurBlockN][nBlVx].vCompoTria[nBlCm].size()) ; ++ nBlTr) {
Triangle3d CurrTria = m_InterBlockSharpTria[nCurBlockN][nBlVx].vCompoTria[nBlCm][nBlTr] ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptOutP, vtOutD, 1.5 * dU2, CurrTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT ||
nIntType == ILTT_EDGE ||
nIntType == ILTT_IN) {
vInt.emplace_back( ( ptLineTria1 - ptOutP) * vtOutD, vtOutD * CurrTria.GetN()) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptOutP) * vtOutD ;
double dP2 = ( ptLineTria2 - ptOutP) * vtOutD ;
double dD = vtOutD * CurrTria.GetN() ;
vInt.emplace_back( ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1), dD) ;
}
}
}
}
}
// Triangoli sharp interni
for ( int nBlVx = 0 ; nBlVx < int( m_BlockSharpTria[nCurBlockN].size()) ; ++ nBlVx) {
if ( m_BlockSharpTria[nCurBlockN][nBlVx].i == nCurVoxIJK[0] &&
m_BlockSharpTria[nCurBlockN][nBlVx].j == nCurVoxIJK[1] &&
m_BlockSharpTria[nCurBlockN][nBlVx].k == nCurVoxIJK[2]) {
for ( int nBlCm = 0 ; nBlCm < int( m_BlockSharpTria[nCurBlockN][nBlVx].vCompoTria.size()) ; ++ nBlCm) {
for ( int nBlTr = 0 ; nBlTr < int( m_BlockSharpTria[nCurBlockN][nBlVx].vCompoTria[nBlCm].size()) ; ++ nBlTr) {
Triangle3d CurrTria = m_BlockSharpTria[nCurBlockN][nBlVx].vCompoTria[nBlCm][nBlTr] ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptOutP, vtOutD, 1.5 * dU2, CurrTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT ||
nIntType == ILTT_EDGE ||
nIntType == ILTT_IN) {
vInt.emplace_back( ( ptLineTria1 - ptOutP) * vtOutD, vtOutD * CurrTria.GetN()) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptOutP) * vtOutD ;
double dP2 = ( ptLineTria2 - ptOutP) * vtOutD ;
double dD = vtOutD * CurrTria.GetN() ;
vInt.emplace_back( ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1), dD) ;
}
}
}
}
}
// Triangoli smooth
for ( int nBlVx = 0 ; nBlVx < int( m_BlockSmoothTria[nCurBlockN].size()) ; ++ nBlVx) {
if ( m_BlockSmoothTria[nCurBlockN][nBlVx].i == nCurVoxIJK[0] &&
m_BlockSmoothTria[nCurBlockN][nBlVx].j == nCurVoxIJK[1] &&
m_BlockSmoothTria[nCurBlockN][nBlVx].k == nCurVoxIJK[2]) {
for ( int nBlTr = 0 ; nBlTr < int( m_BlockSmoothTria[nCurBlockN][nBlVx].vTria.size()) ; ++ nBlTr) {
Triangle3d CurrTria = m_BlockSmoothTria[nCurBlockN][nBlVx].vTria[nBlTr] ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptOutP, vtOutD, 1.5 * dU2, CurrTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT ||
nIntType == ILTT_EDGE ||
nIntType == ILTT_IN) {
vInt.emplace_back( ( ptLineTria1 - ptOutP) * vtOutD, vtOutD * CurrTria.GetN()) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptOutP) * vtOutD ;
double dP2 = ( ptLineTria2 - ptOutP) * vtOutD ;
double dD = vtOutD * CurrTria.GetN() ;
vInt.emplace_back( ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1), dD) ;
}
}
}
}
// Triangoli grandi
if ( nCurBlockN != nPrevBlockN) {
for ( int nBlTr = 0 ; nBlTr < int( m_BlockBigTria[nCurBlockN].size()) ; ++ nBlTr) {
Triangle3d CurrTria = m_BlockBigTria[nCurBlockN][nBlTr] ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptOutP, vtOutD, 1.5 * dU2, CurrTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT ||
nIntType == ILTT_EDGE ||
nIntType == ILTT_IN) {
vInt.emplace_back( ( ptLineTria1 - ptOutP) * vtOutD, vtOutD * CurrTria.GetN()) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptOutP) * vtOutD ;
double dP2 = ( ptLineTria2 - ptOutP) * vtOutD ;
double dD = vtOutD * CurrTria.GetN() ;
vInt.emplace_back( ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1), dD) ;
}
}
nPrevBlockN = nCurBlockN ;
}
}
}
// Ordino le intersezioni in base al parametro distanza con segno da ptP
sort( vInt.begin(), vInt.end(),
[]( const LineTriaInt& a, const LineTriaInt& b)
{ double dFP = ( a.nNum == 2 ? 0.5 * ( a.dPar1 + a.dPar2) : a.dPar1) ;
double dLP = ( b.nNum == 2 ? 0.5 * ( b.dPar1 + b.dPar2) : b.dPar1) ;
return ( dLP > dFP) ; }) ;
// Inizializzo le distanze di ingresso e uscita:
// dInLength diminuisce, dOutLength aumenta.
dInLength = INFINITO ;
dOutLength = - INFINITO ;
// Porto nel riferimento intrinseco dello Zmap
Vector3d vtOutD = vtD ;
vtOutD.ToGlob( m_MapFrame) ;
// Inizializzo le distanze di ingresso e uscita:
// dInLength diminuisce, dOutLength aumenta.
dInLength = INFINITO ;
dOutLength = -INFINITO ;
int nFirstPosN ;
int nN = 0 ;
for ( ; nN < int( vInt.size()) ; ++ nN) {
if ( vInt[nN].dPar1 > - EPS_SMALL) {
for ( ; nN < int( vIntersInfo.size()) ; ++ nN) {
if ( vIntersInfo[nN].dU > - EPS_SMALL) {
nFirstPosN = nN ;
break ;
break ;
}
}
if ( nN == int( vInt.size())) {
if ( nN == int( vIntersInfo.size())) {
dInLength = - 2 ;
dOutLength = - 2 ;
return true ;
}
if ( nFirstPosN > 0) {
if ( vInt[nFirstPosN - 1].dDot < EPS_ZERO)
dInLength = -1 ;
int nVoxIJK[3] ;
GetBlockIJKFromN( vIntersInfo[0].nVox, nVoxIJK) ;
if ( nFirstPosN > 0) {
if ( vIntersInfo[nFirstPosN - 1].trTria.GetN() * vtOutD < EPS_ZERO)
dInLength = - 1 ;
}
else if ( nFirstPosN == 0) {
if ( vInt[nFirstPosN].dDot > EPS_ZERO)
dInLength = -1 ;
else if ( GetPointVoxel( ptP, nVoxI, nVoxJ, nVoxK)) {
int nCubeType = CalcIndex( nVoxI, nVoxJ, nVoxK) ;
if ( vIntersInfo[nFirstPosN].trTria.GetN() * vtOutD > EPS_ZERO)
dInLength = - 1 ;
else if ( GetPointVoxel( ptP, nVoxIJK[0], nVoxIJK[1], nVoxIJK[2])) {
int nCubeType = CalcIndex( nVoxIJK[0], nVoxIJK[1], nVoxIJK[2]) ;
if ( nCubeType == 255)
dInLength = -1 ;
dInLength = - 1 ;
}
}
for ( int nN = nFirstPosN ; nN < int( vInt.size()) ; ++ nN) {
if ( vInt[nN].dDot > - EPS_ZERO) {
if ( vInt[nN].nNum == 2 && dOutLength < vInt[nN].dPar2)
dOutLength = vInt[nN].dPar2 ;
else if ( dOutLength < vInt[nN].dPar1)
dOutLength = vInt[nN].dPar1 ;
}
if ( vInt[nN].dDot < EPS_ZERO &&
dInLength > vInt[nN].dPar1)
dInLength = vInt[nN].dPar1 ;
for ( int nN = nFirstPosN ; nN < int( vIntersInfo.size()) ; ++ nN) {
if ( vIntersInfo[nN].trTria.GetN() * vtOutD > - EPS_ZERO) {
if ( ( vIntersInfo[nN].nILTT == ILTT_SEGM || vIntersInfo[nN].nILTT == ILTT_SEGM_ON_EDGE) &&
dOutLength < vIntersInfo[nN].dU2)
dOutLength = vIntersInfo[nN].dU2 ;
else if ( dOutLength < vIntersInfo[nN].dU)
dOutLength = vIntersInfo[nN].dU ;
}
if ( vIntersInfo[nN].trTria.GetN() * vtOutD < EPS_ZERO &&
dInLength > vIntersInfo[nN].dU)
dInLength = vIntersInfo[nN].dU ;
}
return true ;
@@ -1502,6 +1324,193 @@ VolZmap::GetPartVolume( int nPart, double& dVol) const
return true ;
}
//----------------------------------------------------------------------------
// La retta deve essere espressa nel sistema Zmap.
// Per riferimento viene restituito un vettore di intersezioni della retta con i triangoli della superficie del solido.
// Si restituisce false in caso di errore, true altrimenti.
bool
VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const
{
// Calcolo punto e vettore espressi nel riferimento intrinseco dello Zmap
Point3d ptLocP = ptP ;
Vector3d vtLocD = vtD ;
ptLocP.ToLoc( m_MapFrame) ;
vtLocD.ToLoc( m_MapFrame) ;
// Intersezione fra semiretta e BBox dello Zmap
double dU1, dU2 ;
bool bLineBBoxInters = IntersLineZMapBBox( ptLocP, vtLocD, dU1, dU2) && ( dU1 > 0 || dU2 > 0) ;
// Semiretta esterna al box dello Zmap quindi esterna anche allo Zmap
if ( ! bLineBBoxInters)
return true ;
// Lancio eventuale aggiornamento pendente della grafica
if ( m_nMapNum == 1)
UpdateSingleMapGraphics() ;
else
UpdateTripleMapGraphics() ;
// Ciclo sui blocchi
for ( int nB = 0 ; nB < m_nNumBlock ; ++ nB) {
// Determino indici IJK del blocco; se non trovo il blocco, errore
int nBlockIJK[3] ;
if ( ! GetBlockIJKFromN( nB, nBlockIJK))
return false ;
// Costruisco il bounding-box del blocco; se non è possibile, errore
BBox3d b3BlockBox ;
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( IntersLineBox( ptLocP, vtLocD, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
// Box del voxel
BBox3d b3Vox ;
int nCurVoxIJK[3] = { m_BlockSmoothTria[nB][nV].i,
m_BlockSmoothTria[nB][nV].j,
m_BlockSmoothTria[nB][nV].k } ;
GetVoxelBox( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! IntersLineBox( ptLocP, vtLocD, b3Vox.GetMin(), b3Vox.GetMax()))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
if ( ! trTria.Validate( true))
continue ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptP, vtD, 1.5 * dU2, trTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtD,
nNumVox, nB, ptLineTria1, trTria) ;
}
// altrimenti ci sono due intersezioni
else {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtD ;
double dP2 = ( ptLineTria2 - ptP) * vtD ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
}
}
}
// Triangoli sharp interni al blocco
for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) {
int nCurVoxIJK[3] = { m_BlockSharpTria[nB][nV].i,
m_BlockSharpTria[nB][nV].j,
m_BlockSharpTria[nB][nV].k } ;
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
if ( ! trTria.Validate( true))
continue ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptP, vtD, 1.5 * dU2, trTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtD,
nNumVox, nB, ptLineTria1, trTria) ;
}
// altrimenti ci sono due intersezioni
else {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtD ;
double dP2 = ( ptLineTria2 - ptP) * vtD ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
}
}
}
}
// Triangoli grandi del blocco
for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) {
Triangle3d trTria = m_BlockBigTria[nB][nT] ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptP, vtD, 1.5 * dU2, trTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtD,
-1, nB, ptLineTria1, trTria) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptP) * vtD ;
double dP2 = ( ptLineTria2 - ptP) * vtD ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
-1, nB, ptLineTria1, ptLineTria2, trTria) ;
}
}
}
// In ogni caso valuto i triangoli sharp fra blocchi
for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) {
int nCurVoxIJK[3] = { m_InterBlockSharpTria[nB][nV].i,
m_InterBlockSharpTria[nB][nV].j,
m_InterBlockSharpTria[nB][nV].k } ;
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
if ( ! trTria.Validate( true))
continue ;
Point3d ptLineTria1, ptLineTria2 ;
// Studio dell'intersezione della retta con il triangolo corrente
int nIntType = IntersLineTria( ptP, vtD, 1.5 * dU2, trTria, ptLineTria1, ptLineTria2) ;
// Se non ci sono intersezioni passo al prossimo triangolo
if ( nIntType == ILTT_NO)
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtD,
nNumVox, nB, ptLineTria1, trTria) ;
}
// altrimenti ci sono due intersezioni
else {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtD ;
double dP2 = ( ptLineTria2 - ptP) * vtD ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
}
}
}
}
}
// Ordino le intersezioni in base al parametro distanza con segno da ptP
sort( vIntersInfo.begin(), vIntersInfo.end(),
[]( const IntLineZmapInfo& a, const IntLineZmapInfo& b)
{ double dFP = (( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? 0.5 * ( a.dU + a.dU2) : a.dU) ;
double dLP = (( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? 0.5 * ( b.dU + b.dU2) : b.dU) ;
return ( dLP > dFP) ; }) ;
return true ;
}
//----------------------------------------------------------------------------
// Il piano è espresso nel sistema locale, la funzione lo esprime nel sistema Zmap.
// I loop della flat region ottenuta dall'intersezione vengono salvati nello
@@ -1513,45 +1522,115 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
// Verifico validità parametri
if ( ! plPlane.IsValid())
return false ;
// Porto il piano nel sistema Zmap
Plane3d plPlaneL = plPlane ;
plPlaneL.ToLoc( m_MapFrame) ;
// Vettore del piano
Vector3d vtNL = plPlaneL.GetVersN() ;
Plane3d plPlaneLoc = plPlane ;
plPlaneLoc.ToLoc( m_MapFrame) ;
// Se il piano non interseca il bounding box del solido, abbiamo finito
if ( ! TestIntersPlaneZmapBBox( plPlaneL))
// Se non c'è intersezione fra piano e bounding-box del solido, ho finito.
if ( ! TestIntersPlaneZmapBBox( plPlaneLoc))
return true ;
// Cerco la mappa con i dexel più perpendicolari al piano e valuto
// se il versore del piano è equiverso o controverso ai dexel.
int nGrid = 0 ;
int nSign = ( vtNL.z > 0 ? 1 : - 1) ;
if ( abs( vtNL.x) > abs( vtNL.y) && abs( vtNL.x) > abs( vtNL.z)) {
nGrid = 1 ;
nSign = ( vtNL.x > 0 ? 1 : - 1) ;
}
else if ( abs( vtNL.y) > abs( vtNL.x) && abs( vtNL.y) > abs( vtNL.z)) {
nGrid = 2 ;
nSign = ( vtNL.y > 0 ? 1 : - 1) ;
}
// Ciclo sulle celle
// Lancio eventuale aggiornamento pendente della grafica
if ( m_nMapNum == 1)
UpdateSingleMapGraphics() ;
else
UpdateTripleMapGraphics() ;
// Vettore di segmenti
vector<CurveLine> vLine ;
for ( int ni = - 1 ; ni < int( m_nNx[nGrid]) ; ++ ni) {
for ( int nj = - 1 ; nj < int( m_nNy[nGrid]) ; ++ nj) {
ProcessCell( nGrid, ni, nj, plPlaneL, vLine) ;
// Ciclo sui blocchi
for ( int nB = 0 ; nB < m_nNumBlock ; ++ nB) {
// Determino indici IJK del blocco; Se non trovo il blocco, errore
int nBlockIJK[3] ;
if ( ! GetBlockIJKFromN( nB, nBlockIJK))
return false ;
// Costruisco il bounding-bx del blocco; se non è possiblie, errore
BBox3d b3BlockBox ;
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( TestIntersPlaneBox( b3BlockBox, plPlaneLoc)) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
// Box del voxel
BBox3d b3Vox ;
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! TestIntersPlaneBox(b3Vox, plPlaneLoc))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
if ( cvLine.Set( ptSt, ptEn))
vLine.emplace_back( cvLine) ;
}
}
}
// Triangoli sharp interni al blocco
for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) {
// Box del voxel
BBox3d b3Vox ;
GetVoxelBox( m_BlockSharpTria[nB][nV].i, m_BlockSharpTria[nB][nV].j, m_BlockSharpTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
if (nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
if ( cvLine.Set(ptSt, ptEn))
vLine.emplace_back( cvLine) ;
}
}
}
}
// Triangoli grandi del blocco
for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) {
Triangle3d trTria = m_BlockBigTria[nB][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
if ( cvLine.Set(ptSt, ptEn))
vLine.emplace_back( cvLine) ;
}
}
}
// In ogni caso valuto i triangoli sharp fra blocchi
for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) {
// Ciclo sulle componenti connesse
for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
Point3d ptSt, ptEn ;
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
// Costruisco il tratto di curva
CurveLine cvLine ;
if ( cvLine.Set(ptSt, ptEn))
vLine.emplace_back( cvLine) ;
}
}
}
}
}
// Creo i loop
ChainCurves LoopCreator ;
LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ;
// Carico le curve per concatenarle
// Carico le curve per concatenarle
for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) {
Point3d ptSt = vLine[nCv].GetStart() ;
Point3d ptEn = vLine[nCv].GetEnd() ;
Vector3d vtDir ; vLine[nCv].GetStartDir( vtDir) ;
Point3d ptEn = vLine[nCv].GetEnd() ;
Vector3d vtDir; vLine[nCv].GetStartDir(vtDir) ;
LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ;
}
// Recupero i concatenamenti
@@ -1563,266 +1642,15 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
return false ;
for ( auto i : vIds) {
// Aggiungo la linea alla curva composta.
if ( ! pLoop->AddCurve( vLine[i-1], true, EPS_SMALL))
if ( ! pLoop->AddCurve( vLine[i - 1], true, 10 * EPS_SMALL))
return false ;
}
pLoop->SetExtrusion( vtNL) ;
pLoop->ToGlob( m_MapFrame) ;
// Se normali controverse, devo invertire il verso del loop.
if ( nSign < 0)
pLoop->Invert() ;
// eseguo approssimazione
PolyLine PL ;
if ( ! pLoop->ApproxWithLines( m_dStep, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL) ||
! pLoop->Clear() || ! pLoop->FromPolyLine( PL))
return false ;
pLoop->MergeCurves( m_dStep, ANG_TOL_STD_DEG) ;
// Inserisco la curva composita nella raccolta da ritornare
vpLoop.emplace_back( Release( pLoop)) ;
}
return true ;
}
//----------------------------------------------------------------------------
// Data una cella, identificata dal numero della sua griglia e dai suoi indici i,j
// all'interno della griglia, genera gli eventuali segmenti che costituiscono la curva
// corrispondente alla frontiera della regione di piano interna la solido.
// Se la griglia o la cella non è valida, la funzione restituisce false,
// altrimenti valuta la tipologia della cella e crea gli eventuali segmenti.
// Se il processo va a buon fine la funzione restituisce true.
bool
VolZmap::ProcessCell( int nGrid, int nCellI, int nCellJ, const Plane3d& plPlane, vector<CurveLine>& vLine) const
{
// Se la griglia non esiste vi è un errore
if ( nGrid < 0 || nGrid > 2)
return false ;
// Se la cella non esiste vi è un errore
if ( nCellI < - 1 || nCellI >= int( m_nNx[nGrid]) ||
nCellJ < - 1 || nCellJ >= int( m_nNy[nGrid]))
return false ;
// Determino la configurazione della cella
int nIndex = CalcIndexForPlaneCells( plPlane, nGrid, nCellI, nCellJ) ;
// Tabella segmenti
static int nLineTable[16][5] = {
{ -1, -1, -1, -1, -1},
{ 0, 3, -1, -1, -1},
{ 1, 0, -1, -1, -1},
{ 1, 3, -1, -1, -1},
{ 2, 1, -1, -1, -1},
{ 0, 1, 2, 3, -1},
{ 2, 0, -1, -1, -1},
{ 2, 3, -1, -1, -1},
{ 3, 2, -1, -1, -1},
{ 0, 2, -1, -1, -1},
{ 1, 2, 3, 0, -1},
{ 1, 2, -1, -1, -1},
{ 3, 1, -1, -1, -1},
{ 0, 1, -1, -1, -1},
{ 3, 0, -1, -1, -1},
{ -1, -1, -1, -1, -1}
} ;
// Tabella dei punti medi dei segmenti: le righe rappresentano
// il numero di segmento (0, 1, 2, 3) le colonne rappresentano
// i e j.
static double dDeltaIJ[4][2] = {
{ 0.5, 0},
{ 1, 0.5},
{ 0.5, 1},
{ 0, 0.5}
} ;
// Se la cella è di frontiera costruisco i segmenti della curva
if ( nIndex != 0 && nIndex != 15) {
// Ciclo su tutti gli spigoli della cella che vengono attraversati dalla curva.
for ( int nEdge = 0 ; nLineTable[nIndex][nEdge] != -1 ; nEdge += 2) {
int nStEdge = nLineTable[nIndex][nEdge] ;
int nEnEdge = nLineTable[nIndex][nEdge + 1] ;
double nStDeltaI = dDeltaIJ[nStEdge][0] ;
double nStDeltaJ = dDeltaIJ[nStEdge][1] ;
double nEnDeltaI = dDeltaIJ[nEnEdge][0] ;
double nEnDeltaJ = dDeltaIJ[nEnEdge][1] ;
if ( nGrid == 0) {
// Punti sulla griglia
Point3d ptGrSt( ( nCellI + nStDeltaI + 0.5) * m_dStep, ( nCellJ + nStDeltaJ + 0.5) * m_dStep, 0) ;
Point3d ptGrEn( ( nCellI + nEnDeltaI + 0.5) * m_dStep, ( nCellJ + nEnDeltaJ + 0.5) * m_dStep, 0) ;
// Corrispondenti punti sul piano
Point3d ptSt, ptEn ;
if ( IntersLinePlane( ptGrSt, Z_AX, 10, plPlane, ptSt, false) &&
IntersLinePlane( ptGrEn, Z_AX, 10, plPlane, ptEn, false)) {
// Costruisco il tratto di curva
CurveLine cvLine ;
cvLine.Set( ptSt, ptEn) ;
vLine.emplace_back( cvLine) ;
}
}
else if ( nGrid == 1) {
// Punti sulla griglia
Point3d ptGrSt( 0, ( nCellI + nStDeltaI + 0.5) * m_dStep, ( nCellJ + nStDeltaJ + 0.5) * m_dStep) ;
Point3d ptGrEn( 0, ( nCellI + nEnDeltaI + 0.5) * m_dStep, ( nCellJ + nEnDeltaJ + 0.5) * m_dStep) ;
// Corrispondenti punti sul piano
Point3d ptSt, ptEn ;
if ( IntersLinePlane( ptGrSt, X_AX, 10, plPlane, ptSt, false) &&
IntersLinePlane( ptGrEn, X_AX, 10, plPlane, ptEn, false)) {
// Costruisco il tratto di curva
CurveLine cvLine ;
cvLine.Set( ptSt, ptEn) ;
vLine.emplace_back( cvLine) ;
}
}
else {
// Punti sulla griglia
Point3d ptGrSt( ( nCellJ + nStDeltaJ + 0.5) * m_dStep, 0, ( nCellI + nStDeltaI + 0.5) * m_dStep) ;
Point3d ptGrEn( ( nCellJ + nEnDeltaJ + 0.5) * m_dStep, 0, ( nCellI + nEnDeltaI + 0.5) * m_dStep) ;
// Corrispondenti punti sul piano
Point3d ptSt, ptEn ;
if ( IntersLinePlane( ptGrSt, Y_AX, 10, plPlane, ptSt, false) &&
IntersLinePlane( ptGrEn, Y_AX, 10, plPlane, ptEn, false)) {
// Costruisco il tratto di curva
CurveLine cvLine ;
cvLine.Set( ptSt, ptEn) ;
vLine.emplace_back( cvLine) ;
}
}
}
pLoop->SetExtrusion( plPlane.GetVersN()) ;
pLoop->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
// Inserisco la curva composita nella raccolta da ritornare
vpLoop.emplace_back( Release( pLoop)) ;
}
return true ;
}
//----------------------------------------------------------------------------
// Dato un dexel, identificato dal numero della sua griglia e dai suoi indici,
// determina se un suo intervallo attraversa il piano dato.
// Il numero di griglia e gli indici del dexel devono essere validi, se
// non lo sono, la funzione restituisce false, altrimenti cerca un
// tratto di dexel che intersechi il piano, se lo trova restituisce true,
// false altrimenti.
bool
VolZmap::InOut( const Plane3d& plPlane, int nGrid, int nI, int nJ) const
{
// Se la griglia non esiste, vi è un errore.
if ( nGrid < 0 || nGrid > 2)
return false ;
// Se gli indici sono di frontiera per lo
// Zmap o non esistono, non sono interni.
if ( nI <= - 1 || nI >= int( m_nNx[nGrid]) ||
nJ <= - 1 || nJ >= int( m_nNy[nGrid]))
return false ;
// Numero del dexel
int nDex = nJ * m_nNx[nGrid] + nI ;
// Ciclo sui segmenti del dexel
bool bNotFound = true ;
for ( int nK = 0 ; nK < int( m_Values[nGrid][nDex].size()) ; ++ nK) {
if ( nGrid == 0) {
// Punti estremi del segmento
Point3d ptSt( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, m_Values[nGrid][nDex][nK].dMin) ;
Point3d ptEn( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, m_Values[nGrid][nDex][nK].dMax) ;
// Se il segmento interseca il piano abbiamo finito
Point3d ptInt ;
if ( IntersLinePlane( ptSt, ptEn, plPlane, ptInt))
return true ;
}
else if ( nGrid == 1) {
// Punti estremi del segmento
Point3d ptSt( m_Values[nGrid][nDex][nK].dMin, ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep) ;
Point3d ptEn( m_Values[nGrid][nDex][nK].dMax, ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep) ;
// Se il segmento interseca il piano abbiamo finito
Point3d ptInt ;
if ( IntersLinePlane( ptSt, ptEn, plPlane, ptInt))
return true ;
}
else {
// Punti estremi del segmento
Point3d ptSt( ( nJ + 0.5) * m_dStep, m_Values[nGrid][nDex][nK].dMin, ( nI + 0.5) * m_dStep) ;
Point3d ptEn( ( nJ + 0.5) * m_dStep, m_Values[nGrid][nDex][nK].dMax, ( nI + 0.5) * m_dStep) ;
// Se il segmento interseca il piano abbiamo finito
Point3d ptInt ;
if ( IntersLinePlane( ptSt, ptEn, plPlane, ptInt))
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
int
VolZmap::CalcIndexForPlaneCells( const Plane3d& plPlane, int nGrid, int nCellI, int nCellJ) const
{
int nIndex = 0 ;
if ( InOut( plPlane, nGrid, nCellI, nCellJ))
nIndex |= ( 1 << 0) ;
if ( InOut( plPlane, nGrid, nCellI + 1, nCellJ))
nIndex |= ( 1 << 1) ;
if ( InOut( plPlane, nGrid, nCellI + 1, nCellJ + 1))
nIndex |= ( 1 << 2) ;
if ( InOut( plPlane, nGrid, nCellI, nCellJ + 1))
nIndex |= ( 1 << 3) ;
return nIndex ;
}
//----------------------------------------------------------------------------
// dZ è una quota relativa alla mappa nGrid, se il dexel nDex esiste e
// dZ è interna a un suo intervallo restituisce true, false altrimenti.
bool
VolZmap::IsZInsideInterval( int nGrid, int nDex, double dZ) const
{
// Se la griglia non esiste vi è un errore.
if ( nGrid < 0 || nGrid > 2)
return false ;
// Se il dexel non esiste vi è un errore.
if ( nDex < 0 && nDex > int( m_Values[nGrid].size() - 1))
return false ;
// Valuto se dZ è interna a un intervallo.
for ( int nk = 0 ; nk < int( m_Values[nGrid][nDex].size()) ; ++ nk) {
double dZ1 = m_Values[nGrid][nDex][nk].dMin ;
double dZ2 = m_Values[nGrid][nDex][nk].dMax ;
// Se troviamo dZ in un intervallo abbiamo finito.
if ( dZ > dZ1 && dZ < dZ2)
return true ;
}
// dZ non sta in un intervallo.
return false ;
}
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
bool
TestIntersPlaneBox( const BBox3d& b3Box, const Plane3d& plPlane)
{
// Calcolo le distanze con segno dei punti dal piano
Point3d ptE0 = b3Box.GetMin() ;
double dDist0 = DistPointPlane( ptE0, plPlane) ;
Point3d ptE1( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMin().z) ;
double dDist1 = DistPointPlane( ptE1, plPlane) ;
Point3d ptE2( b3Box.GetMax().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist2 = DistPointPlane( ptE2, plPlane) ;
Point3d ptE3( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist3 = DistPointPlane( ptE3, plPlane) ;
Point3d ptE4( b3Box.GetMin().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist4 = DistPointPlane( ptE4, plPlane) ;
Point3d ptE5( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist5 = DistPointPlane( ptE5, plPlane) ;
Point3d ptE6 = b3Box.GetMax() ;
double dDist6 = DistPointPlane( ptE6, plPlane) ;
Point3d ptE7( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMax().z) ;
double dDist7 = DistPointPlane( ptE7, plPlane) ;
// Distanze tutte positive
if ( dDist0 > EPS_SMALL && dDist1 > EPS_SMALL && dDist2 > EPS_SMALL && dDist3 > EPS_SMALL &&
dDist4 > EPS_SMALL && dDist5 > EPS_SMALL && dDist6 > EPS_SMALL && dDist7 > EPS_SMALL)
return false ;
// Distanze tutte negative
if ( dDist0 < - EPS_SMALL && dDist1 < - EPS_SMALL && dDist2 < - EPS_SMALL && dDist3 < - EPS_SMALL &&
dDist4 < - EPS_SMALL && dDist5 < - EPS_SMALL && dDist6 < - EPS_SMALL && dDist7 < - EPS_SMALL)
return false ;
// Il piano interseca il box
return true ;
}