EgtGeomKernel :
- correzioni e migliorie a IntersCurveCurve.
This commit is contained in:
+116
-104
@@ -26,7 +26,7 @@ using namespace std ;
|
||||
static bool CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvAClosed, double dCrvASpan) ;
|
||||
static bool CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvBClosed, double dCrvBSpan) ;
|
||||
bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB = false) ;
|
||||
static void MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crvCompo) ;
|
||||
static int GetCrvBDirAPrev( IntCrvCrvInfo& Icci) ;
|
||||
static int GetCrvBDirANext( IntCrvCrvInfo& Icci) ;
|
||||
@@ -34,7 +34,6 @@ static bool CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nS
|
||||
const ICurve& CurveB, double dUB, int& nType) ;
|
||||
static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
|
||||
const ICurve& CurveB, double dUB1, double dUB2, int& nType) ;
|
||||
//static bool CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
@@ -430,13 +429,13 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
continue ;
|
||||
}
|
||||
// calcolo sottoindici
|
||||
int ki = 0 ; // del successivo si prende sempre il primo
|
||||
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
|
||||
int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
|
||||
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
|
||||
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
|
||||
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
|
||||
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) &&
|
||||
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) {
|
||||
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan, true)) {
|
||||
// caso entrambi Overlap ma di tipo opposto e sullo stesso tratto
|
||||
if ( m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq &&
|
||||
abs( m_Info[i].IciB[0].dU - m_Info[j].IciB[0].dU) < EPS_PARAM &&
|
||||
@@ -599,18 +598,19 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
|
||||
int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL) {
|
||||
if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
|
||||
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
|
||||
m_Info[i].IciB[ki].nPrevTy = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
|
||||
}
|
||||
}
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
int ki = ( m_Info[i].bOverlap ? 1 : 0) ;
|
||||
ki = ( m_Info[i].bOverlap && m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
|
||||
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[0].nPrevTy ;
|
||||
m_Info[i].IciB[ki].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -781,7 +781,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
|
||||
// verifico se una curva ha tutte le info e queste info sono coerenti
|
||||
if ( m_nNumInters > 1) {
|
||||
if ( m_nNumInters > 1 && ! bAutoInters) {
|
||||
bool bCoherent = true ;
|
||||
INTVECTOR vIncoherenceWithPrev ;
|
||||
INTVECTOR vNewOverlap ;
|
||||
@@ -822,9 +822,10 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// salvo eventuali incoerenze col precedente
|
||||
for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[0].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[0].nPrevTy) &&
|
||||
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[0].nPrevTy != ICCT_SPK) {
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[ki].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[ki].nPrevTy) &&
|
||||
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[ki].nPrevTy != ICCT_SPK) {
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
bCoherent = false ;
|
||||
}
|
||||
@@ -833,11 +834,12 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
if ( ! bCoherent) {
|
||||
for ( int i : vIncoherenceWithPrev) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
int nType = 0 ;
|
||||
CalcSide( j, i, &CCompoB, &CCompoA, false, nType) ;
|
||||
if ( nType != ICCT_ON) {
|
||||
m_Info[i].IciB[0].nPrevTy = nType ;
|
||||
m_Info[i].IciB[ki].nPrevTy = nType ;
|
||||
m_Info[j].IciB[kj].nNextTy = nType ;
|
||||
}
|
||||
else
|
||||
@@ -909,91 +911,91 @@ IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICu
|
||||
nType = ICCT_IN ;
|
||||
else if ( nType == MDS_RIGHT)
|
||||
nType = ICCT_OUT ;
|
||||
//// se lo trovo sulla curva controllo se posso definire un tratto overlap
|
||||
//if ( nType == MDS_ON) {
|
||||
// double dFactor = 1./3. ;
|
||||
// DBLVECTOR vdU(2) ;
|
||||
// bool bIsOn = false ;
|
||||
// if ( bCrvAOrB) {
|
||||
// if ( bPrevIsBefore) {
|
||||
// vdU[0] = ( 1 - dFactor) * Icci2.IciA[0].dU + dFactor * Icci1.IciA[kj].dU ;
|
||||
// vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[0].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
|
||||
// }
|
||||
// else if ( Icci2.IciA[0].dU > 2 * EPS_SMALL){
|
||||
// vdU[0] = ( Icci2.IciA[0].dU + 0.) * dFactor ;
|
||||
// vdU[1] = ( Icci2.IciA[0].dU + 0.) * 2 * dFactor ;
|
||||
// }
|
||||
// else
|
||||
// bIsOn = true ;
|
||||
// }
|
||||
// else {
|
||||
// if ( bPrevIsBefore) {
|
||||
// vdU[0] = ( 1 - dFactor) * Icci2.IciB[0].dU + dFactor * Icci1.IciB[kj].dU ;
|
||||
// vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[0].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
|
||||
// }
|
||||
// else if ( Icci2.IciB[0].dU > 2 * EPS_SMALL) {
|
||||
// vdU[0] = ( Icci2.IciB[0].dU + 0.) * dFactor ;
|
||||
// vdU[1] = ( Icci2.IciB[0].dU + 0.) * 2 * dFactor ;
|
||||
// }
|
||||
// else
|
||||
// bIsOn = true ;
|
||||
// }
|
||||
// if ( ! bIsOn) {
|
||||
// bIsOn = true ;
|
||||
// for ( int k = 0 ; k < ssize(vdU) && bIsOn ; ++k) {
|
||||
// Point3d ptTest2 ; pThisCrv->GetPointD1D2( vdU[k], ICurve::FROM_MINUS, ptTest2) ;
|
||||
// DistPointCurve dpc2( ptTest2, *pOtherCrv) ;
|
||||
// dpc2.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
|
||||
// if ( nType != MDS_ON)
|
||||
// bIsOn = false ;
|
||||
// }
|
||||
// }
|
||||
// if ( bIsOn) {
|
||||
// m_Info[i].bOverlap = true ;
|
||||
// Vector3d vtDirThis, vtDirOther ;
|
||||
// Point3d ptCommon ;
|
||||
// double dUThis = 0 ;
|
||||
// if ( bCrvAOrB)
|
||||
// dUThis = m_Info[i].IciA[0].dU ;
|
||||
// else
|
||||
// dUThis = m_Info[i].IciB[0].dU ;
|
||||
// pThisCrv->GetPointD1D2( dUThis, ICurve::Side::FROM_MINUS, ptCommon, &vtDirThis) ;
|
||||
// double dUOther = 0 ; pOtherCrv->GetParamAtPoint( ptCommon, dUOther) ;
|
||||
// pOtherCrv->GetPointD1D2( dUOther, ICurve::Side::FROM_MINUS, ptCommon, &vtDirOther) ;
|
||||
// m_Info[i].bCBOverEq = vtDirThis * vtDirOther > 0 ;
|
||||
// if ( m_Info[i].bCBOverEq) {
|
||||
// m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
// m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
// m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
// m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
// m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
// m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
// }
|
||||
// else {
|
||||
// if ( bCrvAOrB) {
|
||||
// m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
// m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
// m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
// m_Info[i].IciB[1] = m_Info[j].IciB[kj] ;
|
||||
// m_Info[i].IciB[0].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciB[1].nNextTy = ICCT_ON ;
|
||||
// }
|
||||
// else {
|
||||
// m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
// m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
// m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
// m_Info[i].IciA[1] = m_Info[j].IciA[kj] ;
|
||||
// m_Info[i].IciA[0].nPrevTy = ICCT_ON ;
|
||||
// m_Info[i].IciA[1].nNextTy = ICCT_ON ;
|
||||
// }
|
||||
// }
|
||||
// nType = ICCT_ON ;
|
||||
// }
|
||||
//}
|
||||
// se lo trovo sulla curva controllo se posso definire un tratto overlap
|
||||
if ( nType == MDS_ON) {
|
||||
double dFactor = 1./3. ;
|
||||
DBLVECTOR vdU(2) ;
|
||||
bool bIsOn = false ;
|
||||
if ( bCrvAOrB) {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciA[0].dU + dFactor * Icci1.IciA[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[0].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciA[0].dU > 2 * EPS_SMALL){
|
||||
vdU[0] = ( Icci2.IciA[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciA[0].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
}
|
||||
else {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciB[0].dU + dFactor * Icci1.IciB[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[0].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciB[0].dU > 2 * EPS_SMALL) {
|
||||
vdU[0] = ( Icci2.IciB[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciB[0].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
}
|
||||
if ( ! bIsOn) {
|
||||
bIsOn = true ;
|
||||
for ( int k = 0 ; k < ssize(vdU) && bIsOn ; ++k) {
|
||||
Point3d ptTest2 ; pThisCrv->GetPointD1D2( vdU[k], ICurve::FROM_MINUS, ptTest2) ;
|
||||
DistPointCurve dpc2( ptTest2, *pOtherCrv) ;
|
||||
dpc2.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ;
|
||||
if ( nType != MDS_ON)
|
||||
bIsOn = false ;
|
||||
}
|
||||
}
|
||||
if ( bIsOn) {
|
||||
m_Info[i].bOverlap = true ;
|
||||
Vector3d vtDirThis, vtDirOther ;
|
||||
Point3d ptCommon ;
|
||||
double dUThis = 0 ;
|
||||
if ( bCrvAOrB)
|
||||
dUThis = m_Info[i].IciA[0].dU ;
|
||||
else
|
||||
dUThis = m_Info[i].IciB[0].dU ;
|
||||
pThisCrv->GetPointD1D2( dUThis, ICurve::Side::FROM_MINUS, ptCommon, &vtDirThis) ;
|
||||
double dUOther = 0 ; pOtherCrv->GetParamAtPoint( ptCommon, dUOther) ;
|
||||
pOtherCrv->GetPointD1D2( dUOther, ICurve::Side::FROM_MINUS, ptCommon, &vtDirOther) ;
|
||||
m_Info[i].bCBOverEq = vtDirThis * vtDirOther > 0 ;
|
||||
if ( m_Info[i].bCBOverEq) {
|
||||
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
}
|
||||
else {
|
||||
if ( bCrvAOrB) {
|
||||
m_Info[i].IciA[1] = m_Info[i].IciA[0] ;
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciA[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciB[0].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[1].nNextTy = ICCT_ON ;
|
||||
}
|
||||
else {
|
||||
m_Info[i].IciB[1] = m_Info[i].IciB[0] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[kj] ;
|
||||
m_Info[i].IciB[1].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciB[0].nNextTy = ICCT_ON ;
|
||||
m_Info[i].IciA[1] = m_Info[j].IciA[kj] ;
|
||||
m_Info[i].IciA[0].nPrevTy = ICCT_ON ;
|
||||
m_Info[i].IciA[1].nNextTy = ICCT_ON ;
|
||||
}
|
||||
}
|
||||
nType = ICCT_ON ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1245,11 +1247,21 @@ CompatibleParamA( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CompatibleParamB( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,
|
||||
bool bCrvBClosed, double dCrvBSpan)
|
||||
bool bCrvBClosed, double dCrvBSpan, bool bOrderedOnB)
|
||||
{
|
||||
int k = ( Icci1.bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
|
||||
if ( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvBClosed || abs( abs( Icci1.IciB[k].dU - Icci2.IciB[0].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM))
|
||||
int j = 0 ;
|
||||
int k = 0 ;
|
||||
if ( ! bOrderedOnB) {
|
||||
j = 0 ;
|
||||
k = Icci1.bOverlap ? 1 : 0 ;
|
||||
}
|
||||
else {
|
||||
j = Icci2.bOverlap && ! Icci2.bCBOverEq ? 1 : 0 ;
|
||||
k = Icci1.bOverlap && Icci1.bCBOverEq ? 1 : 0 ;
|
||||
}
|
||||
|
||||
if ( abs( Icci1.IciB[k].dU - Icci2.IciB[j].dU) > 0.1 * SPAN_PARAM &&
|
||||
( ! bCrvBClosed || abs( abs( Icci1.IciB[k].dU - Icci2.IciB[j].dU) - dCrvBSpan) > 0.1 * SPAN_PARAM))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVECLASSCRV 0
|
||||
#if SAVECLASSCRV
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1374,6 +1379,15 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
|
||||
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
// intersezione
|
||||
|
||||
#if SAVECLASSCRV
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.push_back( Crv.Clone()) ;
|
||||
vGeo.push_back( pLoop->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\crv_and_loop.nge") ;
|
||||
#endif
|
||||
|
||||
IntersCurveCurve ccInt( Crv, *pLoop) ;
|
||||
// classificazione
|
||||
CRVCVECTOR ccPart ;
|
||||
|
||||
+1
-1
@@ -1155,7 +1155,7 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::Translate( const Vector3d & vtMove)
|
||||
Voronoi::Translate( const Vector3d& vtMove)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
Reference in New Issue
Block a user