EgtGeomKernel 2.1e3 :
- modifiche a Zmap per intersezioni con linee e piani.
This commit is contained in:
+368
-540
@@ -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 ;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user