Files
EgtGeomKernel/VolZmap.cpp
T
Dario Sassi 2ed2a34d55 EgtGeomKernel :
- modifiche per DistPointLine con interfaccia portata in Include.
2024-05-22 08:19:10 +02:00

2410 lines
91 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 "VolZmap.h"
#include "GeoObjFactory.h"
#include "GdbGeo.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkUiUnits.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include <thread>
#include <future>
using namespace std ;
//----------------------------------------------------------------------------
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
//----------------------------------------------------------------------------
VolZmap::VolZmap(void)
: m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_bShowEdges( false),
m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( -1),
m_dToolLinTol( LIN_TOL_STD), m_dToolAngTolDeg( ANG_TOL_APPROX_DEG)
{
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
m_nNy[i] = 0 ;
m_nDim[i] = 0 ;
m_dMinZ[i] = 0 ;
m_dMaxZ[i] = 0 ;
m_nFracLin[i] = 0 ;
}
m_vTool.resize( 1) ;
}
//----------------------------------------------------------------------------
VolZmap::~VolZmap( void)
{
}
//----------------------------------------------------------------------------
bool
VolZmap::Clear( void)
{
m_nStatus = TO_VERIFY ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_dTempParam[0] = 0.0 ;
m_dTempParam[1] = 0.0 ;
m_bShowEdges = false ;
m_dStep = 10.0 ;
m_nMapNum = 0 ;
m_nShape = GENERIC ;
m_nVoxNumPerBlock = N_VOXBLOCK ;
m_nDexVoxRatio = 1 ;
m_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ;
m_MapFrame.Reset() ;
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
m_nNy[i] = 0 ;
m_nDim[i] = 0 ;
m_dMinZ[i] = 0 ;
m_dMaxZ[i] = 0 ;
m_Values[i].clear() ;
}
m_vTool.resize( 1) ;
m_nCurrTool = 0 ;
m_dToolLinTol = LIN_TOL_STD ;
m_dToolAngTolDeg = ANG_TOL_APPROX_DEG ;
// imposto ri-creazione della grafica
m_OGrMgr.Clear() ;
return true ;
}
//----------------------------------------------------------------------------
VolZmap*
VolZmap::Clone( void) const
{
// alloco oggetto
VolZmap* pVzm = new( nothrow) VolZmap ;
if ( pVzm != nullptr) {
if ( ! pVzm->CopyFrom( *this)) {
delete pVzm ;
return nullptr ;
}
}
return pVzm ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CopyFrom( const IGeoObj* pGObjSrc)
{
const VolZmap* pVzm = GetBasicVolZmap( pGObjSrc) ;
if ( pVzm == nullptr)
return false ;
return CopyFrom( *pVzm) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CopyFrom( const VolZmap& vzmSrc)
{
if ( &vzmSrc == this)
return true ;
m_nMapNum = vzmSrc.m_nMapNum ;
m_nShape = vzmSrc.m_nShape ;
m_nNumBlock = vzmSrc.m_nNumBlock ;
m_nVoxNumPerBlock = vzmSrc.m_nVoxNumPerBlock ;
m_nFracLin[0] = vzmSrc.m_nFracLin[0] ;
m_nFracLin[1] = vzmSrc.m_nFracLin[1] ;
m_nFracLin[2] = vzmSrc.m_nFracLin[2] ;
m_nConnectedCompoCount = vzmSrc.m_nConnectedCompoCount ;
m_MapFrame = vzmSrc.m_MapFrame ;
for ( int i = 0 ; i < int ( m_nMapNum) ; ++ i) {
m_nNx[i] = vzmSrc.m_nNx[i] ;
m_nNy[i] = vzmSrc.m_nNy[i] ;
m_nDim[i] = vzmSrc.m_nDim[i] ;
m_dMinZ[i] = vzmSrc.m_dMinZ[i] ;
m_dMaxZ[i] = vzmSrc.m_dMaxZ[i] ;
m_Values[i] = vzmSrc.m_Values[i] ;
}
m_dStep = vzmSrc.m_dStep ;
m_nStatus = vzmSrc.m_nStatus ;
m_nTempProp[0] = vzmSrc.m_nTempProp[0] ;
m_nTempProp[1] = vzmSrc.m_nTempProp[1] ;
m_dTempParam[0] = vzmSrc.m_dTempParam[0] ;
m_dTempParam[1] = vzmSrc.m_dTempParam[1] ;
m_bShowEdges = vzmSrc.m_bShowEdges ;
// dimensiono membri legati ai blocchi
m_BlockToUpdate = vzmSrc.m_BlockToUpdate ;
m_BlockUpdatingCounter = vzmSrc.m_BlockUpdatingCounter ;
m_InterBlockVox = vzmSrc.m_InterBlockVox ;
m_InterBlockOriginalSharpTria = vzmSrc.m_InterBlockOriginalSharpTria ;
m_InterBlockSharpTria = vzmSrc.m_InterBlockSharpTria ;
m_BlockSharpTria = vzmSrc.m_BlockSharpTria ;
m_BlockSmoothTria = vzmSrc.m_BlockSmoothTria ;
m_BlockBigTria = vzmSrc.m_BlockBigTria ;
m_SingleMapTria = vzmSrc.m_SingleMapTria ;
m_SliceXY = vzmSrc.m_SliceXY ;
m_SliceXZ = vzmSrc.m_SliceXZ ;
m_SliceYZ = vzmSrc.m_SliceYZ ;
// imposto ricalcolo grafica
ResetGraphics() ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetGraphics( void)
{
m_OGrMgr.Clear() ;
for ( int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount)
m_BlockToUpdate[nCount] = true ;
return true ;
}
//----------------------------------------------------------------------------
GeoObjType
VolZmap::GetType( void) const
{
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( VolZmap)) ;
}
//----------------------------------------------------------------------------
const string&
VolZmap::GetTitle( void) const
{
static const string sTitle = "VolZm" ;
return sTitle ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
// tipo
sOut += "Type=" + string( m_nMapNum == 1 ? "dexel" : "tridexel") + szNewLine ;
// forma
switch ( m_nShape) {
default : sOut += "Shape=generic" ; break ;
case BOX : sOut += "Shape=box" ; break ;
case EXTRUSION : sOut += "Shape=extrusion" ; break ;
}
sOut += szNewLine ;
// passo
sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 6) + szNewLine ;
// dimensioni
if ( m_nMapNum == 1)
sOut += "Dim=" + ToString( m_nDim[0]) +
"(" + ToString( m_nNx[0]) + "x" + ToString( m_nNy[0]) + ")" + szNewLine ;
else {
for ( int i = 0 ; i < m_nMapNum ; ++ i)
sOut += "Dim" + ToString( i+1) + "=" + ToString( m_nDim[i]) +
"(" + ToString( m_nNx[i]) + "x" + ToString( m_nNy[i]) + ")" + szNewLine ;
}
// numero di blocchi
sOut += "Blocks=" + ToString( m_nNumBlock) + " (" + ToString( m_nFracLin[0]) + "x" +
ToString( m_nFracLin[1]) + "x" + ToString( m_nFracLin[2]) + ")" + szNewLine ;
// dexel per voxel (DexToVoxRatio)
sOut += "DexVoxRat=" + ToString( m_nDexVoxRatio) + szNewLine ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetNgeId( void) const
{
return GEOOBJ_GETNGEID( VolZmap) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Save( NgeWriter& ngeOut) const
{
// numero di mappe
if ( ! ngeOut.WriteInt( m_nMapNum, ",", false))
return false ;
// numero di blocchi
if ( ! ngeOut.WriteInt( m_nNumBlock, ",", false))
return false ;
// numero di voxel per blocco
if ( ! ngeOut.WriteInt( m_nVoxNumPerBlock, ",", false))
return false ;
// numero di blocchi per ogni asse
for ( int i = 0 ; i < 3 ; ++ i) {
if ( ! ngeOut.WriteInt( m_nFracLin[i], ",", false))
return false ;
}
// DexVoxRatio
if ( ! ngeOut.WriteInt( m_nDexVoxRatio, ",", false))
return false ;
// numero di componenti connesse
if ( ! ngeOut.WriteInt( m_nConnectedCompoCount, ",", false))
return false ;
// passo di campionamento (distanza tra spilloni)
if ( ! ngeOut.WriteDouble( m_dStep, ";", true))
return false ;
// forma
if ( ! ngeOut.WriteInt( m_nShape, ";", true))
return false ;
// sistema di riferimento
if ( ! ngeOut.WriteFrame( m_MapFrame, ";", true))
return false ;
// per ogni mappa : numero di passi in X e Y e quote Z estremali
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
if ( ! ngeOut.WriteInt( m_nNx[i], ",", false))
return false ;
if ( ! ngeOut.WriteInt( m_nNy[i], ",", false))
return false ;
if ( ! ngeOut.WriteDouble( m_dMinZ[i], ",", false))
return false ;
if ( ! ngeOut.WriteDouble( m_dMaxZ[i], ";", true))
return false ;
}
// ciclo sulle mappe
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
// ciclo sui dexel
for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
// numero di estremi
int nDim = int( m_Values[i][j].size()) ;
if ( ! ngeOut.WriteInt( nDim, ":", false))
return false ;
// se dexel nullo
if ( nDim == 0) {
// scrivo un valore dummy
if ( ! ngeOut.WriteDouble( 0, ";", true))
return false ;
}
// altrimenti
else {
for ( int k = 0 ; k < nDim ; ++ k) {
if ( ! ngeOut.WriteDouble( m_Values[i][j][k].dMin, ",", false))
return false ;
if ( ! ngeOut.WriteInt( m_Values[i][j][k].nToolMin, ";", false))
return false ;
if ( ! ngeOut.WriteVector( m_Values[i][j][k].vtMinN, ";", false))
return false ;
if ( ! ngeOut.WriteDouble( m_Values[i][j][k].dMax, ",", false))
return false ;
if ( ! ngeOut.WriteInt( m_Values[i][j][k].nToolMax, ";", false))
return false ;
if ( ! ngeOut.WriteVector( m_Values[i][j][k].vtMaxN, ";", false))
return false ;
if ( ! ngeOut.WriteInt( m_Values[i][j][k].nCompo, ";", true))
return false ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PreSave( GdbGeo& Wrapper) const
{
// salvo il flag di visualizzazione spigoli vivi anche in shading (default false)
if ( m_bShowEdges)
Wrapper.SetInfo( GDB_SI_SHOWEDGES, true) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PostSave( GdbGeo& Wrapper) const
{
// elimino eventuali info aggiunte nella PreSave
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Load( NgeReader& ngeIn)
{
Clear() ;
// numero di mappe
if ( ! ngeIn.ReadInt( m_nMapNum, ",", false))
return false ;
// numero di blocchi
if ( ! ngeIn.ReadInt( m_nNumBlock, ",", false))
return false ;
// numero di voxel per blocco
if ( ! ngeIn.ReadInt( m_nVoxNumPerBlock, ",", false))
return false ;
// numero di blocchi per ogni asse
for ( int i = 0 ; i < 3 ; ++ i) {
if ( ! ngeIn.ReadInt( m_nFracLin[i], ",", false))
return false ;
}
// da versione 1018 : aggiunto DexVoxRatio
if ( ngeIn.GetFileVersion() >= NGE_VER_1018) {
if ( ! ngeIn.ReadInt( m_nDexVoxRatio, ",", false))
return false ;
}
// numero di componenti connesse
if ( ! ngeIn.ReadInt( m_nConnectedCompoCount, ",", false))
return false ;
// passo di campionamento (distanza tra spilloni)
if ( ! ngeIn.ReadDouble( m_dStep, ";", true))
return false ;
// da versione 1014 : aggiunto flag Shape
if ( ngeIn.GetFileVersion() >= NGE_VER_1014) {
if ( ! ngeIn.ReadInt( m_nShape, ";", true))
return false ;
}
// sistema di riferimento
if ( ! ngeIn.ReadFrame( m_MapFrame, ";", true))
return false ;
// per ogni mappa : numero di passi in X e Y e quote Z estremali
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
if ( ! ngeIn.ReadInt( m_nNx[i], ",", false))
return false ;
if ( ! ngeIn.ReadInt( m_nNy[i], ",", false))
return false ;
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
if ( ! ngeIn.ReadDouble( m_dMinZ[i], ",", false))
return false ;
if ( ! ngeIn.ReadDouble( m_dMaxZ[i], ";", true))
return false ;
}
// ciclo sulle mappe
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
// dimensiono i vettori
m_Values[i].resize( m_nDim[i]) ;
// ciclo sui dexel
for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
// leggo il numero di estremi nel dexel
int nDim ;
if ( ! ngeIn.ReadInt( nDim, ":", false))
return false ;
// se dexel nullo
if ( nDim == 0) {
// leggo un valore dummy
double dDummy ;
if ( ! ngeIn.ReadDouble( dDummy, ";", true))
return false ;
}
// altrimenti
else {
// dimensiono l'array
m_Values[i][j].resize( nDim) ;
// leggo i valori
for ( int k = 0 ; k < nDim ; ++ k) {
if ( ! ngeIn.ReadDouble( m_Values[i][j][k].dMin, ",", false))
return false ;
if ( ! ngeIn.ReadInt( m_Values[i][j][k].nToolMin, ";", false))
return false ;
if ( ! ngeIn.ReadVector( m_Values[i][j][k].vtMinN, ";", false))
return false ;
if ( ! ngeIn.ReadDouble( m_Values[i][j][k].dMax, ",", false))
return false ;
if ( ! ngeIn.ReadInt( m_Values[i][j][k].nToolMax, ";", false))
return false ;
if ( ! ngeIn.ReadVector( m_Values[i][j][k].vtMaxN, ";", false))
return false ;
if ( ! ngeIn.ReadInt( m_Values[i][j][k].nCompo, ";", true))
return false ;
}
}
}
}
// imposto aggiornamento obbligatorio su tutti i blocchi
m_BlockToUpdate.resize( m_nNumBlock, true) ;
m_BlockUpdatingCounter.resize( m_nNumBlock + ( m_nMapNum == 1 ? 0 : 1), 0) ;
// per triangoli di feature di frontiera tra blocchi
m_InterBlockVox.resize( m_nNumBlock) ;
m_InterBlockOriginalSharpTria.resize( m_nNumBlock) ;
m_InterBlockSharpTria.resize( m_nNumBlock) ;
m_BlockSharpTria.resize( m_nNumBlock) ;
m_BlockSmoothTria.resize( m_nNumBlock) ;
m_BlockBigTria.resize( m_nNumBlock) ;
m_SingleMapTria.resize( m_nNumBlock) ;
m_SliceXY.resize( m_nNumBlock) ;
m_SliceXZ.resize( m_nNumBlock) ;
m_SliceYZ.resize( m_nNumBlock) ;
m_nStatus = OK ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PostLoad( GdbGeo& Wrapper)
{
// recupero eventuale flag di visualizzazione spigoli vivi anche in shading
bool bVal ;
if ( Wrapper.GetInfo( GDB_SI_SHOWEDGES, bVal)) {
m_bShowEdges = bVal ;
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// reset box
b3Loc.Reset() ;
// se richiesto approssimato
if ( ( nFlag & BBF_EXACT) == 0) {
b3Loc.Add( ORIG) ;
b3Loc.Add( Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ;
b3Loc.ToGlob( m_MapFrame) ;
return true ;
}
// calcolo preciso
// ciclo sui dexel (punti in basso con ciclo aggiunto per punti in alto di ultima riga)
double dY = 0 ;
for ( int j = 0 ; j <= m_nNy[0] ; ++ j) {
int jc = ( ( j != m_nNy[0]) ? j : m_nNy[0] - 1) ;
double dX = 0 ;
// punto a sinistra di ogni dexel (aggiungo un ciclo per fare punto a destra di ultimo)
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
int nPos = ic + jc * m_nNx[0] ;
if ( m_Values[0][nPos].size() > 0) {
Point3d ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersX() + dY * m_MapFrame.VersY() ;
b3Loc.Add( ptP + m_Values[0][nPos][0].dMin * m_MapFrame.VersZ()) ;
b3Loc.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * m_MapFrame.VersZ()) ;
}
// passo al punto successivo
dX += m_dStep ;
}
// passo alla riga successiva
dY += m_dStep ;
}
//
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// reset box
b3Ref.Reset() ;
// trasformo il riferimento locale tramite quello passato
Frame3d frUse = m_MapFrame ;
frUse.ToGlob( frRef) ;
// se richiesto approssimato
if ( ( nFlag & BBF_EXACT) == 0) {
b3Ref.Add( ORIG) ;
b3Ref.Add( Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ;
b3Ref.ToGlob( frUse) ;
return true ;
}
// calcolo preciso
// ciclo sui dexel (punti in basso con ciclo aggiunto per punti in alto di ultima riga)
double dY = 0 ;
for ( int j = 0 ; j <= m_nNy[0] ; ++ j) {
int jc = ( ( j != m_nNy[0]) ? j : m_nNy[0] - 1) ;
double dX = 0 ;
// punto a sinistra di ogni dexel (aggiungo un ciclo per fare punto a destra di ultimo)
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
int nPos = ic + jc * m_nNx[0] ;
if ( nPos >= 0 && m_Values[0][nPos].size() > 0) {
Point3d ptP = frUse.Orig() + dX * frUse.VersX() + dY * frUse.VersY() ;
b3Ref.Add( ptP + m_Values[0][nPos][0].dMin * frUse.VersZ()) ;
b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ;
}
// passo al punto successivo
dX += m_dStep ;
}
// passo alla riga successiva
dY += m_dStep ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetPartLocalBBox( int nPart, BBox3d& b3Loc, int nFlag) const
{
// Verifico lo stato.
if ( m_nStatus != OK)
return false ;
// Se una sola mappa o il numero di componenti indefinito, vi un errore.
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
return false ;
// Se la componente richiesta non esiste, vi un errore.
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
return false ;
// Calcolo Bounding-box
for ( int nMap = 0 ; nMap < 3 ; ++ nMap) {
for ( int nDex = 0 ; nDex < m_nDim[nMap] ; ++ nDex) {
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
// Indici del dexel
int nI = nDex % m_nNx[nMap] ;
int nJ = nDex / m_nNx[nMap] ;
// Posizione del dexel
double dX = ( nI + 0.5) * m_dStep ;
double dY = ( nJ + 0.5) * m_dStep ;
// Definisco i punti nel sistema locale
Point3d ptP, ptPSt, ptPEn ;
if ( nMap == 0) {
ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersX() + dY * m_MapFrame.VersY() ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * m_MapFrame.VersZ() ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * m_MapFrame.VersZ() ;
}
else if ( nMap == 1) {
ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersY() + dY * m_MapFrame.VersZ() ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * m_MapFrame.VersX() ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * m_MapFrame.VersX() ;
}
else {
ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersZ() + dY * m_MapFrame.VersX() ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * m_MapFrame.VersY() ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * m_MapFrame.VersY() ;
}
// Aggiungo i punti al bounding-box
b3Loc.Add( ptPSt) ;
b3Loc.Add( ptPEn) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetPartBBox( int nPart, const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
{
// Verifico lo stato.
if ( m_nStatus != OK)
return false ;
// Se una sola mappa o il numero di componenti indefinito, vi un errore.
if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1)
return false ;
// Se la componente richiesta non esiste, vi un errore.
if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1)
return false ;
// Calcolo Bounding-box
Point3d ptMapFrameOrig = m_MapFrame.Orig() ;
Vector3d vtMapFrameVersX = m_MapFrame.VersX() ;
Vector3d vtMapFrameVersY = m_MapFrame.VersY() ;
Vector3d vtMapFrameVersZ = m_MapFrame.VersZ() ;
ptMapFrameOrig.ToGlob( frRef) ;
vtMapFrameVersX.ToGlob( frRef) ;
vtMapFrameVersY.ToGlob( frRef) ;
vtMapFrameVersZ.ToGlob( frRef) ;
for ( int nMap = 0 ; nMap < 3 ; ++ nMap) {
for ( int nDex = 0 ; nDex < m_nDim[nMap] ; ++ nDex) {
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
// Indici del dexel
int nI = nDex % m_nNx[nMap] ;
int nJ = nDex / m_nNx[nMap] ;
// Posizione del dexel
double dX = ( nI + 0.5) * m_dStep ;
double dY = ( nJ + 0.5) * m_dStep ;
// Definisco i punti nel sistema locale
Point3d ptP, ptPSt, ptPEn ;
if ( nMap == 0) {
ptP = ptMapFrameOrig + dX * vtMapFrameVersX + dY * vtMapFrameVersY ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * vtMapFrameVersZ ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * vtMapFrameVersZ ;
}
else if ( nMap == 1) {
ptP = ptMapFrameOrig + dX * vtMapFrameVersY + dY * vtMapFrameVersZ ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * vtMapFrameVersX ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * vtMapFrameVersX ;
}
else {
ptP = ptMapFrameOrig + dX * vtMapFrameVersZ + dY * vtMapFrameVersX ;
ptPSt = ptP + m_Values[nMap][nDex][nInt].dMin * vtMapFrameVersY ;
ptPEn = ptP + m_Values[nMap][nDex][nInt].dMax * vtMapFrameVersY ;
}
// Aggiungo i punti al bounding-box
b3Ref.Add( ptPSt) ;
b3Ref.Add( ptPEn) ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Translate( const Vector3d& vtMove)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo della grafica
ResetGraphics() ;
// traslo il riferimento
m_MapFrame.Translate( vtMove) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo della grafica
ResetGraphics() ;
// ruoto il riferimento
m_MapFrame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico non sia nulla
if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO)
return false ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ToGlob( const Frame3d& frRef)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identit, non devo fare alcunch
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo della grafica
ResetGraphics() ;
// trasformo il riferimento
m_MapFrame.ToGlob( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ToLoc( const Frame3d& frRef)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identit, non devo fare alcunch
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo della grafica
ResetGraphics() ;
// trasformo il riferimento
m_MapFrame.ToLoc( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validit dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunch
if ( AreSameFrame( frOri, frDest))
return true ;
// imposto ricalcolo della grafica
ResetGraphics() ;
// trasformo il riferimento
m_MapFrame.LocToLoc( frOri, frDest) ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetPartCount( void) const
{
// Se mono-dexel la connessione incalcolabile.
if ( m_nMapNum == 1)
return - 1 ;
// Se il numero delle componenti indefinito
// lo ricalcolo e restituisco il risultato.
if ( m_nConnectedCompoCount == - 1) {
const_cast<VolZmap*>(this)->CheckMapConnection() ;
return m_nConnectedCompoCount ;
}
// Altrimenti restituisco direttamente il numero di componenti.
else
return m_nConnectedCompoCount ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CheckMapConnection( void)
{
// Imposto il numero di componenti connesse a 0
m_nConnectedCompoCount = 0 ;
// Imposto a 0 tutti il valore del numero della componente
// connessa di ciascun tratto di ciascun dexel.
for ( int tMap = 0 ; tMap < m_nMapNum ; ++ tMap) {
for ( int tDex = 0 ; tDex < m_nDim[tMap] ; ++ tDex) {
for ( int tInt = 0 ; tInt < int( m_Values[tMap][tDex].size()) ; ++ tInt) {
m_Values[tMap][tDex][tInt].nCompo = 0 ;
}
}
}
// Numero massimo di thread
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
// Ciclo sui dexel lungo Z
for ( int tI = 0 ; tI < m_nNx[0] ; ++ tI) {
for ( int tJ = 0 ; tJ < m_nNy[0] ; ++ tJ) {
// Numero del dexel lungo Z
int tDexZ = tJ * m_nNx[0] + tI ;
// Numero di intervalli nel dexel
int tStopIntZ = int( m_Values[0][tDexZ].size()) ;
// Ciclo sugli intervalli del dexel
for ( int tIntZ = 0 ; tIntZ < tStopIntZ ; ++ tIntZ) {
if ( m_Values[0][tDexZ][tIntZ].nCompo == 0) {
++ m_nConnectedCompoCount ;
m_Values[0][tDexZ][tIntZ].nCompo = m_nConnectedCompoCount ;
// Espando in tutta la componente
// Segmento corrente
IntervalIndexes NewInt ;
NewInt.tMap = 0 ;
NewInt.tDex = tJ * m_nNx[0] + tI ;
NewInt.tInt = tIntZ ;
// Vettore di stack di segmenti
IntContainerVec IntervalsToProcessStackVec ;
IntervalsToProcessStackVec.resize( nThreadMax) ;
// Mi espando dal primo intervallo mettendo gli intervalli che intersecano nei vari thread
FirstExpansionFromZ( nThreadMax, NewInt, IntervalsToProcessStackVec) ;
// Lancio in parallelo pi ricerche
int nActiveThread = 0 ;
vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ;
for ( int i = 0 ; i < nThreadMax ; ++ i) {
if ( ! IntervalsToProcessStackVec[i].empty()) {
++ nActiveThread ;
vRes[i] = async( launch::async, &VolZmap::ProcessIntervals, this, ref( IntervalsToProcessStackVec[i])) ;
}
}
// Attendo che tutti i porcessi terminino
int nTerminated = 0 ;
while ( nTerminated < nActiveThread) {
for ( int i = 0 ; i < nThreadMax ; ++ i) {
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
vRes[i].get() ;
++ nTerminated ;
}
}
}
}
// Se l'intervallo non attraversa un nodo o ha gi
// un indice assegnato salto questa iterazione.
else
continue ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ExpandFromXInterval( IntContainer& IntCont)
{
// Copio i dati dell'intervallo corrente
IntervalIndexes CurrInterval = IntCont.top() ;
IntCont.pop() ;
int tDex = CurrInterval.tDex ;
int tGrIndex1 = CurrInterval.tDex % m_nNx[1] ;
int tGrIndex2 = CurrInterval.tDex / m_nNx[1] ;
int tInt = CurrInterval.tInt ;
// Quote estreme del segmento lungo X
double dMinX = m_Values[1][tDex][tInt].dMin ;
double dMaxX = m_Values[1][tDex][tInt].dMax ;
double dMinDX = max( floor( ( dMinX - 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
double dMaxDX = max( floor( ( dMaxX + 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
// Indici estremi dei dei dexel ortogonali
// che possono intersecare il segmento di partenza
int tStartI = min( int( dMinDX), ( m_nNx[0] - 1)) ;
int tStopI = min( int( dMaxDX), ( m_nNx[0] - 1)) ;
// Posizione YZ del dexel
double dY = ( tGrIndex1 + 0.5) * m_dStep ;
double dZ = ( tGrIndex2 + 0.5) * m_dStep ;
// Ciclo sugli indici dei dexel che potrebbero
// intersecare il segmento di partenza
for ( int tI = tStartI ; tI <= tStopI ; ++ tI) {
// Analizzo i dexel della griglia 0.
int tStopZ = int( m_Values[0][tGrIndex1 * m_nNx[0] + tI].size()) ;
for ( int tIntZ = 0 ; tIntZ < tStopZ ; ++ tIntZ) {
// Estremi del dexel lunog Z
double dZmin = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMin ;
double dZmax = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dZmin - 2 * EPS_SMALL < dZ &&
dZmax + 2 * EPS_SMALL > dZ &&
m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].nCompo == 0) {
m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].nCompo = m_Values[1][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 0 ;
NewInterval.tDex = tGrIndex1 * m_nNx[0] + tI ;
NewInterval.tInt = tIntZ ;
IntCont.push( NewInterval) ;
}
}
// Analizzo i dexel della griglia 2
int tStopY = int( m_Values[2][tI * m_nNx[2] + tGrIndex2].size()) ;
for ( int tIntY = 0 ; tIntY < tStopY ; ++ tIntY) {
// Estremi del segmento del dexel lungo Y
double dYmin = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMin ;
double dYmax = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].nCompo == 0) {
m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].nCompo = m_Values[1][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 2 ;
NewInterval.tDex = tI * m_nNx[2] + tGrIndex2 ;
NewInterval.tInt = tIntY ;
IntCont.push( NewInterval) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ExpandFromYInterval( IntContainer& IntCont)
{
// Copio i dati dell'intervallo corrente
IntervalIndexes CurrInterval = IntCont.top() ;
IntCont.pop() ;
int tDex = CurrInterval.tDex ;
int tGrIndex1 = CurrInterval.tDex % m_nNx[2] ;
int tGrIndex2 = CurrInterval.tDex / m_nNx[2] ;
int tInt = CurrInterval.tInt ;
// Quote estreme del segmento lungo Y
double dMinY = m_Values[2][tDex][tInt].dMin ;
double dMaxY = m_Values[2][tDex][tInt].dMax ;
double dMinDY = max( floor( ( dMinY - 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
double dMaxDY = max( floor( ( dMaxY + 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
// Indici estremi dei dei dexel ortogonali
// che possono intersecare il segmento di partenza
int tStartJ = min( int( dMinDY), ( m_nNy[0] - 1)) ;
int tStopJ = min( int( dMaxDY), ( m_nNy[0] - 1)) ;
// Posizione XZ del dexel
double dX = ( tGrIndex2 + 0.5) * m_dStep ;
double dZ = ( tGrIndex1 + 0.5) * m_dStep ;
// Ciclo sugli indici dei dexel che potrebbero
// intersecare il segmento di partenza
for ( int tJ = tStartJ ; tJ <= tStopJ ; ++ tJ) {
// Analizzo i dexel della griglia 0.
int tStopZ = int( m_Values[0][tJ * m_nNx[0] + tGrIndex2].size()) ;
for ( int tIntZ = 0 ; tIntZ < tStopZ ; ++ tIntZ) {
// Estremi del dexel lunog Z
double dZmin = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMin ;
double dZmax = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dZmin - 2 * EPS_SMALL < dZ &&
dZmax + 2 * EPS_SMALL > dZ &&
m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].nCompo == 0) {
m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].nCompo = m_Values[2][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 0 ;
NewInterval.tDex = tJ * m_nNx[0] + tGrIndex2 ;
NewInterval.tInt = tIntZ ;
IntCont.push( NewInterval) ;
}
}
// Analizzo i dexel della griglia 1
int tStopX = int( m_Values[1][tGrIndex1 * m_nNx[1] + tJ].size()) ;
for ( int tIntX = 0 ; tIntX < tStopX ; ++ tIntX) {
// Estremi del segmento del dexel lungo X
double dXmin = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMin ;
double dXmax = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].nCompo == 0) {
m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].nCompo = m_Values[2][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 1 ;
NewInterval.tDex = tGrIndex1 * m_nNx[1] + tJ ;
NewInterval.tInt = tIntX ;
IntCont.push( NewInterval) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ExpandFromZInterval( IntContainer& IntCont)
{
// Copio i dati dell'intervallo corrente
IntervalIndexes CurrInterval = IntCont.top() ;
IntCont.pop() ;
int tDex = CurrInterval.tDex ;
int tGrIndex1 = CurrInterval.tDex % m_nNx[0] ;
int tGrIndex2 = CurrInterval.tDex / m_nNx[0] ;
int tInt = CurrInterval.tInt ;
// Quote estreme del segmento lungo Z
double dMinZ = m_Values[0][tDex][tInt].dMin ;
double dMaxZ = m_Values[0][tDex][tInt].dMax ;
double dMinDZ = max( floor( ( dMinZ - 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
double dMaxDZ = max( floor( ( dMaxZ + 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
// Indici estremi dei dexel ortogonali
// che possono intersecare il segmento di partenza
int tStartK = min( int( dMinDZ), ( m_nNy[1] - 1)) ;
int tStopK = min( int( dMaxDZ), ( m_nNy[1] - 1)) ;
// Posizione XY del dexel
double dX = ( tGrIndex1 + 0.5) * m_dStep ;
double dY = ( tGrIndex2 + 0.5) * m_dStep ;
// Ciclo sugli indici dei dexel che potrebbero
// intersecare il segmento di partenza
for ( int tK = tStartK ; tK <= tStopK ; ++ tK) {
// Analizzo i dexel della griglia 1.
int tStopX = int( m_Values[1][tK * m_nNx[1] + tGrIndex2].size()) ;
for ( int tIntX = 0 ; tIntX < tStopX ; ++ tIntX) {
// Estremi del segmento del dexel lungo X
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo == 0) {
m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo = m_Values[0][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 1 ;
NewInterval.tDex = tK * m_nNx[1] + tGrIndex2 ;
NewInterval.tInt = tIntX ;
IntCont.push( NewInterval) ;
}
}
// Analizzo i dexel della griglia 2
int tStopY = int( m_Values[2][tGrIndex1 * m_nNx[2] + tK].size()) ;
for ( int tIntY = 0 ; tIntY < tStopY ; ++ tIntY) {
// Estremi del segmento del dexel lungo Y
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo == 0) {
m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo = m_Values[0][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 2 ;
NewInterval.tDex = tGrIndex1 * m_nNx[2] + tK ;
NewInterval.tInt = tIntY ;
IntCont.push( NewInterval) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContainerVec& IntervalsToProcessStackVec)
{
int tDex = IntSt.tDex ;
int tGrIndex1 = IntSt.tDex % m_nNx[0] ;
int tGrIndex2 = IntSt.tDex / m_nNx[0] ;
int tInt = IntSt.tInt ;
// Quote estreme del segmento lungo Z
double dMinZ = m_Values[0][tDex][tInt].dMin ;
double dMaxZ = m_Values[0][tDex][tInt].dMax ;
double dMinDZ = max( floor( ( dMinZ - 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
double dMaxDZ = max( floor( ( dMaxZ + 2 * EPS_SMALL) / m_dStep - 0.5), 0.) ;
// Indici estremi dei dexel ortogonali
// che possono intersecare il segmento di partenza
int tStartK = min( int( dMinDZ), ( m_nNy[1] - 1)) ;
int tStopK = min( int( dMaxDZ), ( m_nNy[1] - 1)) ;
// Posizione XY del dexel
double dX = ( tGrIndex1 + 0.5) * m_dStep ;
double dY = ( tGrIndex2 + 0.5) * m_dStep ;
// Ciclo sugli indici dei dexel che potrebbero
// intersecare il segmento di partenza
int nCurStack = 0 ;
for ( int tK = tStartK ; tK <= tStopK ; ++ tK) {
// Analizzo i dexel della griglia 1.
int tStopX = int( m_Values[1][tK * m_nNx[1] + tGrIndex2].size()) ;
for ( int tIntX = 0 ; tIntX < tStopX ; ++ tIntX) {
// Estremi del segmento del dexel lungo X
double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ;
double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dXmin - 2 * EPS_SMALL < dX &&
dXmax + 2 * EPS_SMALL > dX &&
m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo == 0) {
m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].nCompo = m_Values[0][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 1 ;
NewInterval.tDex = tK * m_nNx[1] + tGrIndex2 ;
NewInterval.tInt = tIntX ;
IntervalsToProcessStackVec[nCurStack].push( NewInterval) ;
nCurStack = ( ++ nCurStack) % int( IntervalsToProcessStackVec.size()) ;
}
}
// Analizzo i dexel della griglia 2
int tStopY = int( m_Values[2][tGrIndex1 * m_nNx[2] + tK].size()) ;
for ( int tIntY = 0 ; tIntY < tStopY ; ++ tIntY) {
// Estremi del segmento del dexel lungo Y
double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ;
double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ;
// Se i segmenti si incrociano e il nuovo trovato non
// ha gi un indice assegnato, assegno l'indice e
// aggiungo l'intervallo trovato allo stack.
if ( dYmin - 2 * EPS_SMALL < dY &&
dYmax + 2 * EPS_SMALL > dY &&
m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo == 0) {
m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].nCompo = m_Values[0][tDex][tInt].nCompo ;
IntervalIndexes NewInterval ;
NewInterval.tMap = 2 ;
NewInterval.tDex = tGrIndex1 * m_nNx[2] + tK ;
NewInterval.tInt = tIntY ;
IntervalsToProcessStackVec[nCurStack].push( NewInterval) ;
nCurStack = ( ++ nCurStack) % int( IntervalsToProcessStackVec.size()) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ProcessIntervals( IntContainer& IntervalsToProcess)
{
// Processo gli intervalli trovati
while ( ! IntervalsToProcess.empty()) {
switch ( IntervalsToProcess.top().tMap) {
case 0:
ExpandFromZInterval( IntervalsToProcess) ;
break ;
case 1:
ExpandFromXInterval( IntervalsToProcess) ;
break ;
case 2:
ExpandFromYInterval( IntervalsToProcess) ;
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
VolZmap*
VolZmap::ClonePart( int nPart) const
{
// verifico lo stato
if ( m_nStatus != OK)
return nullptr ;
// Se definita una sola griglia non sono definibili le parti, errore
if ( m_nMapNum == 1)
return nullptr ;
// Se richiesta una componente fuori intervallo, errore
if ( nPart < 0 || nPart >= m_nConnectedCompoCount)
return nullptr ;
// Se il numero di componenti indefinito, lo ricalcolo.
if ( m_nConnectedCompoCount == - 1)
const_cast<VolZmap*>(this)->CheckMapConnection() ;
// Se non vi sono componenti, errore
if ( m_nConnectedCompoCount == 0)
return nullptr ;
// Creo nuovo oggetto Zmap
PtrOwner<VolZmap> pVolume( CreateBasicVolZmap()) ;
if ( IsNull( pVolume))
return nullptr ;
// Setto per il nuovo Zmap le seguenti variabili
pVolume->m_nConnectedCompoCount = 1 ;
pVolume->m_dStep = m_dStep ;
pVolume->m_nMapNum = m_nMapNum ;
// Minimi e massimi indici i,j della componente per le tre griglie
int nMinIndI[N_MAPS] ;
int nMaxIndI[N_MAPS] ;
int nMinIndJ[N_MAPS] ;
int nMaxIndJ[N_MAPS] ;
// Coordinate dell'origine del sistema di riferimento
// del nuovo Zmap
double dNewOx, dNewOy, dNewOz ;
// Ciclo sulle mappe
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
nMinIndI[nMap] = m_nNx[nMap] ;
nMinIndJ[nMap] = m_nNy[nMap] ;
nMaxIndI[nMap] = 0 ;
nMaxIndJ[nMap] = 0 ;
pVolume->m_dMinZ[nMap] = m_dMaxZ[nMap] ;
pVolume->m_dMaxZ[nMap] = m_dMinZ[nMap] ;
// Della componente connessa in questione calcolo indici i e j massimi e minimi.
// Inoltre cerco la minima e massima Z.
for ( int nIndI = 0 ; nIndI < int( m_nNx[nMap]) ; ++ nIndI) {
for ( int nIndJ = 0 ; nIndJ < int( m_nNy[nMap]) ; ++ nIndJ) {
int nDex = nIndJ * m_nNx[nMap] + nIndI ;
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
if ( nIndI < nMinIndI[nMap])
nMinIndI[nMap] = nIndI ;
if ( nIndJ < nMinIndJ[nMap])
nMinIndJ[nMap] = nIndJ ;
if ( nIndI > nMaxIndI[nMap])
nMaxIndI[nMap] = nIndI ;
if ( nIndJ > nMaxIndJ[nMap])
nMaxIndJ[nMap] = nIndJ ;
if ( m_Values[nMap][nDex][nInt].dMin < pVolume->m_dMinZ[nMap])
pVolume->m_dMinZ[nMap] = m_Values[nMap][nDex][nInt].dMin ;
if ( m_Values[nMap][nDex][nInt].dMax > pVolume->m_dMaxZ[nMap])
pVolume->m_dMaxZ[nMap] = m_Values[nMap][nDex][nInt].dMax ;
}
}
}
}
}
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
if ( nMinIndI[nMap] > 0)
-- nMinIndI[nMap] ;
if ( nMaxIndI[nMap] < int( m_nNx[nMap]) - 1)
++ nMaxIndI[nMap] ;
if ( nMinIndJ[nMap] > 0)
-- nMinIndJ[nMap] ;
if ( nMaxIndJ[nMap] < int( m_nNy[nMap]) - 1)
++ nMaxIndJ[nMap] ;
pVolume->m_nNx[nMap] = max( 0, nMaxIndI[nMap] - nMinIndI[nMap] + 1) ;
pVolume->m_nNy[nMap] = max( 0, nMaxIndJ[nMap] - nMinIndJ[nMap] + 1) ;
pVolume->m_nDim[nMap] = pVolume->m_nNx[nMap] * pVolume->m_nNy[nMap] ;
pVolume->m_Values[nMap].resize( pVolume->m_nDim[nMap]) ;
}
// Se almeno una griglia nulla, non ha senso Zmap
if ( pVolume->m_nDim[0] == 0 ||
pVolume->m_nDim[1] == 0 ||
pVolume->m_nDim[2] == 0)
return nullptr ;
// Copio gli intervalli nelle griglie del nuovo oggetto:
// Griglia 0
for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[0]) ; ++ nIndJ) {
for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[0]) ; ++ nIndI) {
int nNewDex = nIndJ * pVolume->m_nNx[0] + nIndI ;
int nOldDex = ( nIndJ + nMinIndJ[0]) * m_nNx[0] + nIndI + nMinIndI[0] ;
for ( int nInt = 0 ; nInt < int( m_Values[0][nOldDex].size()) ; ++ nInt) {
if ( m_Values[0][nOldDex][nInt].nCompo == nPart + 1) {
pVolume->m_Values[0][nNewDex].emplace_back( m_Values[0][nOldDex][nInt]) ;
pVolume->m_Values[0][nNewDex].back().nCompo = 1 ;
}
}
}
}
// Griglia 1
for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[1]) ; ++ nIndJ) {
for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[1]) ; ++ nIndI) {
int nNewDex = nIndJ * pVolume->m_nNx[1] + nIndI ;
int nOldDex = ( nIndJ + nMinIndJ[1]) * m_nNx[1] + nIndI + nMinIndI[1] ;
for ( int nInt = 0 ; nInt < int( m_Values[1][nOldDex].size()) ; ++ nInt) {
if ( m_Values[1][nOldDex][nInt].nCompo == nPart + 1) {
pVolume->m_Values[1][nNewDex].emplace_back( m_Values[1][nOldDex][nInt]) ;
pVolume->m_Values[1][nNewDex].back().nCompo = 1 ;
}
}
}
}
// Griglia 2
for ( int nIndJ = 0 ; nIndJ < int( pVolume->m_nNy[2]) ; ++ nIndJ) {
for ( int nIndI = 0 ; nIndI < int( pVolume->m_nNx[2]) ; ++ nIndI) {
int nNewDex = nIndJ * pVolume->m_nNx[2] + nIndI ;
int nOldDex = ( nIndJ + nMinIndJ[2]) * m_nNx[2] + nIndI + nMinIndI[2] ;
for ( int nInt = 0 ; nInt < int( m_Values[2][nOldDex].size()) ; ++ nInt) {
if ( m_Values[2][nOldDex][nInt].nCompo == nPart + 1) {
pVolume->m_Values[2][nNewDex].emplace_back( m_Values[2][nOldDex][nInt]) ;
pVolume->m_Values[2][nNewDex].back().nCompo = 1 ;
}
}
}
}
// Coordinate x,y dell'origine del sistema di riferimento
dNewOx = nMinIndI[0] * m_dStep ;
dNewOy = nMinIndJ[0] * m_dStep ;
dNewOz = nMinIndJ[1] * m_dStep ;
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c' bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al pi per una traslazione.
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
// Quote estreme Z
switch ( nMap) {
case 0 :
pVolume->m_dMinZ[nMap] -= dNewOz ;
pVolume->m_dMaxZ[nMap] -= dNewOz ;
break ;
case 1 :
pVolume->m_dMinZ[nMap] -= dNewOx ;
pVolume->m_dMaxZ[nMap] -= dNewOx ;
break ;
case 2 :
pVolume->m_dMinZ[nMap] -= dNewOy ;
pVolume->m_dMaxZ[nMap] -= dNewOy ;
break ;
}
// Dexel
for ( int nDex = 0 ; nDex < int( pVolume->m_nDim[nMap]) ; ++ nDex) {
for ( int nInt = 0 ; nInt < int( pVolume->m_Values[nMap][nDex].size()) ; ++ nInt) {
switch ( nMap) {
case 0 :
pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOz ;
pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOz ;
break ;
case 1 :
pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOx ;
pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOx ;
break ;
case 2 :
pVolume->m_Values[nMap][nDex][nInt].dMin -= dNewOy ;
pVolume->m_Values[nMap][nDex][nInt].dMax -= dNewOy ;
break ;
}
}
}
}
// Definisco il numero di blocchi lungo x,y e z
if ( ! pVolume->CalcBlockNum())
return nullptr ;
// Sistema di riferimento intrinseco del nuovo solido
Point3d ptNewO = m_MapFrame.Orig() + Vector3d( dNewOx, dNewOy, dNewOz) ;
pVolume->m_MapFrame.Set( ptNewO, X_AX, Y_AX, Z_AX) ;
// Determino la forma
pVolume->m_nShape = ( pVolume->IsBox() ? BOX : GENERIC) ;
// Setto lo stato del nuovo Solido
pVolume->m_nStatus = m_nStatus ;
// Restituisco il nuovo solido
return Release( pVolume) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::RemovePart( int nPart)
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// Se definita una sola griglia non sono definibili le parti, errore
if ( m_nMapNum == 1)
return false ;
// Se il numero di componenti indefinito, lo ricalcolo
if ( m_nConnectedCompoCount == - 1)
CheckMapConnection() ;
// Se non vi sono componenti, abbiamo finito
if ( m_nConnectedCompoCount == 0)
return true ;
// Elimino i segmenti con indice nPart + 1 e aggiorno quelli con indice superiore
// Ciclo sulle mappe.
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
// Ciclo sui dexel della mappa.
for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) {
// Ciclo sugli intervalli del dexel.
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
// Se l'intervallo appartiene alla componente da eliminare, lo cancello.
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
SetToModifyDexelBlocks( nMap, nDex, nInt) ;
m_Values[nMap][nDex].erase( m_Values[nMap][nDex].begin() + nInt) ;
-- nInt ;
}
else if ( m_Values[nMap][nDex][nInt].nCompo > nPart + 1)
m_Values[nMap][nDex][nInt].nCompo -= 1 ;
}
}
}
// Decremento il numero di componenti.
m_nConnectedCompoCount -= 1 ;
// Imposto ricalcolo grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
{
// Verifico lo stato e che siano definibili le componenti connesse
if ( m_nStatus != OK || m_nMapNum == 1)
return - 1 ;
// Se il numero di componenti indefinito, lo ricalcolo
if ( m_nConnectedCompoCount == -1)
const_cast<VolZmap*>( this)->CheckMapConnection() ;
// Se non vi sono componenti, abbiamo finito
if ( m_nConnectedCompoCount == 0)
return - 1 ;
// Porto il punto nel riferimento intrinseco
Point3d ptPL = ptP ;
ptPL.ToLoc( m_MapFrame) ;
// Trovo la componente connessa di minima distanza dal punto
double dMinDist = DBL_MAX ;
int nMinDistPart = - 1 ;
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
for ( int nDex = 0 ; nDex < m_nDim[nMap] ; ++ nDex) {
double dX = ( ( nDex % m_nNx[nMap]) + 0.5) * m_dStep ;
double dY = ( ( nDex / m_nNx[nMap]) + 0.5) * m_dStep ;
int nIntervalNum = int( m_Values[nMap][nDex].size()) ;
for ( int nInt = 0 ; nInt < nIntervalNum ; ++ nInt) {
Point3d ptSt( dX, dY, m_Values[nMap][nDex][nInt].dMin) ;
Point3d ptEn( dX, dY, m_Values[nMap][nDex][nInt].dMax) ;
// Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco)
if ( nMap == 1) {
swap( ptSt.x, ptSt.z) ;
swap( ptSt.y, ptSt.z) ;
swap( ptEn.x, ptEn.z) ;
swap( ptEn.y, ptEn.z) ;
}
else if ( nMap == 2) {
swap( ptSt.y, ptSt.z) ;
swap( ptSt.x, ptSt.z) ;
swap( ptEn.y, ptEn.z) ;
swap( ptEn.x, ptEn.z) ;
}
// Calcolo la distanza del punto dal segmento corrente. Se minore della minima distanza aggiorno quest'ultima
// e la corrispondente componente connessa di minima distanza con la distanza e la componente connessa correnti.
double dDist ;
DistPointLine DistCalc( ptPL, ptSt, ptEn) ;
if ( DistCalc.GetDist( dDist) && dDist < dMinDist) {
dMinDist = dDist ;
nMinDistPart = m_Values[nMap][nDex][nInt].nCompo ;
}
}
}
}
return ( nMinDistPart - 1) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
{
// controllo sulla superficie
double dVol ;
if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() ||
! pStm->GetVolume( dVol) || dVol < 0)
return false ;
// controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente
BBox3d BBox_stm, BBox_curr ;
if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr))
return false ;
BBox3d BBox_inters ;
if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty())
return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap
Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone
// ciclo sulle griglie
bool bCompleted = true ;
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
// definisco dei sistemi di riferimento ausiliari
Frame3d frMapFrame ;
if ( g == 0)
frMapFrame = m_MapFrame ;
else if ( g == 1)
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
else if ( g == 2)
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
// oggetto per calcolo massivo intersezioni
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
// numero massimo di thread
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ;
// se dimensione griglia in X maggiore di dimensione Y
if ( m_nNx[g] > m_nNy[g]) {
int nDexNum = m_nNx[g] / nThreadMax ;
int nRemainder = m_nNx[g] % nThreadMax ;
int nInfI = 0 ;
int nSupI = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
}
}
// se dimensione griglia in Y maggiore di dimensione X
else {
int nDexNum = m_nNy[g] / nThreadMax ;
int nRemainder = m_nNy[g] % nThreadMax ;
int nInfJ = 0 ;
int nSupJ = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
}
}
// ciclo per attendere che tutti gli async abbiano terminato.
int nTerminated = 0 ;
while ( nTerminated < nThreadMax) {
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
// async terminato
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
++ nTerminated ;
bCompleted = bCompleted && vRes[nL].get() ;
}
}
}
if ( ! bCompleted)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MakeUniform( double dToler)
{
// controllo validit dello Zmap
if ( ! IsValid())
return false ;
// la tolleranza deve essere minore dello step
dToler = min( dToler, 0.95 * m_dStep) ;
// creo lo Zmpa che andr a sostituire il corrente
PtrOwner<VolZmap> pOldVolZmap( CloneBasicVolZmap( this)) ;
if ( IsNull( pOldVolZmap))
return false ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// salvo lo Zmap prima di modificare gli spilloni
PtrOwner<VolZmap> pVolZMapCurrGrid( CloneBasicVolZmap( this)) ;
if ( IsNull( pVolZMapCurrGrid))
return false ;
// ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
// se il dexel corrente non ha sotto-intervalli passo al successivo
if ( int( m_Values[nGrid][nDex].size()) == 0)
continue ;
// indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// salvo le informazioni dei sotto-intervalli del dexel corrente
vector<Data> vInfo ;
for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr)
vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ;
// per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza
int nSub_intervals = int( vInfo.size()) ;
// scorro gli intervalli
for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// estremo inferiore
if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMin - dToler,
vInfo[nInfo].dMin + dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin,
true) ;
// se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due
// direzioni nel voxel corrispondente
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
// l'intervallo corrente si unito con il precedente...
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN,
vInfo[nInfo].nToolMin) ;
}
}
// estremo superiore
if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMax - dToler,
vInfo[nInfo].dMax + dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax,
true) ;
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN,
vInfo[nInfo].nToolMax) ;
}
}
}
// per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza
// ( NB. avendo aggiunto intervalli, il dexel pu modificare la sua struttura interna )
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra,
// altrimenti rimuovo parti in eccesso )
if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) {
if ( nInfo != 0 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
{
// Controllo sulla validit della griglia
if ( nGrid < 0 || nGrid > 2)
return false ;
// Controllo sulla validit del dexel
if ( nDex <= - 1 || nDex >= int( m_Values[nGrid].size()))
return false ;
// Controllo sulla validit dell'intervallo
if ( nInt <= - 1 || nInt >= int( m_Values[nGrid][nDex].size()))
return false ;
// Determino quali blocchi sono stati modificati
int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ;
// Indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// Quote estreme del dexel
double dMin = m_Values[nGrid][nDex][nInt].dMin ;
double dMax = m_Values[nGrid][nDex][nInt].dMax ;
if ( nGrid == 0) {
int nXStop = 1 ;
int nYStop = 1 ;
int nXBlock[2] ;
int nYBlock[2] ;
// Passo dal dexel al voxel
nI /= m_nDexVoxRatio ;
nJ /= m_nDexVoxRatio ;
nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
// Numero di voxel lungo Z
int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ;
int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ;
int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ;
for ( int tI = 0 ; tI < nXStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) {
for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) {
int nBlockNum = k * nLayerBlock + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 1) {
int nYStop = 1 ;
int nZStop = 1 ;
int nYBlock[2] ;
int nZBlock[2] ;
// Passo dal dexel al voxel
nI /= m_nDexVoxRatio ;
nJ /= m_nDexVoxRatio ;
nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ;
nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) {
nYBlock[1] = nYBlock[0] - 1 ;
++ nYStop ;
}
if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Numero di voxel lungo X
int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ;
int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ;
int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ;
for ( int tI = 0 ; tI < nYStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) {
for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) {
int nBlockNum = nZBlock[tJ] * nLayerBlock + nYBlock[tI] * m_nFracLin[0] + k ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
else if ( nGrid == 2) {
int nXStop = 1 ;
int nZStop = 1 ;
int nXBlock[2] ;
int nZBlock[2] ;
// Passo dal dexel al voxel
nI /= m_nDexVoxRatio ;
nJ /= m_nDexVoxRatio ;
nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ;
nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ;
if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) {
nXBlock[1] = nXBlock[0] - 1 ;
++ nXStop ;
}
if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) {
nZBlock[1] = nZBlock[0] - 1 ;
++ nZStop ;
}
// Numero di voxel lungo Y
int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ;
int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ;
int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ;
for ( int tI = 0 ; tI < nZStop ; ++ tI) {
for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) {
for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) {
int nBlockNum = nZBlock[tI] * nLayerBlock + k * m_nFracLin[0] + nXBlock[tJ] ;
m_BlockToUpdate[nBlockNum] = true ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ)
{
if ( ! m_bIsBox)
return true ;
dMinZ = m_dMaxZ[nMap] ;
dMaxZ = m_dMinZ[nMap] ;
for ( int i = nInfI ; i < nSupI ; ++ i) {
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
int n = j * m_nNx[nMap] + i ;
int nSize = int( m_Values[nMap][n].size()) ;
if ( nSize > 1)
return false ;
else if ( nSize > 0) {
if ( dMinZ > dMaxZ) {
dMinZ = m_Values[nMap][n][0].dMin ;
dMaxZ = m_Values[nMap][n][0].dMax ;
}
else {
if ( abs( m_Values[nMap][n][0].dMin - dMinZ) > EPS_SMALL ||
abs( m_Values[nMap][n][0].dMax - dMaxZ) > EPS_SMALL)
return false ;
}
}
}
}
return ( dMaxZ >= dMinZ) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::IsBox( void)
{
// Se non tridexel, non posso stabilire con il metodo seguente se un box
if ( m_nMapNum == 1)
return false ;
// Numero massimo di thread per il calcolo parallelo.
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
// Disponibile un solo thread
if ( nThreadMax == 1) {
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
double dMinZ, dMaxZ ;
if ( ! IsMapPartABox( nMap, 0, m_nNx[nMap], 0, m_nNy[nMap], dMinZ, dMaxZ))
return false ;
}
return true ;
}
// Caso di pi thread
m_bIsBox = true ;
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
vector< future<bool>> vRes ;
vRes.resize( nThreadMax) ;
std::vector<double> vMinZ, vMaxZ ;
vMinZ.resize( nThreadMax) ;
vMaxZ.resize( nThreadMax) ;
if ( m_nNx[nMap] > m_nNy[nMap]) {
int nDexNum = m_nNx[nMap] / nThreadMax ;
int nRemainder = m_nNx[nMap] % nThreadMax ;
int nInfI = 0 ;
int nSupI = 0 ;
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::IsMapPartABox, this, nMap,
nInfI, nSupI, 0, m_nNy[nMap], ref( vMinZ[nThread]), ref( vMaxZ[nThread])) ;
}
}
else {
int nDexNum = m_nNy[nMap] / nThreadMax ;
int nRemainder = m_nNy[nMap] % nThreadMax ;
int nInfJ = 0 ;
int nSupJ = 0 ;
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::IsMapPartABox, this, nMap,
0, m_nNx[nMap], nInfJ, nSupJ, ref(vMinZ[nThread]), ref(vMaxZ[nThread])) ;
}
}
// Ciclo per attendere che tutti gli async abbiano terminato.
int nTerminated = 0 ;
while ( nTerminated < nThreadMax) {
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
// Async terminato
if ( vRes[nL].valid() && vRes[nL].wait_for(chrono::microseconds{ 1 }) == future_status::ready) {
++ nTerminated ;
if ( ! vRes[nL].get()) {
m_bIsBox = false ;
}
}
}
}
// Se uno dei thread trova che la sua porzione non un box, non lo pu essere il solido intero.
if ( ! m_bIsBox)
return false ;
// Controllo che gli estremi Z siano uguali.
for ( int nT = 1 ; nT < nThreadMax ; ++ nT) {
if ( abs( vMinZ[nT] - vMinZ[0]) > EPS_SMALL)
return false ;
if ( abs( vMaxZ[nT] - vMaxZ[0]) > EPS_SMALL)
return false ;
}
}
return m_bIsBox ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Cut( const Plane3d& plPlane)
{
// Porto il piano nel riferimento intrinseco
Plane3d plMyPlane = plPlane ;
plMyPlane.ToLoc( m_MapFrame) ;
// Interseco lo Zmap col piano, ciclando sulle griglie
bool bModified = false ;
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
// Porto il piano nel riferimento di griglia
if ( nMap == 1) {
Frame3d frGrid ; frGrid.Set( ORIG, Y_AX, Z_AX, X_AX) ;
plMyPlane.ToLoc( frGrid) ;
}
else if (nMap == 2) {
Frame3d frGrid ; frGrid.Set( ORIG, Y_AX, Z_AX, X_AX) ;
plMyPlane.ToLoc( frGrid) ;
}
// Ciclo sui dexel della mappa
for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) {
// Se spillone gi vuoto, passo al successivo
if ( m_Values[nMap][nD].empty())
continue ;
// Indici di spillone
int nI = nD % m_nNx[nMap] ;
int nJ = nD / m_nNx[nMap] ;
// Recupero estremi spillone
double dMin = m_Values[nMap][nD][0].dMin ;
double dMax = m_Values[nMap][nD][m_Values[nMap][nD].size() - 1].dMax ;
Point3d ptSt( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, dMin) ;
Point3d ptEn( ( nI + 0.5) * m_dStep, ( nJ + 0.5) * m_dStep, dMax) ;
// Distanze degli estremi del segmento dal piano
double dStDist = DistPointPlane( ptSt, plMyPlane) ;
double dEnDist = DistPointPlane( ptEn, plMyPlane) ;
// Se entrambi sotto il piano
if ( dStDist < EPS_SMALL && dEnDist < EPS_SMALL)
// Non devo fare alcunch
;
// se altrimenti entrambi gli estremi sono oltre il piano
else if ( dStDist > -EPS_SMALL && dEnDist > -EPS_SMALL) {
// Si elimina tutto
SubtractIntervals( nMap, nI, nJ, dMin, dMax, V_NULL, V_NULL, 1) ;
}
// se altrimenti da tenere il punto iniziale
else if ( dStDist < 0) {
// Si elimina la parte tra intersezione e punto finale
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
SubtractIntervals( nMap, nI, nJ, dInt, dMax, plMyPlane.GetVersN(), V_NULL, 1) ;
}
// se altrimenti da tenere il punto finale
else if (dEnDist < 0) {
// Si elimina la parte tra punto iniziale e intersezione
double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ;
SubtractIntervals( nMap, nI, nJ, dMin, dInt, V_NULL, plMyPlane.GetVersN(), 1) ;
}
}
}
if ( bModified == true) {
// Imposto forma generica
m_nShape = GENERIC ;
// Imposto ricalcolo grafica
m_OGrMgr.Reset() ;
// Imposto numero di componenti connesse da ricalcolare
m_nConnectedCompoCount = - 1 ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Compact( void)
{
// Determino i nuovi estremi sugli indici e sulle quote Z e copio i dexel i cui indici sono compresi fra gli estremi
int nMinI[N_MAPS] ;
int nMinJ[N_MAPS] ;
int nMaxI[N_MAPS] ;
int nMaxJ[N_MAPS] ;
int nNx[N_MAPS] ;
int nNy[N_MAPS] ;
int nDim[N_MAPS] ;
double dMinZ[N_MAPS] ;
double dMaxZ[N_MAPS] ;
vector<vector<Data>> Values[N_MAPS] ;
bool bNotEmptyGrid = true ;
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
nMinI[nMap] = m_nNx[nMap] - 1 ;
nMinJ[nMap] = m_nNy[nMap] - 1 ;
nMaxI[nMap] = 0 ;
nMaxJ[nMap] = 0 ;
dMinZ[nMap] = m_dMaxZ[nMap] ;
dMaxZ[nMap] = m_dMinZ[nMap] ;
// Determino estremi degli indici e delle quote Z
for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) {
int nDexDim = int( m_Values[nMap][nD].size()) ;
if ( nDexDim > 0) {
int nI = nD % m_nNx[nMap] ;
int nJ = nD / m_nNx[nMap] ;
if ( nI < nMinI[nMap])
nMinI[nMap] = nI ;
if ( nJ < nMinJ[nMap])
nMinJ[nMap] = nJ ;
if ( nI > nMaxI[nMap])
nMaxI[nMap] = nI ;
if ( nJ > nMaxJ[nMap])
nMaxJ[nMap] = nJ ;
if ( m_Values[nMap][nD][0].dMin < dMinZ[nMap])
dMinZ[nMap] = m_Values[nMap][nD][0].dMin ;
if ( m_Values[nMap][nD][nDexDim - 1].dMax > dMaxZ[nMap])
dMaxZ[nMap] = m_Values[nMap][nD][nDexDim - 1].dMax ;
}
}
if ( nMinI[nMap] > nMaxI[nMap] || nMinJ[nMap] > nMaxJ[nMap]) {
bNotEmptyGrid = false ;
break ;
}
// Se necessario espando la griglia
if ( nMinI[nMap] > 0)
-- nMinI[nMap] ;
if ( nMinJ[nMap] > 0)
-- nMinJ[nMap] ;
if ( nMaxI[nMap] < int( m_nNx[nMap]) - 1)
++ nMaxI[nMap] ;
if ( nMaxJ[nMap] < int( m_nNy[nMap]) - 1)
++ nMaxJ[nMap] ;
nNx[nMap] = nMaxI[nMap] - nMinI[nMap] + 1 ;
nNy[nMap] = nMaxJ[nMap] - nMinJ[nMap] + 1 ;
nDim[nMap] = nNx[nMap] * nNy[nMap] ;
// Copio i dexel i cui indici sono compresi fra gli estremi
for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) {
int nI = nD % m_nNx[nMap] ;
int nJ = nD / m_nNx[nMap] ;
if ( nI >= nMinI[nMap] && nI <= nMaxI[nMap] && nJ >= nMinJ[nMap] && nJ <= nMaxJ[nMap]) {
Values[nMap].emplace_back( m_Values[nMap][nD]) ;
}
}
}
// Se non vi materiale
if ( ! bNotEmptyGrid) {
m_nStatus = TO_VERIFY ;
m_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ;
m_nShape = GENERIC ;
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
m_nNy[i] = 0 ;
m_nDim[i] = 0 ;
m_dMinZ[i] = 0 ;
m_dMaxZ[i] = 0 ;
m_nFracLin[i] = 0 ;
}
return true ;
}
// Coordinate x,y dell'origine del sistema di riferimento
double dNewOx = nMinI[0] * m_dStep ;
double dNewOy = nMinJ[0] * m_dStep ;
double dNewOz = nMinJ[1] * m_dStep ;
// Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c' bisogno di trasformare le normali,
// infatti i sistemi di riferimento in gioco differiscono al pi per una traslazione.
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
// Quote estreme Z
switch ( nMap) {
case 0 :
dMinZ[nMap] -= dNewOz ;
dMaxZ[nMap] -= dNewOz ;
break ;
case 1 :
dMinZ[nMap] -= dNewOx ;
dMaxZ[nMap] -= dNewOx ;
break ;
case 2 :
dMinZ[nMap] -= dNewOy ;
dMaxZ[nMap] -= dNewOy ;
break ;
}
// Dexel
for ( int nD = 0 ; nD < int( nDim[nMap]) ; ++ nD) {
for ( int nS = 0 ; nS < int( Values[nMap][nD].size()) ; ++ nS) {
switch ( nMap) {
case 0 :
Values[nMap][nD][nS].dMin -= dNewOz ;
Values[nMap][nD][nS].dMax -= dNewOz ;
break ;
case 1 :
Values[nMap][nD][nS].dMin -= dNewOx ;
Values[nMap][nD][nS].dMax -= dNewOx ;
break ;
case 2 :
Values[nMap][nD][nS].dMin -= dNewOy ;
Values[nMap][nD][nS].dMax -= dNewOy ;
break ;
}
}
}
}
// Ricopio i dexel con gli indici compresi fra gli estremi
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
m_nNx[nMap] = nNx[nMap] ;
m_nNy[nMap] = nNy[nMap] ;
m_nDim[nMap] = nDim[nMap] ;
m_Values[nMap].resize( 0) ;
for ( int nD = 0 ; nD < int( Values[nMap].size()) ; ++ nD) {
m_Values[nMap].emplace_back( Values[nMap][nD]) ;
}
}
// Definisco il numero di blocchi lungo x,y e z
if ( ! CalcBlockNum())
return false ;
// Sistema di riferimento intrinseco del nuovo solido
Point3d ptNewO = m_MapFrame.Orig() + Vector3d( dNewOx, dNewOy, dNewOz) ;
m_MapFrame.Set( ptNewO, X_AX, Y_AX, Z_AX) ;
// Imposto ricalcolo grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ChangeResolution( int nDexVoxRatio)
{
if ( nDexVoxRatio < 1 || nDexVoxRatio > 5)
return false ;
if ( nDexVoxRatio != m_nDexVoxRatio) {
int nOldDexVoxRatio = m_nDexVoxRatio ;
m_nDexVoxRatio = nDexVoxRatio ;
if ( CalcBlockNum()) {
ResetGraphics() ;
m_OGrMgr.Clear() ;
return true ;
}
m_nDexVoxRatio = nOldDexVoxRatio ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CalcBlockNum( void)
{
// Calcolo il numero di voxel lungo X e Y
int nVoxNumX = m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2) ;
int nVoxNumY = m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2) ;
if ( nVoxNumX == 0 || nVoxNumY == 0)
return false ;
// Definisco il numero di blocchi lungo X e Y
m_nFracLin[0] = max( 1, nVoxNumX / m_nVoxNumPerBlock + ( nVoxNumX % m_nVoxNumPerBlock > m_nVoxNumPerBlock / 4 ? 1 : 0)) ;
m_nFracLin[1] = max( 1, nVoxNumY / m_nVoxNumPerBlock + ( nVoxNumY % m_nVoxNumPerBlock > m_nVoxNumPerBlock / 4 ? 1 : 0)) ;
if ( m_nMapNum == 1) {
m_nFracLin[2] = 1 ;
m_nNumBlock = m_nFracLin[0] * m_nFracLin[1] * m_nFracLin[2] ;
m_BlockToUpdate.clear() ;
m_BlockToUpdate.resize( m_nNumBlock, true) ;
m_BlockUpdatingCounter.clear() ;
m_BlockUpdatingCounter.resize( m_nNumBlock, 0) ;
m_SingleMapTria.resize( m_nNumBlock) ;
return true ;
}
// Calcolo il numero di voxel lungo Z
int nVoxNumZ = m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2) ;
// Definisco il numero di blocchi lungo Z
m_nFracLin[2] = max( 1, nVoxNumZ / m_nVoxNumPerBlock + ( nVoxNumZ % m_nVoxNumPerBlock > m_nVoxNumPerBlock / 4 ? 1 : 0)) ;
// Dimensiono e setto il vettore dei blocchi a da ricalcolare e il vettore di contatori di aggiornamenti della grafica
m_nNumBlock = m_nFracLin[0] * m_nFracLin[1] * m_nFracLin[2] ;
m_BlockToUpdate.clear() ;
m_BlockToUpdate.resize( m_nNumBlock, true) ;
m_BlockUpdatingCounter.clear() ;
m_BlockUpdatingCounter.resize( m_nNumBlock + 1, 0) ;
// Dimensiono raccolta di voxel, triangoli di feature tra blocchi e di segnalatori di materiale fra voxel
m_InterBlockVox.resize( m_nNumBlock) ;
m_InterBlockOriginalSharpTria.resize( m_nNumBlock) ;
m_InterBlockSharpTria.resize( m_nNumBlock) ;
m_BlockSharpTria.resize( m_nNumBlock) ;
m_BlockSmoothTria.resize( m_nNumBlock) ;
m_BlockBigTria.resize( m_nNumBlock) ;
m_SingleMapTria.resize( m_nNumBlock) ;
m_SliceXY.resize( m_nNumBlock) ;
m_SliceXZ.resize( m_nNumBlock) ;
m_SliceYZ.resize( m_nNumBlock) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetToolTolerances( double dLinTol, double dAngTolDeg)
{
m_dToolLinTol = max( dLinTol, LIN_TOL_MIN) ;
m_dToolAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetAdvTool( const string& sToolName,
double dH, double dR, double dTipH, double dTipR, double dCornR, double dCutterH, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetSawTool( const string& sToolName,
double dH, double dR, double dThick, double dStemR, double dCornR, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetGenTool( sToolName, pToolOutline, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetAdditiveTool( const std::string& sToolName,
double dH, double dR, double dRc, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetAdditiveTool( sToolName, dH, dR, dRc, nFlag) ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetToolCount( void) const
{
return m_vTool.size() ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetCurrTool( int nCurrTool)
{
if ( nCurrTool < 0 || nCurrTool >= int( m_vTool.size()))
return false ;
m_nCurrTool = nCurrTool ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetTools( void)
{
m_vTool.resize( 1) ;
m_nCurrTool = 0 ;
return m_vTool[0].Clear() ;
}
//----------------------------------------------------------------------------
const ICurveComposite&
VolZmap::GetToolOutline( bool bApprox) const
{
if ( m_nCurrTool < 0 || m_nCurrTool >= int( m_vTool.size())) {
static CurveComposite StatCrvCo ;
return StatCrvCo ;
}
const Tool& CurrTool = m_vTool[m_nCurrTool] ;
return ( bApprox ? CurrTool.GetApproxOutline() : CurrTool.GetOutline()) ;
}