2ed2a34d55
- modifiche per DistPointLine con interfaccia portata in Include.
2410 lines
91 KiB
C++
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()) ;
|
|
}
|