EgtGeomKernel 1.8c2 :
- Validate e DoCompacting di SurfTrimesh eliminano i triangoli degeneri (punto o segmento di retta) - a SurfTrimesh aggiunta Cut (taglio con un piano).
This commit is contained in:
+1
-1
@@ -347,7 +347,7 @@ CurveBezier::GetType( void) const
|
||||
const string&
|
||||
CurveBezier::GetTitle( void) const
|
||||
{
|
||||
static const string sTitle = "CBezier" ;
|
||||
static const string sTitle = "CurveBezier" ;
|
||||
return sTitle ;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -575,7 +575,7 @@ CurveComposite::GetType( void) const
|
||||
const string&
|
||||
CurveComposite::GetTitle( void) const
|
||||
{
|
||||
static const string sTitle = "CComposite" ;
|
||||
static const string sTitle = "CurveCompo" ;
|
||||
return sTitle ;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -58,9 +58,14 @@ PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
|
||||
{
|
||||
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
|
||||
if ( m_lUPointBs.size() > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
||||
// assegno parametro e bulge
|
||||
m_lUPointBs.back().dU = dPar ;
|
||||
m_lUPointBs.back().dB = dBulge ;
|
||||
// incremento contatore rifiutati ed esco
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
// aggiungo il punto
|
||||
try {
|
||||
m_lUPointBs.emplace_back( dPar, ptP, dBulge) ;
|
||||
}
|
||||
|
||||
+2
-2
@@ -136,7 +136,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
// fondo le curve allineate
|
||||
pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ;
|
||||
// ne faccio una copia e la inverto
|
||||
PtrOwner<ICurveComposite> pCompo2( GetCurveComposite( pCompo1->Clone())) ;
|
||||
PtrOwner<CurveComposite> pCompo2( pCompo1->Clone()) ;
|
||||
if ( IsNull( pCompo2) || ! pCompo2->Invert())
|
||||
return nullptr ;
|
||||
// per creare la regione
|
||||
@@ -168,7 +168,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
// fondo le curve allineate
|
||||
pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ;
|
||||
// ne faccio una copia e la inverto
|
||||
PtrOwner<ICurveComposite> pCompo2( GetCurveComposite( pCompo1->Clone())) ;
|
||||
PtrOwner<CurveComposite> pCompo2( pCompo1->Clone()) ;
|
||||
if ( IsNull( pCompo2) || ! pCompo2->Invert())
|
||||
return nullptr ;
|
||||
// offset della prima curva a destra del raggio
|
||||
|
||||
+2
-2
@@ -107,7 +107,7 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
|
||||
if ( IsNull( pSTM1) || ! pSTM1->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
// la copio
|
||||
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMesh( pSTM1->Clone())) ;
|
||||
PtrOwner<ISurfTriMesh> pSTM2( pSTM1->Clone()) ;
|
||||
if ( IsNull( pSTM2))
|
||||
return nullptr ;
|
||||
// inverto la prima superficie
|
||||
@@ -154,7 +154,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
return nullptr ;
|
||||
// creo la seconda superficie e la unisco alla prima
|
||||
{ // copio la prima superficie
|
||||
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMesh( pSTM->Clone())) ;
|
||||
PtrOwner<ISurfTriMesh> pSTM2( pSTM->Clone()) ;
|
||||
if ( IsNull( pSTM2))
|
||||
return nullptr ;
|
||||
// inverto la prima superficie
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ GetSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
||||
if ( IsNull( pSTM1) || ! pSTM1->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
// la copio
|
||||
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMesh( pSTM1->Clone())) ;
|
||||
PtrOwner<ISurfTriMesh> pSTM2( pSTM1->Clone()) ;
|
||||
if ( IsNull( pSTM2))
|
||||
return nullptr ;
|
||||
// inverto la prima superficie
|
||||
|
||||
+1
-1
@@ -375,7 +375,7 @@ SurfFlatRegion::GetType( void) const
|
||||
const string&
|
||||
SurfFlatRegion::GetTitle( void) const
|
||||
{
|
||||
static const string sTitle = "FlatRegion" ;
|
||||
static const string sTitle = "SurfFr" ;
|
||||
return sTitle ;
|
||||
}
|
||||
|
||||
|
||||
+224
-7
@@ -35,7 +35,8 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh::SurfTriMesh( void)
|
||||
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false), m_nTimeStamp(), m_nTempProp()
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false),
|
||||
m_nTimeStamp( 0), m_nTempProp( 0)
|
||||
{
|
||||
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
@@ -925,7 +926,7 @@ SurfTriMesh::GetType( void) const
|
||||
const string&
|
||||
SurfTriMesh::GetTitle( void) const
|
||||
{
|
||||
static const string sTitle = "TriMesh" ;
|
||||
static const string sTitle = "SurfTm" ;
|
||||
return sTitle ;
|
||||
}
|
||||
|
||||
@@ -1146,8 +1147,10 @@ SurfTriMesh::Validate( void)
|
||||
m_nStatus = ERR ;
|
||||
}
|
||||
// calcolo eventuale normale mancante
|
||||
if ( m_nStatus == OK && m_vTria[i].vtN.IsSmall())
|
||||
CalcTriangleNormal( i) ;
|
||||
if ( m_nStatus == OK && m_vTria[i].vtN.IsSmall()) {
|
||||
if ( ! CalcTriangleNormal( i))
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2216,6 +2219,11 @@ SurfTriMesh::DoCompacting( void)
|
||||
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
|
||||
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
// se due vertici coincidono, cancello il triangolo
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] ||
|
||||
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] ||
|
||||
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2])
|
||||
RemoveTriangle( nId) ;
|
||||
}
|
||||
|
||||
// ricalcolo le adiacenze
|
||||
@@ -2295,9 +2303,11 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
|
||||
vId[0] = vVId[vOId[0]] ;
|
||||
vId[1] = vVId[vOId[1]] ;
|
||||
vId[2] = vVId[vOId[2]] ;
|
||||
// inserisco il triangolo
|
||||
if ( AddTriangle( vId) == SVT_NULL)
|
||||
return false ;
|
||||
// se triangolo ancora valido, lo inserisco
|
||||
if ( vId[0] != vId[1] && vId[0] != vId[2] && vId[1] != vId[2]) {
|
||||
if ( AddTriangle( vId) == SVT_NULL)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// ricalcolo le adiacenze
|
||||
@@ -2673,3 +2683,210 @@ SurfTriMesh::Invert( void)
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// classifico i vertici rispetto al piano
|
||||
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
|
||||
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
m_vVert[i].nTemp = 0 ;
|
||||
else if ( dDist > 0)
|
||||
m_vVert[i].nTemp = +1 ;
|
||||
else
|
||||
m_vVert[i].nTemp = -1 ;
|
||||
}
|
||||
|
||||
// aggiorno timestamp dei triangoli
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nTemp = m_nTimeStamp ;
|
||||
++ m_nTimeStamp ;
|
||||
|
||||
// sistemo i triangoli (eventualmente li elimino)
|
||||
bool bModif = false ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// salto i triangoli cancellati e quelli aggiunti
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
|
||||
continue ;
|
||||
// se flag abilita e giace sul piano ed equiverso, lo salvo
|
||||
if ( bSaveOnEq &&
|
||||
m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp == 0 &&
|
||||
AreSameVectorApprox( m_vTria[i].vtN, plPlane.vtN))
|
||||
;
|
||||
// se giace sul piano o dalla parte esterna del piano, lo cancello
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != -1) {
|
||||
bModif = true ;
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != 1)
|
||||
;
|
||||
// altrimenti attraversa il piano, devo modificarlo
|
||||
else {
|
||||
bModif = true ;
|
||||
int nDisc = m_vVert[ m_vTria[i].nIdVert[0]].nTemp +
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp +
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp ;
|
||||
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
|
||||
if ( nDisc == 0) {
|
||||
// classifico i vertici
|
||||
int nVertOn, nVertIn, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0) {
|
||||
nVertOn = 0 ;
|
||||
nVertIn = 1 ;
|
||||
nVertOut = 2 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0) {
|
||||
nVertOn = 1 ;
|
||||
nVertIn = 2 ;
|
||||
nVertOut = 0 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[2]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else {
|
||||
nVertOn = 2 ;
|
||||
nVertIn = 0 ;
|
||||
nVertOut = 1 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
// calcolo il punto di intersezione del lato che attraversa il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut)) ;
|
||||
// inserisco il nuovo vertice
|
||||
int nNewV = AddVertex( ptInt) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
nIdVert[nVertOut] = nNewV ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( ! IsValidSvt( nIdTria))
|
||||
return false ;
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
|
||||
else if ( nDisc == 1) {
|
||||
// classifico i vertici
|
||||
int nVertIn, nVertOut1, nVertOut2 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == -1) {
|
||||
nVertIn = 0 ;
|
||||
nVertOut1 = 1 ;
|
||||
nVertOut2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == -1) {
|
||||
nVertIn = 1 ;
|
||||
nVertOut1 = 2 ;
|
||||
nVertOut2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertIn = 2 ;
|
||||
nVertOut1 = 0 ;
|
||||
nVertOut2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP, plPlane) ;
|
||||
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut1)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut2)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
nIdVert[nVertOut1] = nNewV1 ;
|
||||
nIdVert[nVertOut2] = nNewV2 ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( ! IsValidSvt( nIdTria))
|
||||
return false ;
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// altrimenti ha due vertici allinterno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
|
||||
else {
|
||||
// classifico i vertici
|
||||
int nVertIn1, nVertIn2, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 1) {
|
||||
nVertOut = 0 ;
|
||||
nVertIn1 = 1 ;
|
||||
nVertIn2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 1) {
|
||||
nVertOut = 1 ;
|
||||
nVertIn1 = 2 ;
|
||||
nVertIn2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertOut = 2 ;
|
||||
nVertIn1 = 0 ;
|
||||
nVertIn2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, plPlane) ;
|
||||
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn1 / ( dDistIn1 + dDistOut)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn2 / ( dDistIn2 + dDistOut)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco i nuovi triangoli
|
||||
int nIdVert1[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
int nIdVert2[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
double dSqDist1 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, ptInt2) ;
|
||||
double dSqDist2 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, ptInt1) ;
|
||||
if ( dSqDist1 <= dSqDist2) {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert1[nVertIn2] = nNewV2 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
}
|
||||
else {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
nIdVert2[nVertIn1] = nNewV1 ;
|
||||
}
|
||||
int nIdTria1 = AddTriangle( nIdVert1) ;
|
||||
int nIdTria2 = AddTriangle( nIdVert2) ;
|
||||
if ( ! IsValidSvt( nIdTria1) || ! IsValidSvt( nIdTria2))
|
||||
return false ;
|
||||
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
|
||||
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se necessario, aggiorno tutto
|
||||
if ( bModif)
|
||||
return DoCompacting() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+5
-3
@@ -25,13 +25,14 @@
|
||||
class StmVert
|
||||
{
|
||||
public :
|
||||
StmVert( void) : ptP(), nIdTria( SVT_NULL), nFlag( 0) {}
|
||||
StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( SVT_NULL), nFlag( 0) {}
|
||||
StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF) {}
|
||||
StmVert( void) : ptP(), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
|
||||
StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
|
||||
StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF), nTemp( 0) {}
|
||||
public :
|
||||
Point3d ptP ;
|
||||
int nIdTria ;
|
||||
int nFlag ;
|
||||
mutable int nTemp ;
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -177,6 +178,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetFacetNormal( int nF, Vector3d& vtN) const override ;
|
||||
bool GetFacetArea( int nF, double& dArea) const override ;
|
||||
SurfTriMesh* CloneFacet( int nF) const override ;
|
||||
bool Cut( const Plane3d& plPlane, bool bSaveOnEq) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ VolZmap::GetType( void) const
|
||||
const string&
|
||||
VolZmap::GetTitle( void) const
|
||||
{
|
||||
static const string sTitle = "Zmap" ;
|
||||
static const string sTitle = "VolZm" ;
|
||||
return sTitle ;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user