EgtGeomKernel 1.5g3 :
- aggiunto concatenamento di Curve - aggiunta modifica di punto iniziale e finale di Curve - aggiunta Add a curva composita con tolleranza - aggiunto calcolo distanza approssimativa tra due punti (senza radice quadrata) - riordinate funzioni per modifica e copia curve.
This commit is contained in:
+233
-82
@@ -34,6 +34,7 @@
|
||||
#include "/EgtDev/Include/EgkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgkIntersCurveCurve.h"
|
||||
#include "/EgtDev/Include/EgkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgkSurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EgkExtText.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
@@ -118,16 +119,12 @@ GdbExecutor::GdbExecutor( void)
|
||||
m_ExecMgr.Insert( "MIR", &GdbExecutor::ExecuteMirror) ;
|
||||
m_ExecMgr.Insert( "MIRROR", &GdbExecutor::ExecuteMirror) ;
|
||||
m_ExecMgr.Insert( "SHEAR", &GdbExecutor::ExecuteShear) ;
|
||||
m_ExecMgr.Insert( "INVC", &GdbExecutor::ExecuteInvertCurve) ;
|
||||
m_ExecMgr.Insert( "INVERTCURVE", &GdbExecutor::ExecuteInvertCurve) ;
|
||||
m_ExecMgr.Insert( "COPYC", &GdbExecutor::ExecuteCopyCurve) ;
|
||||
m_ExecMgr.Insert( "COPYCURVE", &GdbExecutor::ExecuteCopyCurve) ;
|
||||
m_ExecMgr.Insert( "INVS", &GdbExecutor::ExecuteInvertSurf) ;
|
||||
m_ExecMgr.Insert( "INVERTSURF", &GdbExecutor::ExecuteInvertSurf) ;
|
||||
m_ExecMgr.Insert( "TRC", &GdbExecutor::ExecuteTrimCurve) ;
|
||||
m_ExecMgr.Insert( "TRIMCURVE", &GdbExecutor::ExecuteTrimCurve) ;
|
||||
m_ExecMgr.Insert( "SPC", &GdbExecutor::ExecuteSplitCurve) ;
|
||||
m_ExecMgr.Insert( "SPLITCURVE", &GdbExecutor::ExecuteSplitCurve) ;
|
||||
m_ExecMgr.Insert( "CMOD", &GdbExecutor::ExecuteCurveModify) ;
|
||||
m_ExecMgr.Insert( "CURVEMODIFY", &GdbExecutor::ExecuteCurveModify) ;
|
||||
m_ExecMgr.Insert( "CCOPY", &GdbExecutor::ExecuteCurveCopy) ;
|
||||
m_ExecMgr.Insert( "CURVECOPY", &GdbExecutor::ExecuteCurveCopy) ;
|
||||
m_ExecMgr.Insert( "SMOD", &GdbExecutor::ExecuteSurfModify) ;
|
||||
m_ExecMgr.Insert( "SURFMODIFY", &GdbExecutor::ExecuteSurfModify) ;
|
||||
m_ExecMgr.Insert( "NEW", &GdbExecutor::ExecuteNew) ;
|
||||
m_ExecMgr.Insert( "LOAD", &GdbExecutor::ExecuteLoad) ;
|
||||
m_ExecMgr.Insert( "SAVE", &GdbExecutor::ExecuteSave) ;
|
||||
@@ -1608,7 +1605,7 @@ GdbExecutor::CurveCompoMake( const STRVECTOR& vsParams)
|
||||
// altrimenti devo prima trasformare la curva
|
||||
else {
|
||||
// creo una copia della curva (da buttare alla fine)
|
||||
PtrOwner<ICurve> pModCrv( GetCurve( pCrv->Clone())) ;
|
||||
PtrOwner<ICurve> pModCrv( pCrv->Clone()) ;
|
||||
if ( ! IsValid( pModCrv))
|
||||
return false ;
|
||||
// eseguo la trasformazione
|
||||
@@ -2294,7 +2291,7 @@ GdbExecutor::GetPolylineFromCurve( int nId, const Frame3d& frDest, double dLinTo
|
||||
// altrimenti devo prima trasformare la curva
|
||||
else {
|
||||
// creo una copia della curva (da buttare alla fine)
|
||||
PtrOwner<ICurve> pModCrv( GetCurve( pCrv->Clone())) ;
|
||||
PtrOwner<ICurve> pModCrv( pCrv->Clone()) ;
|
||||
if ( ! IsValid( pModCrv))
|
||||
return false ;
|
||||
// eseguo la trasformazione
|
||||
@@ -4371,7 +4368,30 @@ GdbExecutor::ExecuteShear( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteInvertCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
GdbExecutor::ExecuteCurveModify( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
{
|
||||
if ( sCmd2 == "INV" || sCmd2 == "INVERT")
|
||||
return CurveModifyInvert( vsParams) ;
|
||||
else if ( sCmd2 == "SP" || sCmd2 == "STARTPOINT")
|
||||
return CurveModifyStartPoint( vsParams) ;
|
||||
else if ( sCmd2 == "EP" || sCmd2 == "ENDPOINT")
|
||||
return CurveModifyEndPoint( vsParams) ;
|
||||
if ( sCmd2 == "TRSL" || sCmd2 == "TRIMSTARTLEN")
|
||||
return CurveModifyTrim( vsParams, SL) ;
|
||||
else if ( sCmd2 == "TREL" || sCmd2 == "TRIMENDLEN")
|
||||
return CurveModifyTrim( vsParams, EL) ;
|
||||
else if ( sCmd2 == "TRSP" || sCmd2 == "TRIMSTARTPAR")
|
||||
return CurveModifyTrim( vsParams, SP) ;
|
||||
else if ( sCmd2 == "TREP" || sCmd2 == "TRIMENDPAR")
|
||||
return CurveModifyTrim( vsParams, EP) ;
|
||||
else if ( sCmd2 == "TRSEP" || sCmd2 == "TRIMSTARTENDPAR")
|
||||
return CurveModifyTrim( vsParams, SEP) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::CurveModifyInvert( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 1 parametro : Id/s
|
||||
if ( vsParams.size() != 1)
|
||||
@@ -4393,77 +4413,56 @@ GdbExecutor::ExecuteInvertCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteCopyCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
GdbExecutor::CurveModifyStartPoint( const STRVECTOR& vsParams)
|
||||
{
|
||||
if ( sCmd2 == "PR" || sCmd2 == "PARAMRANGE")
|
||||
return CopyCurveByParamRange( vsParams) ;
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::CopyCurveByParamRange( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 5 parametri : IdCrv, IdDest, IdGroupDest, StartPar, EndPar
|
||||
if ( vsParams.size() != 5)
|
||||
// 2 parametri : Id, PtNewStart
|
||||
if ( vsParams.size() != 2)
|
||||
return false ;
|
||||
// recupero la curva sorgente
|
||||
int nIdCrv = GetIdParam( vsParams[0]) ;
|
||||
const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
|
||||
ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// recupero il suo riferimento
|
||||
Frame3d frCrv ;
|
||||
if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv))
|
||||
return false ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frDest))
|
||||
// recupero il nuovo punto di inizio
|
||||
Point3d ptNewStart ;
|
||||
if ( ! GetPointParam( vsParams[1], frCrv, ptNewStart))
|
||||
return false ;
|
||||
// recupero i parametri del range
|
||||
double dUStart, dUEnd ;
|
||||
if ( ! FromString( vsParams[3], dUStart) ||
|
||||
! FromString( vsParams[4], dUEnd))
|
||||
return false ;
|
||||
// copio la parte di curva che interessa e la porto nel riferimento del gruppo destinazione
|
||||
PtrOwner<ICurve> pCopy( pCrv->CopyParamRange( dUStart, dUEnd)) ;
|
||||
if ( ! ::IsValid( pCopy))
|
||||
return false ;
|
||||
pCopy->LocToLoc( frCrv, frDest) ;
|
||||
// la inserisco nel gruppo
|
||||
return AddGeoObj( vsParams[1], vsParams[2], ::Release( pCopy)) ;
|
||||
// eseguo la modifica
|
||||
return pCrv->ModifyStart( ptNewStart) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteInvertSurf( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
GdbExecutor::CurveModifyEndPoint( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 1 parametro ( Nome/i)
|
||||
if ( vsParams.size() != 1)
|
||||
// 2 parametri : Id, PtNewEnd
|
||||
if ( vsParams.size() != 2)
|
||||
return false ;
|
||||
// recupero lista nomi
|
||||
INTVECTOR vnNames ;
|
||||
if ( ! GetNamesParam( vsParams[0], vnNames))
|
||||
// recupero la curva sorgente
|
||||
int nIdCrv = GetIdParam( vsParams[0]) ;
|
||||
ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// esecuzione inversione normale superficie
|
||||
INTVECTOR::iterator Iter ;
|
||||
for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) {
|
||||
ISurf* pSurf = GetSurf( m_pGDB->GetGeoObj( *Iter)) ;
|
||||
if ( pSurf == nullptr || ! pSurf->Invert())
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
// recupero il suo riferimento
|
||||
Frame3d frCrv ;
|
||||
if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv))
|
||||
return false ;
|
||||
// recupero il nuovo punto di fine
|
||||
Point3d ptNewEnd ;
|
||||
if ( ! GetPointParam( vsParams[1], frCrv, ptNewEnd))
|
||||
return false ;
|
||||
// eseguo la modifica
|
||||
return pCrv->ModifyEnd( ptNewEnd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
GdbExecutor::CurveModifyTrim( const STRVECTOR& vsParams, int nTrimType)
|
||||
{
|
||||
enum SeLp { SL, EL, SP, EP, SEP} ;
|
||||
|
||||
|
||||
// almeno 2 parametri : Nome, parametro [, secondo parametro]
|
||||
if ( vsParams.size() < 2)
|
||||
return false ;
|
||||
@@ -4475,26 +4474,12 @@ GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
double dPar ;
|
||||
if ( ! FromString( vsParams[1], dPar))
|
||||
return false ;
|
||||
// determino il tipo di trim
|
||||
SeLp StEnLenPar ;
|
||||
if ( sCmd2 == "STARTLEN" || sCmd2 == "SL")
|
||||
StEnLenPar = SL ;
|
||||
else if ( sCmd2 == "ENDLEN" || sCmd2 == "EL")
|
||||
StEnLenPar = EL ;
|
||||
else if ( sCmd2 == "STARTPAR" || sCmd2 == "SP")
|
||||
StEnLenPar = SP ;
|
||||
else if ( sCmd2 == "ENDPAR" || sCmd2 == "EP")
|
||||
StEnLenPar = EP ;
|
||||
else if ( sCmd2 == "STARTENDPAR" || sCmd2 == "SEP")
|
||||
StEnLenPar = SEP ;
|
||||
else
|
||||
return false ;
|
||||
// esecuzione trim
|
||||
INTVECTOR::iterator Iter ;
|
||||
for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) {
|
||||
ICurve* pCurve ;
|
||||
if ( ( pCurve = GetCurve( m_pGDB->GetGeoObj( *Iter))) != nullptr) {
|
||||
switch ( StEnLenPar) {
|
||||
switch ( nTrimType) {
|
||||
case SL :
|
||||
if ( ! pCurve->TrimStartAtLen( dPar))
|
||||
return false ;
|
||||
@@ -4530,17 +4515,54 @@ GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteSplitCurve( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
GdbExecutor::ExecuteCurveCopy( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
{
|
||||
if ( sCmd2 == "C" || sCmd2 == "CLASS")
|
||||
return SplitCurveByClass( vsParams) ;
|
||||
else
|
||||
return false ;
|
||||
if ( sCmd2 == "PR" || sCmd2 == "PARAMRANGE")
|
||||
return CurveCopyByParamRange( vsParams) ;
|
||||
else if ( sCmd2 == "SPC" || sCmd2 == "SPLITCLASS")
|
||||
return CurveCopyBySplitClass( vsParams) ;
|
||||
else if ( sCmd2 == "CHAIN")
|
||||
return CurveCopyByChain( vsParams) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::SplitCurveByClass( const STRVECTOR& vsParams)
|
||||
GdbExecutor::CurveCopyByParamRange( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 5 parametri : IdCrv, IdDest, IdGroupDest, StartPar, EndPar
|
||||
if ( vsParams.size() != 5)
|
||||
return false ;
|
||||
// recupero la curva sorgente
|
||||
int nIdCrv = GetIdParam( vsParams[0]) ;
|
||||
const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// recupero il suo riferimento
|
||||
Frame3d frCrv ;
|
||||
if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv))
|
||||
return false ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frDest))
|
||||
return false ;
|
||||
// recupero i parametri del range
|
||||
double dUStart, dUEnd ;
|
||||
if ( ! FromString( vsParams[3], dUStart) ||
|
||||
! FromString( vsParams[4], dUEnd))
|
||||
return false ;
|
||||
// copio la parte di curva che interessa e la porto nel riferimento del gruppo destinazione
|
||||
PtrOwner<ICurve> pCopy( pCrv->CopyParamRange( dUStart, dUEnd)) ;
|
||||
if ( ! ::IsValid( pCopy))
|
||||
return false ;
|
||||
pCopy->LocToLoc( frCrv, frDest) ;
|
||||
// la inserisco nel gruppo
|
||||
return AddGeoObj( vsParams[1], vsParams[2], ::Release( pCopy)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 6 parametri : IdCurve, IdClosedCurve, IdGroupIn, IdGroupOut, IdGroupOnP, IdGroupOnM
|
||||
if ( vsParams.size() != 6)
|
||||
@@ -4618,6 +4640,135 @@ GdbExecutor::SplitCurveByClass( const STRVECTOR& vsParams)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::CurveCopyByChain( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 3, 4 o 5 parametri : IdCurve/s, IdGroupDest, ptNearStart [, bAllowInvert [, dToler]]
|
||||
if ( vsParams.size() < 3)
|
||||
return false ;
|
||||
// recupero lista Id
|
||||
INTVECTOR vnNames ;
|
||||
if ( ! GetNamesParam( vsParams[0], vnNames))
|
||||
return false ;
|
||||
// recupero il gruppo destinazione e il suo riferimento
|
||||
int nIdDest = GetIdParam( vsParams[1]) ;
|
||||
Frame3d frDest ;
|
||||
if ( ! m_pGDB->GetGroupGlobFrame( nIdDest, frDest))
|
||||
return false ;
|
||||
// recupero il punto vicino alla partenza
|
||||
Point3d ptNearStart ;
|
||||
if ( ! GetPointParam( vsParams[2], frDest, ptNearStart))
|
||||
return false ;
|
||||
// recupero eventuale flag per consentire inversione di curve
|
||||
bool bAllowInvert = true ;
|
||||
if ( vsParams.size() >= 4 && ! FromString( vsParams[3], bAllowInvert))
|
||||
return false ;
|
||||
// recupero eventuale tolleranza
|
||||
double dToler = EPS_SMALL ;
|
||||
if ( vsParams.size() >= 5 && ! FromString( vsParams[4], dToler))
|
||||
return false ;
|
||||
// preparo i dati per il concatenamento
|
||||
ChainCurves chainC ;
|
||||
chainC.Init( bAllowInvert, dToler, int( vnNames.size())) ;
|
||||
INTVECTOR::iterator Iter ;
|
||||
for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) {
|
||||
// recupero la curva e il suo riferimento
|
||||
ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( *Iter)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
Frame3d frCrv ;
|
||||
if ( ! m_pGDB->GetGlobFrame( *Iter, frCrv))
|
||||
return false ;
|
||||
// recupero i dati della curva necessari al concatenamento e li assegno
|
||||
Point3d ptStart, ptEnd ;
|
||||
Vector3d vtStart, vtEnd ;
|
||||
if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetStartDir( vtStart) ||
|
||||
! pCrv->GetEndPoint( ptEnd) || ! pCrv->GetEndDir( vtEnd))
|
||||
return false ;
|
||||
ptStart.LocToLoc( frCrv, frDest) ;
|
||||
vtStart.LocToLoc( frCrv, frDest) ;
|
||||
ptEnd.LocToLoc( frCrv, frDest) ;
|
||||
vtEnd.LocToLoc( frCrv, frDest) ;
|
||||
if ( ! chainC.AddCurve( *Iter, ptStart, vtStart, ptEnd, vtEnd))
|
||||
return false ;
|
||||
}
|
||||
// recupero i percorsi concatenati
|
||||
INTVECTOR vIds ;
|
||||
while ( chainC.GetChainFromNear( ptNearStart, vIds)) {
|
||||
// creo una curva composita
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( ! IsValid( pCrvCompo))
|
||||
return false ;
|
||||
// recupero le curve semplici e le inserisco nella curva composita
|
||||
INTVECTOR::iterator Iter ;
|
||||
for ( Iter = vIds.begin() ; Iter != vIds.end() ; ++Iter) {
|
||||
int nId = abs( *Iter) ;
|
||||
bool bInvert = ( *Iter < 0) ;
|
||||
// recupero la curva e il suo riferimento
|
||||
ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nId)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
Frame3d frCrv ;
|
||||
if ( ! m_pGDB->GetGlobFrame( nId, frCrv))
|
||||
return false ;
|
||||
// copio la curva
|
||||
PtrOwner<ICurve> pCopCrv( pCrv->Clone()) ;
|
||||
if ( ! IsValid( pCopCrv))
|
||||
return false ;
|
||||
// se necessario, la inverto
|
||||
if ( bInvert)
|
||||
pCopCrv->Invert() ;
|
||||
// la sistemo per i riferimenti
|
||||
pCopCrv->LocToLoc( frCrv, frDest) ;
|
||||
// la aggiungo alla curva composta
|
||||
if ( ! pCrvCompo->AddCurve( ::Release( pCopCrv), true, dToler))
|
||||
return false ;
|
||||
}
|
||||
// aggiorno il nuovo punto vicino
|
||||
if ( pCrvCompo->GetCurveNumber() > 0)
|
||||
pCrvCompo->GetEndPoint( ptNearStart) ;
|
||||
// inserisco la curva composita nel gruppo destinazione
|
||||
if ( pCrvCompo->GetCurveNumber() > 0) {
|
||||
if ( m_pGDB->AddGeoObj( GDB_ID_NULL, nIdDest, ::Release( pCrvCompo)) == GDB_ID_NULL)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteSurfModify( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
{
|
||||
if ( sCmd2 == "INV" || sCmd2 == "INVERT")
|
||||
return SurfModifyInvert( vsParams) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::SurfModifyInvert( const STRVECTOR& vsParams)
|
||||
{
|
||||
// 1 parametro ( Nome/i)
|
||||
if ( vsParams.size() != 1)
|
||||
return false ;
|
||||
// recupero lista nomi
|
||||
INTVECTOR vnNames ;
|
||||
if ( ! GetNamesParam( vsParams[0], vnNames))
|
||||
return false ;
|
||||
// esecuzione inversione normale superficie
|
||||
INTVECTOR::iterator Iter ;
|
||||
for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) {
|
||||
ISurf* pSurf = GetSurf( m_pGDB->GetGeoObj( *Iter)) ;
|
||||
if ( pSurf == nullptr || ! pSurf->Invert())
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
|
||||
Reference in New Issue
Block a user