Merge branch 'master' into FasterVMill5Axis

This commit is contained in:
Daniele Bariletti
2025-07-21 09:03:18 +02:00
14 changed files with 1122 additions and 538 deletions
+152 -109
View File
@@ -311,7 +311,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol,
bool bAdvCorners)
{
// se non ho polylinee, allora esco
if ( vPL.empty())
return true ;
@@ -341,10 +340,45 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv))
return false ;
#if ENABLE_SHARPED_EDGES_DEBUG
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
// ombra del tool
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
// 1° gruppo, griglia di punti
for ( int j = 0 ; j <= nStepY ; ++ j) {
for ( int i = 0 ; i <= nStepX ; ++ i) {
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
myPtGrid->Set( ptP) ;
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
vvCol[0].emplace_back( BLUE) ;
}
}
// 2° gruppo, superfici
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
if ( ! IsNull( pMyStm)) {
pMyStm->ToLoc( frGrid) ;
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
}
}
#endif
// vettore delle polyline visitate ( viste però come curve composite)
ICRVCOMPOPOVECTOR vPL_AsCompo ; vPL_AsCompo.reserve( vPL.size()) ;
// scorro i Chunk della matrice di interi, quindi le righe
for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) {
// scorro le PolyLinee presenti nel Chunk
for ( int nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) {
for ( int nLoop = 0 ; nLoop < int( mIndMat[nChunk].size()) ; ++ nLoop) {
// recupero l'indice della PolyLine di riferimento
int nPol = mIndMat[nChunk][nLoop] ;
if ( nPol < 0 || nPol >= int( vPL.size()))
return false ;
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla
int nPts = vPL[nPol].GetPointNbr() ;
if ( nPts < 4)
@@ -380,33 +414,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
#if ENABLE_SHARPED_EDGES_DEBUG
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
// ombra del tool
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
// 1° gruppo, griglia di punti
for ( int j = 0 ; j <= nStepY ; ++ j) {
for ( int i = 0 ; i <= nStepX ; ++ i) {
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
myPtGrid->Set( ptP) ;
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
vvCol[0].emplace_back( BLUE) ;
break ;
}
break ;
}
// 2° gruppo, superfici
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
if ( ! IsNull( pMyStm)) {
pMyStm->ToLoc( frGrid) ;
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
}
}
// 3° gruppo, punti della PolyLine
for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) {
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
@@ -416,23 +423,23 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
}
#endif
// modifico la posizione dei punti
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
return false ;
// modifico la posizione dei punti
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
return false ;
// ricostrusico la polyLine
vPL[nPol].Clear() ;
// ricostrusico la polyLine a partire da una vuota
PolyLine PL_New ;
double dPar = -1 ;
for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) {
// se punto valido o sharped di angolo interno, lo aggiungo
if ( j == 0 || j == int( vAdvPt.size() - 1) ||
vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT)
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
// se è un punto sharped di un angolo esterno
else if ( vAdvPt[j].second == PointType::SHARPED_EXT) {
// se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto
if ( ! bAdvCorners)
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
else {
// ricavo il punto a minima distanza dal materiale mediante metodo di bisezione
Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ;
@@ -463,51 +470,29 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ;
distPtLPrev.GetMinDistPoint( ptMinDistA) ;
distPtLSucc.GetMinDistPoint( ptMinDistB) ;
vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ;
vPL[nPol].AddUPoint( ++ dPar, ptTest) ;
vPL[nPol].AddUPoint( ++ dPar, ptMinDistB) ;
}
PL_New.AddUPoint( ++ dPar, ptMinDistA) ;
PL_New.AddUPoint( ++ dPar, ptTest) ;
PL_New.AddUPoint( ++ dPar, ptMinDistB) ;
#if ENABLE_SHARPED_EDGES_DEBUG
// 5° gruppo, punti minDist A e B e ptMid
/*PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
myPtA->Set( ptMinDistA) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
myPtB->Set( ptMinDistB) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
myPtMid->Set( ptTest) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
vvCol[4].emplace_back( BROWN) ;*/
#endif
#if ENABLE_SHARPED_EDGES_DEBUG
// 5° gruppo, punti minDist A e B e ptMid
PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
myPtA->Set( ptMinDistA) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
myPtB->Set( ptMinDistB) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
vvCol[4].emplace_back( BROWN) ;
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
myPtMid->Set( ptTest) ;
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
vvCol[4].emplace_back( BROWN) ;
#endif
}
}
}
// riposiziono la polyLine
#if ENABLE_SHARPED_EDGES_DEBUG
// 6° gruppo, curve composita derivante dalla polyline
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
pCrvCompoPoly->FromPolyLine( vPL[nPol]) ;
//pCrvCompoPoly->SetExtrusion( frGrid.VersZ()) ;
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
vvCol[5].emplace_back( RED) ;
// 7° gruppo, controOffset
OffsetCurve offsCrv ;
offsCrv.Make( pCrvCompoPoly, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
pCrvCompoPoly.Set( ConvertCurveToComposite( offsCrv.GetLongerCurve())) ;
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( Release( pCrvCompoPoly))) ;
vvCol[6].emplace_back( WHITE) ;
string myName = Sharped_Edges_Debug_File_Name +
to_string( nChunk) + "_" +
to_string( nPol) + "_" +
to_string( dLevel) + "_" +
to_string( dAngTol) + ".nge" ;
SaveGeoObj( vvpGObj, vvCol, myName) ;
#endif
// se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla
// trimesh rischio di evere Chunk distinti uniti in un unico Chunk
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
@@ -515,11 +500,53 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
return false ;
pCompo->FromPolyLine( vPL[nPol]) ;
SelfIntersCurve SIC( *pCompo) ;
if ( SIC.GetCrossOrOverlapIntersCount() > 0)
continue ;
bool bDiscard = ( SIC.GetCrossOrOverlapIntersCount() > 0) ;
if ( ! bDiscard) {
// se la polyLine interseca una delle PolyLine precedenti, non la modifico
for ( auto& pCompoPL_Prev : vPL_AsCompo) {
IntersCurveCurve ICC( *pCompo, *pCompoPL_Prev) ;
if ( ICC.GetCrossOrOverlapIntersCount() > 0) {
bDiscard = true ;
break ;
}
}
}
// se nuova approssimazione da conservare, memorizzo i risultati
if ( ! bDiscard) {
vPL[nPol] = PL_New ;
vPL_AsCompo.emplace_back( Release( pCompo)) ;
}
}
}
#if ENABLE_SHARPED_EDGES_DEBUG
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
for ( const auto& PL : vPL) {
// 6° gruppo, curve composita derivante dalla polyline
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
pCrvCompoPoly->FromPolyLine( PL) ;
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
vvCol[5].emplace_back( RED) ;
vpCrv.emplace_back( Release( pCrvCompoPoly)) ;
}
// 7° gruppo, controOffset
ICURVEPOVECTOR vCrvCompoOffs ;
if ( ! CalcOffsetCurves( vpCrv, vCrvCompoOffs, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND)) {
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
return false ;
}
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
for ( const auto& pCvrOffs : vCrvCompoOffs) {
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCvrOffs))) ;
vvCol[6].emplace_back( WHITE) ;
}
string myName = Sharped_Edges_Debug_File_Name +
to_string( dLevel) + "_" +
to_string( dAngTol) + ".nge" ;
SaveGeoObj( vvpGObj, vvCol, myName) ;
#endif
return true ;
}
@@ -785,21 +812,31 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false))
swap( vPL_Sharped, vPL) ;
// se vettore di PolyLine vuoto, non faccio nulla
if ( vPL.empty())
return true ;
// se non ho impostato un utensile, devo effettuare un contro-offset
if ( ! bTool) {
POLYLINEVECTOR vPL_Offs ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
CurveComposite crvCompo ;
if ( ! crvCompo.FromPolyLine( vPL[i]))
return false ;
OffsetCurve offsCompo ;
offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ;
while ( ! IsNull( pCrvOffset)) {
ICURVEPOVECTOR vpOwCrv ; vpOwCrv.reserve( vPL.size()) ;
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
for ( const auto& PL : vPL) {
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
pCrvCompoPoly->FromPolyLine( PL) ;
vpOwCrv.emplace_back( Release( pCrvCompoPoly)) ;
vpCrv.emplace_back( vpOwCrv.back()) ;
}
// calcolo l'Offset
ICURVEPOVECTOR vpCrvOffs ;
if ( ! CalcOffsetCurves( vpCrv, vpCrvOffs, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND))
return false ;
// resituisco le PolyLine
POLYLINEVECTOR vPL_Offs ; vPL_Offs.reserve( vpCrvOffs.size()) ;
for ( auto& pCrv : vpCrvOffs) {
if ( pCrv != nullptr && pCrv->IsValid()) {
PolyLine myPolyLine ;
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
vPL_Offs.emplace_back( myPolyLine) ;
pCrvOffset.Set( offsCompo.GetLongerCurve()) ;
}
}
swap( vPL_Offs, vPL) ;
@@ -976,28 +1013,13 @@ CAvParSilhouettesSurfTm::Prepare( void)
return false ;
b3All.Add( b3Surf) ;
}
// calcolo dati della griglia
const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ;
// espansione in Z del Box
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
b3All.Expand( 0., 0., EXTRA_Z) ;
m_dDimZ = b3All.GetDimZ() ;
m_dLevelOffs = - b3All.GetMin().z ;
// calcolo dei punti della griglia (sul top del cilindro)
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
int nInd = i + j * ( m_nStepX + 1) ;
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
vPntM[nInd] = { ptP, 0.} ;
}
}
// esecuzione della verifica
// set utensile corrente per calcolo delle collisioni
double dExtraXY = m_dRad ;
if ( m_dSideAng < EPS_ANG_SMALL)
m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
else {
@@ -1015,8 +1037,29 @@ CAvParSilhouettesSurfTm::Prepare( void)
double dStemRad = m_dRad + dDeltaRad ;
double dTipRad = m_dRad ;
dExtraXY = dStemRad ;
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
}
// calcolo dati della griglia
const double EXTRA_XY = ( m_bTool ? dExtraXY + 2. : 1.5 * m_dTol) ;
b3All.Expand( EXTRA_XY, EXTRA_XY, 0.) ;
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
m_dLevelOffs = - b3All.GetMin().z ;
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
// calcolo dei punti della griglia (sul top del cilindro)
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
int nInd = i + j * ( m_nStepX + 1) ;
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
vPntM[nInd] = { ptP, 0.} ;
}
}
// esecuzione verifica della collisione
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
return false ;
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
+229 -111
View File
@@ -56,6 +56,7 @@ struct PocketParams {
double dMaxOptSize = 0. ; // dimensione per ottimizzazione
double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag
double dLiTang = INFINITO ; // valore di LeadIn in ingresso
bool bCalcUnclearedRegs = true ; // flag per calcolare o meno le regioni non svuotate
bool bOptOffsets = true ; // flag per evitare Offset non necessari
bool bAboveHead = true ; // flag per testa da sopra ( Z+)
bool bSmooth = false ; // curve smussate
@@ -398,6 +399,16 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV
return true ;
}
//----------------------------------------------------------------------------
static bool
SwapSideBySecondTempParam( ICurveComposite* pCompo)
{
if ( pCompo == nullptr || ! pCompo->IsValid())
return false ;
pCompo->SetTempParam( int( pCompo->GetTempParam( 1)) == MDS_LEFT ? MDS_RIGHT : MDS_LEFT, 1) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll)
@@ -462,7 +473,7 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdg
pNewCrv->SetTempProp( pCrv->GetTempProp( 0), 0) ;
pNewCrv->SetTempProp( pCrv->GetTempProp( 1), 1) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 1), 1) ;
double dThick ; pCrv->GetThickness( dThick) ;
pNewCrv->SetThickness( dThick) ;
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
@@ -4784,7 +4795,7 @@ CalcSpecialBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart,
pZigZagLink->AddLine( ptNew) ;
}
// questa composita contiene al massimo 5 curve e, in generale, quella una curva molto più lunga
// questa composita contiene al massimo 5 curve e, in generale, una curva molto più lunga
// delle altre ( quella che collega le due estensioni calcolate). Spezzo la composita ottenuta in curve
// la cui lunghezza massima è circa il raggio utensile
PolyLine PL ;
@@ -4965,12 +4976,14 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM
double dLenS ; pCrvS->GetLength( dLenS) ;
double dLenE ; pCrvE->GetLength( dLenE) ;
// se ho una curva di primo Offset allora non devo accorciarla ( sia per bordi esterni che per isole)
// azzero i parametri per curve di primo Offset
for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) {
if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE))
dLenPercS = 0. ;
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
dLenPercE = 0. ;
#if 0
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
dLenPercE = 0. ;
#endif
}
#if 0 // nel caso volessi estendere anche prima del punto finale
double dLStepS = ( dLenPercS < EPS_SMALL ? 0. : PockParams.dRad) ;
@@ -5025,14 +5038,17 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM
//----------------------------------------------------------
static bool
GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ISurfFlatRegion* pSrfToCut)
GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ISurfFlatRegion* pSfrUncleared)
{
// se non devo nè calcolare la Feed nè calcolare le regioni svuotate, allora non faccio nulla
if ( ! PockParams.bCalcFeed && ! PockParams.bCalcUnclearedRegs)
return true ;
// controllo dei parametri
if ( vFirstOffs.empty() || int( vOffs.size()) < int( vFirstOffs.size()))
return false ;
pSrfToCut->Clear() ;
pSfrUncleared->Clear() ;
// creo la regione esterna ( definita dalle curve di primo Offset)
// NB. Questa regione è diversa dalla pSfrOrig :
@@ -5053,7 +5069,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
}
}
// 2) creo la regione che all'esterno contiene i lati aperti
// creo la regione che all'esterno contiene i lati aperti
// NB. Prendendo la superficie originale ( con lati Open/Close impostati), se effettuo un
// Offset interno dell'estensione degli aperti, tutto ciò che è all'esterno di tale regione è classificato
// come lato aperto
@@ -5081,6 +5097,9 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
// recupero le proprietà temporanee
int nProp0 = vOffs[i]->GetTempProp( 0) ;
int nProp1 = vOffs[i]->GetTempProp( 1) ;
// il primo TempParam viene settato in proporzione alla Feed
// il secondo TempParam contiene l'nSide della curva
double dTempPar1 = vOffs[i]->GetTempParam( 1) ;
// Feed
bool bFirstOffs = false ;
@@ -5100,10 +5119,11 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
pSfrTool.Set( pSrfToolOffs) ;
else
pSfrTool->Add( *pSrfToolOffs) ;
pSfrTool->Add( *pSrfToolOffs) ;
}
vOffs[i]->SetTempProp( nProp0, 0) ;
vOffs[i]->SetTempProp( nProp1, 1) ;
vOffs[i]->SetTempParam( dTempPar1, 1) ;
// ================= LINK ================================
int nLink_Ind = ( bFollowOrder ? i + 1 : i) ;
@@ -5125,7 +5145,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
if ( ! IsNull( pSfrToolLink)) {
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
pSfrTool.Set( pSfrToolLink) ;
else
else
pSfrTool->Add( *pSfrToolLink) ;
}
// risetto il Link come curva composita ...
@@ -5136,10 +5156,12 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
}
// 4) Creo la regione contenente tutte le parti non svuotate
pSrfToCut->CopyFrom( pSrfExtern) ;
if ( ! pSrfToCut->Subtract( *pSfrTool))
return false ;
// se rischiesto, creo la regione contenente tutte le parti non svuotate
if ( PockParams.bCalcUnclearedRegs) {
pSfrUncleared->CopyFrom( pSrfExtern) ;
if ( ! pSfrUncleared->Subtract( *pSfrTool))
return false ;
}
return true ;
}
@@ -5150,12 +5172,13 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
const Point3d& ptToGo, const PocketParams& PockParams,
int& nInd, Point3d& ptCloser, bool& bFirstOffs)
{
/*
E' richiesto che le curve di Offset presentino le seguenti TempProps :
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
[per SPIRAL le proprietà sono ricavate automaticamente]
*/
// E' richiesto che le curve di Offset presentino le seguenti proprietà :
// - CONFORMAL
// * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter)
// * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// - SPIRAL
// * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno
// * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// controllo dei parametri
nInd = -1 ;
@@ -5177,10 +5200,8 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
vOffsPtMinDist[i].nInd = i ;
// nel caso di Conformal, escludo le curve di primo Offset dalla ricerca
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
bool bSkip = false ;
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) && ! bSkip ; ++ j)
bSkip = ( vOffs[i]->GetTempProp( 0) == 0) ; // prima iterazione
if ( bSkip) {
// prima iterazione
if ( vOffs[i]->GetTempProp( 0) == 0) {
vOffsPtMinDist[i].bFirstOffs = true ;
continue ;
}
@@ -5190,26 +5211,16 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
// in questo modo riesco a creare le curve a ricciolo
int nSide ;
DistPointCurve DistPtCrv( ptToGo, *vOffs[i]) ;
bool bFirstBorderIsland = false ;
if ( DistPtCrv.GetSideAtMinDistPoint( EPS_SMALL, Z_AX, nSide)) {
// nel caso Spiral
if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) {
// InVsOut
vOffsPtMinDist[i].bInVsOut = ( ( ! PockParams.bInvert && nSide == MDS_LEFT) ||
( PockParams.bInvert && nSide == MDS_RIGHT)) ;
vOffsPtMinDist[i].bInVsOut = ( int( vOffs[i]->GetTempParam( 1) != nSide)) ;
// controllo se la curva in questione è di primo Offset
Point3d ptCheck ; vOffs[i]->GetStartPoint( ptCheck) ;
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) ; ++ j) {
if ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100 * EPS_SMALL)) {
vOffsPtMinDist[i].bFirstOffs = true ;
// controllo se Isola o di bordo
double dArea = 0. ;
vOffs[i]->GetAreaXY( dArea) ;
bFirstBorderIsland = ( ( ! PockParams.bInvert && dArea < 0.) ||
( PockParams.bInvert && dArea > 0.)) ;
// se isola di primo Offset, InVsOut va invertito
if ( bFirstBorderIsland)
vOffsPtMinDist[i].bInVsOut = ( ! vOffsPtMinDist[i].bInVsOut) ;
break ;
}
}
@@ -5228,7 +5239,7 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
PockParams.dSideStep + PockParams.dSideStep ;
}
// se curva di bordo esterno, aggiungo un'altra penalità ( euristica)
if ( vOffsPtMinDist[i].bFirstOffs && ! bFirstBorderIsland)
if ( vOffsPtMinDist[i].bFirstOffs)
vOffsPtMinDist[i].dSqDist *= 2. ;
}
}
@@ -5249,12 +5260,17 @@ static bool
RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs,
ICRVCOMPOPOVECTOR& vOffsFirstCurve, const PocketParams& PockParams)
{
/*
E' richiesto che le curve di Offset presentino le seguenti TempProps :
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
[per SPIRAL le proprietà sono ricavate automaticamente]
*/
// se non devo calcolare le regioni non svuotate, esco subito
if ( ! PockParams.bCalcUnclearedRegs)
return true ;
// E' richiesto che le curve di Offset presentino le seguenti proprietà :
// - CONFORMAL
// * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter)
// * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// - SPIRAL
// * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno
// * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// se non ho nessuna superficie valida da svuotare, allora esco
if ( pSfrUncleared == nullptr)
@@ -5267,17 +5283,15 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR&
for ( int nC = 0 ; nC < pSfrUncleared->GetChunkCount() ; ++ nC) {
// recupero il centroide del Chunk da rimuovere
Point3d ptCentroid ; pSfrUncleared->GetChunkCentroid( nC, ptCentroid) ;
/*
Tra tutte le curve di Offset escludo le curve che :
- Sono di primo Offset
- Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
... cerco la più vicina tra le rimanenti
*/
// Tra tutte le curve di Offset escludo le curve che :
// - Sono di primo Offset
// - Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
// ... cerco la più vicina tra le rimanenti
// recupero la curva migliore
int nInd = -1 ;
Point3d ptCloser ;
bool bFirstOffs = false ;
if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams,
if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams,
nInd, ptCloser, bFirstOffs))
return false ;
// se nessun indice trovato, salto il chunk
@@ -5570,6 +5584,9 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
vLinks.clear() ;
vLinks.resize( int( vOffs.size())) ;
// NB. Dato che le curve di Offset sono invertite a seconda di dove si trova il materiale,
// Utilizzo il secondo TempParam per evere l'nSide
// scorro tutte le curva di Offset
for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) {
@@ -5577,6 +5594,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
Point3d ptS ;
if ( ! vOffs[i]->GetStartPoint( ptS))
return false ;
// tra le curve successive cerco la curva interna e più vicina ad essa
int nNextInd = -1 ; // indice della curva successiva
double dMinDist = INFINITO ; // distanza tra questa curva e la successiva
@@ -5588,8 +5606,8 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
// se interna
if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) &&
int( ccClass.size()) == 1 &&
( ( ! PockParams.bInvert && ccClass[0].nClass == CRVC_IN) ||
( PockParams.bInvert && ccClass[0].nClass == CRVC_OUT))) {
( ( ccClass[0].nClass == CRVC_IN && int( vOffs[i]->GetTempParam( 1)) == MDS_RIGHT) ||
( ccClass[0].nClass == CRVC_OUT && int( vOffs[i]->GetTempParam( 1)) == MDS_LEFT))) {
// calcolo la distanza minima tra essa
int nFlag ;
double dPar = 0. ;
@@ -5649,13 +5667,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
// scambio la curva i+1 esima con la j-esima ( se non sono già in ordine)
if ( nNextInd != i + 1)
swap( vOffs[nNextInd], vOffs[i+1]) ;
// cambio il suo punto iniziale nel punto più vicino tovato
double dUS ;
if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL))
return false ;
vOffs[i+1]->ChangeStartPoint( dUS) ;
// accorcio la curva per raccordarmi in tangenza con la successiva
// se ho più di una curva di Offset
if ( int( vOffs.size()) > 1) {
// clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle )
PtrOwner<ICurveComposite> pCrv_i( vOffs[i]->Clone()) ;
@@ -5666,15 +5685,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
if ( IsNull( pCrvLink))
return false ;
// NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset
double dLenPercS = ( i == 0 ? 0. : 10 * EPS_SMALL) ;
double dLenPercE = ( bMinDistAtSmooth ? 0. : 10 * EPS_SMALL) ;
if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) ||
! pCrvLink->IsValid()) {
// se non sono riuscito, cerco una strada più semplice ripristinando le curve
pCrvLink->Clear() ;
vOffs[i].Set( pCrv_i) ; // chiuso
vOffs[i+1].Set( pCrv_ii) ; // chiuso
vOffs[i].Set( pCrv_i) ;
vOffs[i+1].Set( pCrv_ii) ;
// recupero i vettori tangenti iniziali ( le curve sono chiuse )
Vector3d vtS, vtE ;
if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE))
@@ -5728,6 +5746,10 @@ CheckIfOffsetIsNecessary( const ISurfFlatRegion* pSfrAct, const ICurveComposite*
if ( ! PockParams.bOptOffsets)
return true ;
// se spiral out non vanno eliminati parti di percorso
if ( PockParams.nType == POCKET_SPIRALOUT)
return true ;
if ( nIter != 0) { // controllo se sono almeno al secondo offset...
// per ogni curva controllo se il suo Offset massimo non genera alcuna regione
double dMaxOffs ;
@@ -5819,6 +5841,55 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po
return true ;
}
//----------------------------------------------------------------------------
static int
CalcInversionForSpiralOffset( const ISurfFlatRegion* pSfrChunk)
{
// controllo validità della regione
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
return -1 ;
// Caso 0 : Non esistono isole
// Caso 1 : Loop Esterno Chiuso e, se esiste, Isola Chiusa
// Caso 2 : Loop Esterno Chiuso e, se esiste, Isola Aperta
// Caso 3 : Loop Esterno Aperto e, se esiste, Isola Chiusa
// Caso 4 : Loop Esterno Aperto e, se esiste, Isola Aperta
// se non esistono isole, allora Caso 0
if ( pSfrChunk->GetLoopCount( 0) == 1)
return 0 ;
// Il Loop esterno è considerato chiuso <=> esiste almeno una curva chiusa
bool bExtClosed = false ;
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, 0) && ! bExtClosed ; ++ nU) {
int nTempProp = TEMP_PROP_INVALID ;
bExtClosed = ( pSfrChunk->GetCurveTempProp( 0, 0, nU, nTempProp) &&
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
}
// Le isole vengono classificate come tutte chiuse <=> esiste almeno un isola chiusa
bool bIntClosed = false ;
for ( int nLoop = 1 ; nLoop < pSfrChunk->GetLoopCount( 0) && ! bIntClosed ; ++ nLoop) {
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, nLoop) && ! bIntClosed ; ++ nU) {
int nTempProp = TEMP_PROP_INVALID ;
bIntClosed = ( pSfrChunk->GetCurveTempProp( 0, nLoop, nU, nTempProp) &&
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
}
}
// restituisco il caso corrente
if ( bExtClosed && bIntClosed)
return 1 ;
if ( bExtClosed && ! bIntClosed)
return 2 ;
if ( ! bExtClosed && bIntClosed)
return 3 ;
if ( ! bExtClosed && ! bIntClosed)
return 4 ;
return -1 ;
}
//----------------------------------------------------------------------------
static bool
CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart,
@@ -5833,14 +5904,19 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// ciclo di offset verso l'interno
const int MAX_ITER = 1000 ;
int nIter = 0 ;
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
// tengo una copia della regione corrente da svuotare
PtrOwner<ISurfFlatRegion> pSrfAct( CloneSurfFlatRegion( pSfrPock)) ;
if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0)
return false ;
// ricavo il tipo di relazione descritta tra Open/Close di bordo esterno e/o isole
int nCase = CalcInversionForSpiralOffset( pSrfAct) ;
if ( nCase == -1)
return false ;
// ricavo le regioni progressive
double dOffsPrec = 0. ;
int nCrvFirstOffs = 0 ;
@@ -5858,12 +5934,15 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// se primo Offset
if ( nIter == 0) {
// aggiorno il nuovo valore delle regioni totali di primo Offset
int my_nReg = nReg ;
nReg = pSfrOffsVR->GetChunkCount() ; // aggiorno il nuovo valore delle regioni totali di primo Offset
nReg = pSfrOffsVR->GetChunkCount() ;
// gli Offset progressivi appartengono al Chunk nReg-esimo
pSrfAct.Set( pSfrOffsVR->CloneChunk( my_nReg)) ;
if ( IsNull( pSrfAct)) // se supero i chunk ottenuti
// se supero i chunk ottenuti
if ( IsNull( pSrfAct))
return true ;
// imposto la regione id svuotatura corrente
pSfrOffsVR.Set( pSrfAct->Clone()) ;
}
@@ -5873,24 +5952,28 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
for ( int i = 0 ; i < nChunks ; ++ i) {
// per ogni chunk...
int nLoops = pSfrOffsVR->GetLoopCount( i) ;
for ( int j = 0 ; j < nLoops ; ++ j) {
for ( int j = 0 ; j < nLoops ; ++ j) {
// per ogni loop...
PtrOwner<ICurveComposite> pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid())
return false ;
/*
Il materiale deve sempre trovarsi alla destra ( se bInvert -> alla sinistra) del tool
soltanto sul primo bordo; Nel caso di isole aperte o nelle passate di Offset intermedio
l'orientamente non ha importanza.
*/
if ( nIter != 0 && j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate)
pCrvCompoBorder->Invert() ;
// controllo quali regioni di Offset possono essere sostituite
bool bInsert = true ;
if ( ! CheckIfOffsetIsNecessary( pSrfAct, pCrvCompoBorder, dOffs, dOffsPrec, nIter, PockParams, bInsert))
return false ;
if ( bInsert)
if ( bInsert) {
// imposto come secondo TempParam il Side di classificazione
pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ;
// stabilisco l'orientamento della curva
if ( ( nCase == 1 && nIter != 0 && j > 0) ||
( nCase == 2 && j > 0) ||
( nCase == 3 && j == 0) ||
( nCase == 4 && j > 0)) {
pCrvCompoBorder->Invert() ;
SwapSideBySecondTempParam( pCrvCompoBorder) ;
}
vOffs.emplace_back( Release( pCrvCompoBorder)) ;
}
if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT)
PtrOwner<ICurveComposite> pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ;
@@ -5917,9 +6000,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
dOffs = PockParams.dSideStep ;
}
}
// se devo usare un Offset più piccolo...
else if ( ! bSmallRad)
// se non ho Chunks e devo usare un Offset più piccolo...
else if ( ! bSmallRad) {
if ( PockParams.dRad < EPS_SMALL)
break ;
dOffs = dOffsPrec + ( nIter == 0 ? PockParams.dRad + PockParams.dRadialOffset : PockParams.dRad) ;
}
// altrimenti ho finito la regione da svuotare...
else
break ;
@@ -5936,11 +6022,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
Point3d ptNewStart ;
// Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte...
int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare
int nIndexSwap = 0 ;
if ( PockParams.nType == POCKET_SPIRALIN) {
if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart,
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops))
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) {
vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ;
}
else
return false ;
}
@@ -5954,8 +6041,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// se richiesta inversione
if ( PockParams.bInvert) {
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i)
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
vOffs[i]->Invert() ;
SwapSideBySecondTempParam( vOffs[i]) ;
}
}
// smusso le curve di offset ( ad eccezione di quelle di primo Offset)
@@ -5975,10 +6064,6 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione
// riordino le curve e creo i collegamenti
/*
Se richiesto parametro di smusso, tutti gli Offset ( ad eccezione di quelli generati alla
prima iterazione vengono tagliati, quindi diventano aperti
*/
ICURVEPOVECTOR vLinks( vOffs.size()) ;
if ( ! CreateSpiralPocketingPath( vOffs, vLinks, PockParams, vOffsFirstCurve))
return false ;
@@ -5996,9 +6081,8 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// se collegamento da aggiungere
if ( ! IsNull( vLinks[i])) {
// accodo nel percorso di lavorazione
if ( ! pMCrv->AddCurve( Release( vLinks[i]))) {
if ( ! pMCrv->AddCurve( Release( vLinks[i])))
return false ;
}
}
pMCrv->AddCurve( Release( vOffs[i])) ;
}
@@ -7063,8 +7147,8 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
//----------------------------------------------------------------------------
static bool
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
{
// controllo dei parametri
@@ -7073,53 +7157,79 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
pCrvLink == nullptr || ! pCrvLink->IsValid())
return false ;
// curva precedente
// definisco la lunghezza del segmento iniziale e finale sulle due curve di Offset
double dRefLenSeg = 2. * dSmoothPar ;
// --- Curva precedente ---
// recupero la lunghezza e il dominio del primo Offset
double dLen ;
pCrvOffs0->GetLength( dLen) ;
double dUStart, dUEnd ;
pCrvOffs0->GetDomain( dUStart, dUEnd) ;
// inizializzo la curva
PtrOwner<ICurveComposite> pCrvBef( CreateCurveComposite()) ;
if ( IsNull( pCrvBef))
return false ;
// se primo Offset di bordo o chiuso...
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
const ICurve* pCrvFirst = pCrvOffs0->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
double dU = dUEnd ;
if ( dLen > dRefLenSeg - EPS_SMALL)
pCrvOffs0->GetParamAtLength( dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dUStart, dU)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
// altrimenti...
else {
const ICurve* pCrvLast = pCrvOffs0->GetLastCurve() ;
if ( pCrvLast == nullptr || ! pCrvLast->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvLast->Clone()) ;
double dU = dUStart ;
if ( dLen > dRefLenSeg)
pCrvOffs0->GetParamAtLength( dLen - dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dU, dUEnd)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
// se non valida, errore
if ( ! pCrvBef->IsValid())
return false ;
// curva successiva
// --- Curva successiva ---
// recupero la lunghezza e il dominio del primo Offset
pCrvOffs1->GetLength( dLen) ;
pCrvOffs1->GetDomain( dUStart, dUEnd) ;
// inizializzo la curva
PtrOwner<ICurveComposite> pCrvAft( CreateCurveComposite()) ;
if ( IsNull( pCrvAft))
return false ;
const ICurve* pCrvFirst = pCrvOffs1->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
// calcolo il parametro di taglio
double dU = dUEnd ;
if ( dLen > dRefLenSeg - EPS_SMALL)
pCrvOffs1->GetParamAtLength( dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs1->CopyParamRange( dUStart, dU)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvAft->AddCurve( Release( pMyCrv)) ;
// se non valida, errore
if ( ! pCrvAft->IsValid())
return false ;
// controllo la validità delle curve precedenti e successive ricavate
if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid())
return false ;
// estendo il Link
// estendo il Link ( linea di ingresso, segmento Link, linea d'uscita)
pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ;
pCrvLink->AddCurve( Release( pCrvAft), true, dTol) ;
// smusso
// miglioro la curva
pCrvLink->MergeCurves( 100 * EPS_SMALL, ANG_TOL_STD_DEG) ;
// smusso la curva
ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ;
// toglo gli estremi
// toglo gli estremi, il Link è in tangenza e le linee di ingresso e d'uscita sono più
// estese dell'arco di smusso creato
delete( pCrvLink->RemoveFirstOrLastCurve( false)) ;
delete( pCrvLink->RemoveFirstOrLastCurve( true)) ;
// modifico Offset0 per raccordarlo al nuovo Link
// modifico il primo Offset per raccordarlo al nuovo Link
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
const ICurve* pCrvFirst = pCrvLink->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
@@ -7135,7 +7245,8 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ;
pCrvOffs0->TrimEndAtParam( dUE) ;
}
// modifico Offset1 per raccordarlo al nuovo Link
// modifico il secondo Offset per raccordarlo al nuovo Link
Point3d ptE ; pCrvLink->GetEndPoint( ptE) ;
double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ;
if ( bFirstOffs1 && pCrvOffs1->IsClosed())
@@ -7195,8 +7306,8 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos
//----------------------------------------------------------------------------
static bool
GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
{
// controllo validità delle due curve di Offset
if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() ||
@@ -7248,10 +7359,16 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket
ICRVCOMPOPOVECTOR vCrvChunk ;
for ( int i = 0 ; i < int( vIndOffs0.size()) ; ++ i)
vCrvChunk.emplace_back( vCrvClassBorder[vIndOffs0[i]]->Clone()) ;
// se la curva successiva è chiusa, aggiorno il suo punto iniziale a quello a minima distanza
if ( ! bOpen1) {
Point3d ptS ; pCrvOffs0->GetStartPoint( ptS) ;
double dPar ;
int nFlag ;
if ( DistPointCurve( ptS, *pCrvOffs1).GetParamAtMinDistPoint( 0., dPar, nFlag))
pCrvOffs1->ChangeStartPoint( dPar) ;
}
if ( ! CutCurveToConnect( pCrvOffs0, pCrvOffs1, vCrvChunk, PockParams,
( ( bOpen0 || bFirstIterOffs0) ? 0. : 10 * EPS_SMALL),
( ( bOpen1 || bFirstIterOffs1) ? 0. : 10 * EPS_SMALL),
pCrvLink) ||
bOpen0 ? 0. : 10 * EPS_SMALL, bOpen1 ? 0. : 10 * EPS_SMALL, pCrvLink) ||
! pCrvLink->IsValid()) {
// se curva di Link non valida, cerco una strada più semplice
pCrvLink->Clear() ;
@@ -7778,7 +7895,7 @@ CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion*
if ( IsNull( pCrvLink))
return false ;
// se non calcolabile, allora retroazione, altrimenti lo memorizzo
if ( ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
if ( ! CalcConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
IsNull( pCrvLink) || ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0)
vCrvLink.resize( int( vCrvLink.size()) + 1) ;
else
@@ -8808,7 +8925,7 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa
//----------------------------------------------------------------------------
bool
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
double dOpenMinSafe, int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs,
double dMaxOptSize, double dLiTang, int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
{
@@ -8831,6 +8948,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
myParams.dAngle = dAngle ;
myParams.dSideStep = dStep ;
myParams.dOpenMinSafe = dOpenMinSafe ;
myParams.bCalcUnclearedRegs = bCalcUnclReg ;
myParams.bInvert = bInvert ;
myParams.bAvoidOpt = bAvoidOpt ;
myParams.bCalcFeed = bCalcFeed ;
+45
View File
@@ -2087,6 +2087,51 @@ CalcCurveSingleCurvesOffset( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double d
return pVoronoiObj->CalcSingleCurvesOffset( vCrvs, dOffs) ;
}
//----------------------------------------------------------------------------
bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs, int nType)
{
// creo oggetto Voronoi con le curve passate
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
return pVoronoiObj->CalcOffset( vCrvs, dOffs, nType) ;
}
//----------------------------------------------------------------------------
bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs,
bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps)
{
// controllo validità delle curve
for ( auto& pCrv : vpCrvs) {
if ( pCrv == nullptr)
return false ;
}
// se offset nullo restituisco direttamente le curve
if ( abs( dOffs) < EPS_SMALL) {
for ( auto& pCrv : vpCrvs) {
if ( ! vCrvs.emplace_back( pCrv->Clone()))
return false ;
}
return true ;
}
// creo oggetto Voronoi con le curve passate
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
return pVoronoiObj->CalcFatCurve( vCrvs, dOffs, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
}
//----------------------------------------------------------------------------
void
ResetCurveVoronoi( const ICurve& crvC)
+10 -4
View File
@@ -224,8 +224,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
// lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ;
// eseguo modifica
if ( ! pCrv->ModifyStart( ptEnd))
return false ;
if ( ! pCrv->ModifyStart( ptEnd)) {
CurveLine crvLine ;
if ( ! crvLine.Set( ptEnd, ptCrvEnd) || ! pCrv.Set( crvLine.Clone()))
return false ;
}
// verifico che la lunghezza non sia variata troppo
double dNewLen ; pCrv->GetLength( dNewLen) ;
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
@@ -246,8 +249,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
// lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ;
// eseguo modifica
if ( ! pCrv->ModifyEnd( ptStart))
return false ;
if ( ! pCrv->ModifyEnd( ptStart)) {
CurveLine crvLine ;
if ( ! crvLine.Set( ptCrvStart, ptStart) || ! pCrv.Set( crvLine.Clone()))
return false ;
}
// verifico che la lunghezza non sia variata troppo
double dNewLen ; pCrv->GetLength( dNewLen) ;
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
BIN
View File
Binary file not shown.
+1
View File
@@ -345,6 +345,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
<ClInclude Include="CAvSilhouetteSurfTm.h" />
<ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" />
+4 -1
View File
@@ -550,7 +550,7 @@
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshOffset.cpp">
<Filter>File di origine\Geo</Filter>
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -1232,6 +1232,9 @@
<ClInclude Include="CAvSilhouetteSurfTm.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+52 -2
View File
@@ -234,12 +234,12 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
m_vPart.clear() ;
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
if ( ! vtN.Normalize( EPS_ZERO))
return SVT_DEL ;
// inserisco il triangolo
try { m_vTria.emplace_back( nIdVert, nTFlag) ;}
catch(...) { return SVT_NULL ;}
// aggiorno la sua normale
if ( ! vtN.Normalize( EPS_ZERO))
return false ;
m_vTria.back().vtN = vtN ;
// aggiorno massimo TFlag
m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ;
@@ -4029,6 +4029,56 @@ SurfTriMesh::CloneShell( int nShell) const
return Release( pSurfTM) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartLocalBBox( int nP, BBox3d& b3Loc) const
{
// verifico esistenza della parte
if ( nP < 0 || nP >= GetPartCount())
return false ;
// assegno il box in locale
b3Loc.Reset() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// recupero il vettore delle Shell della parte corrente
const auto& vShell = m_vPart[nP].vShell ;
// scorro i triangoli validi contenuti nella Shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
// ciclo sui tre vertici
for ( int j = 0 ; j < 3 ; ++ j)
b3Loc.Add( m_vVert[m_vTria[i].nIdVert[j]].ptP) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const
{
// verifico esistenza della parte
if ( nP < 0 || nP >= GetPartCount())
return false ;
// assegno il box in locale
b3Ref.Reset() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// recupero il vettore delle Shell della parte corrente
const auto& vShell = m_vPart[nP].vShell ;
// scorro i triangoli validi contenuti nella Shell
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
// ciclo sui tre vertici
for ( int j = 0 ; j < 3 ; ++ j)
b3Ref.Add( GetToGlob( m_vVert[m_vTria[i].nIdVert[j]].ptP, frRef)) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetPartCount( void) const
+2
View File
@@ -337,6 +337,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetShellArea( int nShell, double& dArea) const override ;
bool RemoveShell( int nShell) override ;
SurfTriMesh* CloneShell( int nShell) const override ;
bool GetPartLocalBBox( int nP, BBox3d& b3Loc) const override ;
bool GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const override ;
int GetPartCount( void) const override ;
bool RemovePart( int nPart) override ;
bool GetPartArea( int nPart, double& dArea) const override ;
+53 -12
View File
@@ -1,19 +1,21 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2022
// EgalTech 2025
//----------------------------------------------------------------------------
// File : SurfTriMeshOffset.cpp Data : 10.06.25 Versione : 2.7e4
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
//
//
//
// Modifiche : 10.06.25 RE Creazione modulo.
// 10.06.25 RE Offset di superfici chiuse.
// 04.07.25 RE Thickening Offset di superfici generiche.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "VolZmap.h"
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
using namespace std ;
@@ -44,32 +46,71 @@ SumStm( const CISURFTMPVECTOR& vStm)
}
//----------------------------------------------------------------------------
/* Funzione che crea l'Offset di una superficie TriMesh chiusa */
// Funzione che crea l'Offset di una superficie TriMesh
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dLinTol)
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
{
return CreateSurfTriMeshesOffset( { pStm}, dOffs, dLinTol) ;
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
}
//----------------------------------------------------------------------------
/* Funzione che crea l'Offset di un insieme di superfici */
// Funzione che crea il Fat Offset di una superficie TriMesh
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLinTol)
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
{
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
}
//----------------------------------------------------------------------------
// Funzione che crea l'Offset di un insieme di superfici
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
{
// se vettore delle superfici vuoto, non faccio nulla
if ( vStm.empty())
return nullptr ;
// controllo sul valore di tolleranza lineare
double dMyLinTol = max( dLinTol, 10 * EPS_SMALL) ;
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
if ( abs( dOffs) < 10 * EPS_SMALL)
return SumStm( vStm) ;
// --- NB. Per la creazione dello Zmap è necessario che le superfici siano chiuse
// creo lo Zmap associato alle superfici TriMesh
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyLinTol))
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
return nullptr ;
// restituisco la superficie TriMesh
return ( pVolZmap->GetSurfTriMesh()) ;
}
}
//----------------------------------------------------------------------------
//* Funzione che crea il Fat Offset di un insieme di superfici
//----------------------------------------------------------------------------
ISurfTriMesh*
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
{
// se vettore delle superfici vuoto, non faccio nulla
if ( vStm.empty())
return nullptr ;
// controllo sul valore di tolleranza lineare
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
if ( abs( dOffs) < 10 * EPS_SMALL)
return SumStm( vStm) ;
// creo lo Zmap associato alle superfici TriMesh
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
return nullptr ;
// restituisco la superficie TriMesh
return ( pVolZmap->GetSurfTriMesh()) ;
}
+10 -4
View File
@@ -85,8 +85,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 100 * EPS_SMALL) override ;
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0.) override ;
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -461,8 +462,13 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
// Funzioni per Offset di superfici
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) ;
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid) ;
bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap = false) ;
+3 -2
View File
@@ -802,7 +802,8 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
// quindi espandiamo il bounding box per ovviare al problema.
SurfBBox.Expand( dExtraBox) ;
if ( dExtraBox > EPS_ZERO)
SurfBBox.Expand( dExtraBox) ;
// Determino i punti estremi del bounding box
Point3d ptMapOrig, ptMapEnd ;
@@ -920,7 +921,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
// Tipologia
m_nShape = ( IsBox() ? BOX : GENERIC) ;
m_nShape = ( dExtraBox > EPS_ZERO && IsBox() ? BOX : GENERIC) ;
// Aggiornamento dello stato
m_nStatus = OK ;
+408 -140
View File
@@ -23,36 +23,36 @@
using namespace std ;
//----------------------------------------------------------------------------
/* Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh */
// Funzione per sottrarre intervalli lungo un Dexel per l'offset di una superficie TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap)
{
// per ora la funzione è la stessa della differenza in generale
// TODO -- Aggiustare eventuali tolleranze
return SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
}
//----------------------------------------------------------------------------
/* Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh */
// Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ,
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
int nToolNum, bool bSkipSwap)
{
// per ora la funzione è la stessa della somma generale
// TODO -- Aggiustare eventuali tolleranze
return AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
}
//----------------------------------------------------------------------------
/* Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
aggiungere o sottrarre intervalli lungo i Dexel coinvolti */
// Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti
//----------------------------------------------------------------------------
bool
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nTool)
{
// determino il Box della sfera posizionata su tale vertice
BBox3d BBoxSphere( ptV - dOffs * Vector3d( 1., 1., 1.),
@@ -78,9 +78,9 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ;
vtNmax.Normalize() ;
if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, 0) ;
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ;
else
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, 0) ;
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ;
}
}
}
@@ -89,10 +89,12 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
}
//----------------------------------------------------------------------------
/* Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
aggiungere o sottrarre intervalli lungo i Dexel coinvolti */
// Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti.
//----------------------------------------------------------------------------
bool
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid)
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid,
int nTool)
{
// determino la lunghezza dello spigolo corrente
double dH = Dist( ptP1, ptP2) ;
@@ -131,9 +133,9 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
ptInt1, vtN1, ptInt2, vtN2)) {
if ( dOffs > 0.)
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, 0) ;
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
else
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, 0) ;
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
}
}
}
@@ -142,10 +144,351 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou
}
//----------------------------------------------------------------------------
/* Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da una
superficie TriMesh */
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
// L'idea è quella di creare uno ZMap a partire dal Box complessivo delle superfici TriMesh :
// - le superfici chiuse possono già inserire i rispettivi spilloni
// - le superfici aperte non danno contributo
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
VolZmap::InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
{
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
// --- se una sola superficie
if ( int( vSurf.size()) == 1) {
// controllo la validità della superficie
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
return true ;
// --- se superficie chiusa posso direttamente creare lo Zmap iniziale
if ( vSurf[0]->IsClosed()) {
// definisco lo Zamp a partire dall'espansione del Box della superficie
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
return false ;
}
// --- se superficie aperta, lo creo inizialmente vuoto a partire dal suo Box
BBox3d BBoxSurf ;
vSurf[0]->GetLocalBBox( BBoxSurf) ;
BBoxSurf.Expand( dBoxExpansion) ;
if ( ! CreateEmpty( BBoxSurf.GetMin(), BBoxSurf.GetDimX(), BBoxSurf.GetDimY(), BBoxSurf.GetDimZ(), dTol, true))
return false ;
}
// --- se più superfici
else {
// calcolo il Box complessivo
BBox3d BBoxGlob ;
for ( const ISurfTriMesh* Surf : vSurf) {
// controllo la validità della superficie
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// calcolo il Box della superficie
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
// aggiungo il Box a quello complessivo
BBoxGlob.Add( BBoxSurf) ;
}
// definisco uno Zmap vuoto a partire dal Box
BBoxGlob.Expand( dBoxExpansion) ;
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
return false ;
// aggiungo tutte le superfici chiuse
for ( const ISurfTriMesh* Surf : vSurf) {
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0 || ! Surf->IsClosed())
continue ;
if ( ! AddSurfTm( Surf))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
// L'idea è quella di creare uno ZMap vuoto a partire dal Box complessivo delle superfici TriMesh
//----------------------------------------------------------------------------
bool
VolZmap::InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
{
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
// calcolo il Box complessivo
BBox3d BBoxGlob ;
for ( const ISurfTriMesh* Surf : vSurf) {
// controllo la validità della superficie
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// calcolo il Box della superficie
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
// aggiungo il Box a quello complessivo
BBoxGlob.Add( BBoxSurf) ;
}
// definisco uno Zmap vuoto a partire dal Box
BBoxGlob.Expand( dBoxExpansion) ;
return ( CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) ;
}
//----------------------------------------------------------------------------
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie aperta
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// da studiare...
return false ;
}
//----------------------------------------------------------------------------
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie chiusa
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// controlli sulla superficie
if ( Surf == nullptr || ! Surf->IsClosed())
return false ;
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
return true ;
// Assunzioni :
// - Idea Generale di Offset
// - Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
// centro il vertice corrente)
// - Su ogni lato viene definito un cilindro ( con raggio di base pari al valore di Offset
// e asse definito dall'edge stesso)
// - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
// definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
//
// - Segno dell'Offset :
// - Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
// - Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
//
// - Semplificazione entità :
// La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
// "spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
// calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
// troppo i conti introducendo variabili angolari che non sommando tutte le parti.
//
// definisco vettore di frame Locali alle 3 griglie
FRAME3DVECTOR vFrGrid( 4) ;
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
// ----------------------- Cilindri e Sfere -----------------------
// scorro gli Edge della superficie
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
// recupero lo spigolo
int nV1, nV2, nF1, nF2 ; double dAng ;
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
// controllo se il cilindro serve
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
if ( dAng * dOffs < 0)
continue ;
// recupero le coordinate dei vertici
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
// esprimo gli estremi nel riferimento della griglia
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
// aggiungo/sottraggo gli intervalli definiti dal cilindro
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
return false ;
// aggiungo/sottraggo gli intervalli definiti dalla sfera
if ( ! vbVert[nV1]) {
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
return false ;
}
if ( ! vbVert[nV2]) {
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
return false ;
}
}
vbVert[nV1] = true ;
vbVert[nV2] = true ;
}
// ----------------------- Facce -----------------------
// scorro tutte le facce definendo una superficie di estrusione
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
// recupero lo faccia
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
// recupero la normale della faccia
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
// definisco la superficie di estrusione
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vPL[i].Translate( - abs( dOffs) * vtN) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
vpCrvs.emplace_back( Release( pCrvCompo)) ;
}
// recupero la TriMesh di estrusione
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
// aggiorno gli spilloni
if ( dOffs > 0.)
AddSurfTm( pStmExtr) ;
else
SubtractSurfTm( pStmExtr) ;
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// [Fillet Thickening] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
// mediante una superficie generica (aperta o chiusa)
//----------------------------------------------------------------------------
bool
VolZmap::UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
{
// controlli sulla superficie
if ( Surf == nullptr)
return false ;
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
return true ;
// non inizializzo lo Zmap, semplicemente lavoro con facce, spigoli e vertici
// definisco vettore di frame Locali alle 3 griglie
FRAME3DVECTOR vFrGrid( 4) ;
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
// ----------------------- Cilindri e Sfere -----------------------
// scorro gli Edge della superficie
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
// recupero lo spigolo
int nV1, nV2, nF1, nF2 ; double dAng ;
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
// recupero le coordinate dei vertici
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
// esprimo gli estremi nel riferimento della griglia
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
// aggiungo/sottraggo gli intervalli definiti dal cilindro
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid))
return false ;
// aggiungo/sottraggo gli intervalli definiti dalla sfera
if ( ! vbVert[nV1]) {
if ( ! CreateOffsSphereOnVertex( ptP1, abs( dOffs), nGrid))
return false ;
}
if ( ! vbVert[nV2]) {
if ( ! CreateOffsSphereOnVertex( ptP2, abs( dOffs), nGrid))
return false ;
}
}
vbVert[nV1] = true ;
vbVert[nV2] = true ;
}
// ----------------------- Facce -----------------------
// scorro tutte le facce definendo una superficie di estrusione
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
// recupero lo faccia
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
// recupero la normale della faccia
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
// definisco la superficie di estrusione
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vPL[i].Translate( - abs( dOffs) * vtN) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
vpCrvs.emplace_back( Release( pCrvCompo)) ;
}
// recupero la TriMesh di estrusione
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
return false ;
}
// aggiorno gli spilloni
AddSurfTm( pStmExtr) ;
// dealloco le curve
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
delete ( vpCrvs[i]) ;
vpCrvs[i] = nullptr ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da un
// vettore di superfici TriMesh (aperte o chiuse).
// Definizione :
// - Lo Zmap di Offset ( positivo o negativo) di una superficie chiusa è automaticamente l'Offset stesso
// - Lo Zmap di Offset ( positivo o negativo) di una superficie aperta è ????? ( da capire...)
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
{
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
@@ -159,142 +502,67 @@ VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, do
if ( vSurf.empty())
return true ;
// definisco lo Zmap di partenza a partire dalle superfici
// se una sola superficie
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
if ( int( vSurf.size()) == 1) {
// controllo la validità della superficie
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
return true ;
// definisco lo Zamp a partire dall'espansione del Box della superficie
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
return false ;
}
// se più superfici
else {
// calcolo il Box complessivo delle superfici TriMesh
BBox3d BBoxGlob ;
for ( int i = 0 ; i < int( vSurf.size()) ; ++ i) {
// controllo la validità della superficie
if ( ! vSurf[i]->IsValid() || vSurf[i]->GetTriangleCount() == 0)
continue ;
// calcolo il Box della superficie
BBox3d BBoxSurf ; vSurf[i]->GetLocalBBox( BBoxSurf) ;
// aggiungo il Box a quello complessivo
BBoxGlob.Add( BBoxSurf) ;
}
// definisco uno Zmap vuoto a partire dal Box
BBoxGlob.Expand( dBoxExpansion) ;
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
return false ;
for ( const ISurfTriMesh* Surf : vSurf) {
if ( ! AddSurfTm( Surf))
return false ;
}
}
/* Assunzioni :
- Idea Generale di Offset
- Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
centro il vertice corrente)
- Su ogni lato viene definito un cilindro ( con raggio di pase pari al valore di Offset
e asse definito dall'edge stesso)
- Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
- Segno dell'Offset :
- Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
- Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
- Semplificazione entità :
La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
"spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
troppo i conti introducendo variabili angolari che non sommando tutte le parti.
*/
// definisco vettore di frame Locali alle 3 griglie
FRAME3DVECTOR vFrGrid( 4) ;
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
// inizializzo lo Zmap di Offset a partire dalle superfici
if ( ! InitVolZMapOffs( vSurf, dOffs, dTol))
return false ;
// scorro le superfici
for ( const ISurfTriMesh* Surf : vSurf) {
// se superficie non valida, passo alla successiva
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
// ----------------------- Cilindri e Sfere -----------------------
// scorro gli Edge della superficie
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
// recupero lo spigolo
int nV1, nV2, nF1, nF2 ; double dAng ;
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
// controllo se il cilindro serve
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
if ( dAng * dOffs < 0)
continue ;
// recupero le coordinate dei vertici
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
// esprimo gli estremi nel riferimento della griglia
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
// aggiungo/sottraggo gli intervalli definiti dal cilindro
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
// aggiorno lo ZMap
if ( Surf->IsClosed()) {
if ( nType == STMOFF_FILLET) {
if ( ! UpdateVolZMapByClosedSurfFilletOffset( Surf, dOffs, dTol))
return false ;
// aggiungo/sottraggo gli intervalli definiti dalla sfera
if ( ! vbVert[nV1]) {
vbVert[nV1] = ( nGrid == 2) ;
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
return false ;
}
if ( ! vbVert[nV2]) {
vbVert[nV2] = ( nGrid == 2) ;
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
return false ;
}
}
}
// ----------------------- Facce -----------------------
// scorro tutte le facce definendo una superficie di estrusione
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
// recupero lo faccia
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
// recupero la normale della faccia
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
// definisco la superficie di estrusione
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vPL[i].Translate( - abs( dOffs) * vtN) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i]))
return false ;
vpCrvs.emplace_back( Release( pCrvCompo)) ;
}
// recupero la TriMesh di estrusione
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0)
return false ;
// aggiorno gli spilloni
if ( dOffs > 0.)
AddSurfTm( pStmExtr) ;
else
SubtractSurfTm( pStmExtr) ;
else {
// --- LE SUPERFICI APERTE SONO PER ORA DISABILITATE ---
}
}
m_nShape = OFFSET ; // OFFSET (?) ... per ora va bene così
m_nShape = OFFSET ;
return true ;
}
//----------------------------------------------------------------------------
// Funzione per la creazine di uno Zmap di Fat Offset a partire da un
// vettore di superfici TriMesh (aperte o chiuse).
//----------------------------------------------------------------------------
bool
VolZmap::CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
{
// controllo delle superfici
for ( const ISurfTriMesh* Surf : vSurf) {
if ( Surf == nullptr)
return false ;
}
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
if ( abs( dOffs) < 10 * EPS_SMALL)
return true ;
// se non ho superfici, non faccio nulla
if ( vSurf.empty())
return true ;
// inizializzo lo Zmap di Offset a partire dalle superfici
if ( ! InitVolZMapThickeningOffs( vSurf, dOffs, dTol))
return false ;
// scorro le superfici
for ( const ISurfTriMesh* Surf : vSurf) {
// se superficie non valida, passo alla successiva
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
continue ;
// aggiorno lo Zmap
if ( nType == STMOFF_FILLET) {
if ( ! UpdateVolZMapBySurfThickeningFilletOffset( Surf, dOffs, dTol))
return false ;
}
}
m_nShape = OFFSET ;
return true ;
}
+153 -153
View File
@@ -25,7 +25,7 @@
using namespace std ;
//----------------------------------------------------------------------------
Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
{
// tento di aggiungere la curva
@@ -35,7 +35,7 @@ Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
}
//----------------------------------------------------------------------------
Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
{
// tento di aggiungere la superficie
@@ -45,16 +45,16 @@ Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
}
//----------------------------------------------------------------------------
Voronoi::~Voronoi( void)
Voronoi::~Voronoi( void)
{
Clear() ;
}
//----------------------------------------------------------------------------
bool
Voronoi::Clear( void)
Voronoi::Clear( void)
{
// pulizia oggetto vroni
// pulizia oggetto vroni
if ( m_vroni != nullptr)
delete m_vroni ;
m_vroni = nullptr ;
@@ -72,7 +72,7 @@ Voronoi::Clear( void)
//----------------------------------------------------------------------------
bool
Voronoi::AddCurve( const ICurve* pCrv)
Voronoi::AddCurve( const ICurve* pCrv)
{
if ( ! m_bAllowAdd)
return false ;
@@ -99,21 +99,21 @@ Voronoi::AddCurve( const ICurve* pCrv)
if ( ! vtExtr.IsSmall())
plPlane.Set( ptS, vtExtr) ;
else
plPlane.Set( ptS, Z_AX) ;
plPlane.Set( ptS, Z_AX) ;
}
else {
if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL))
return false ;
}
return false ;
}
if ( m_vpCrvs.empty()) {
// se prima curva considerata assegno il frame al Voronoi
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
}
else {
// altrimenti verifico sia complanare ad eventuali curve già presenti
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ;
return false ;
}
// creo una copia della curva e la porto in locale
@@ -128,8 +128,8 @@ Voronoi::AddCurve( const ICurve* pCrv)
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
return false ;
m_vroni->apiInitializeProgram() ;
}
m_vroni->apiInitializeProgram() ;
}
// aggiungo la curva in locale all'oggetto vroni
if ( ! AddCurveToVroni( pCrvLoc))
@@ -144,61 +144,61 @@ Voronoi::AddCurve( const ICurve* pCrv)
BBox3d bBox ;
pCrvLoc->GetLocalBBox( bBox) ;
m_bBox.Add( bBox) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
{
if ( ! m_bAllowAdd)
return false ;
if ( pSfr == nullptr)
return false ;
// recupero il piano
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Vector3d vtN = pSfr->GetNormVersor() ;
Vector3d vtN = pSfr->GetNormVersor() ;
if ( m_vpCrvs.empty()) {
// assegno il frame al Voronoi
m_Frame.Set( ptCen, vtN) ;
m_Frame.Set( ptCen, vtN) ;
}
else {
// verifico sia complanare ad eventuali curve già presenti
Plane3d plPlane ;
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ;
return false ;
}
try {
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
return false ;
m_vroni->apiInitializeProgram() ;
m_vroni->apiInitializeProgram() ;
}
// aggiungo le curve di loop
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
if ( IsNull( pCrvLoc))
return false ;
pCrvLoc->ToLoc( m_Frame) ;
pCrvLoc->ToLoc( m_Frame) ;
if ( ! AddCurveToVroni( pCrvLoc))
return false ;
}
}
}
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage())
return false ;
}
// aggiorno il box complessivo
BBox3d bBox ;
Frame3d frSrf = m_Frame ;
@@ -211,16 +211,16 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
//----------------------------------------------------------------------------
bool
Voronoi::AddCurveToVroni( const ICurve* pCrv)
Voronoi::AddCurveToVroni( const ICurve* pCrv)
{
int nLoopId = m_vpCrvs.size() ;
// aggiungo il punto iniziale
Point3d ptStart ;
Point3d ptStart ;
if ( ! pCrv->GetStartPoint( ptStart))
return false ;
int nCrv = m_vroni->HandlePnt( ptStart.x, ptStart.y, {nLoopId, 0}) ;
// aggiungo la parte rimanente della curva
switch ( pCrv->GetType()) {
case CRV_LINE :
@@ -229,7 +229,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
case CRV_ARC :
m_vpCrvs.emplace_back( pCrv->Clone()) ;
return AddArcToVroni( GetCurveArc( pCrv), nCrv, nLoopId) ;
case CRV_COMPO :
case CRV_COMPO :
return AddCompoToVroni( GetCurveComposite( pCrv), nCrv, nLoopId) ;
case CRV_BEZIER :
return AddBezierToVroni( GetCurveBezier( pCrv), nCrv, nLoopId) ;
@@ -242,7 +242,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
//----------------------------------------------------------------------------
bool
Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
{
if ( pLine == nullptr)
return false ;
@@ -250,7 +250,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
// verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine
if ( ! ptEnd.IsValid()) {
if ( ! pLine->GetEndPoint( ptEnd))
return false ;
return false ;
}
m_vroni->AddSeg( &nVroniCrv, ptEnd.x, ptEnd.y, {nLoopId, nCrvId}) ;
@@ -259,7 +259,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
//----------------------------------------------------------------------------
bool
Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
{
if ( pArc == nullptr)
return false ;
@@ -285,7 +285,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
// verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc
if ( ! ptEnd.IsValid()) {
if ( ! pArc->GetEndPoint( ptEnd))
return false ;
return false ;
}
m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ;
}
@@ -295,7 +295,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
//----------------------------------------------------------------------------
bool
Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId)
Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId)
{
if ( pCompo == nullptr)
return false ;
@@ -315,18 +315,18 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
bool bClosed = pCopy->IsClosed() ;
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
Point3d ptForcedEnd = P_INVALID ;
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
pCompo->GetStartPoint( ptForcedEnd) ;
// aggiungo
const ICurve* pCrv = pCopy->GetCurve( i) ;
int nType = pCrv->GetType() ;
if ( nType == CRV_LINE)
AddLineToVroni( GetCurveLine( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
else if ( nType == CRV_ARC)
AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
}
// aggiungo al vettore di curve
@@ -341,7 +341,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
{
if ( pBezier == nullptr)
return false ;
// riconduco al caso di curva composita
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCompo))
@@ -352,28 +352,28 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
Vector3d vtExtr ; pBezier->GetExtrusion( vtExtr) ;
pCompo->SetExtrusion( vtExtr) ;
return AddCompoToVroni( pCompo, nVroniCrv, nLoopId) ;
}
//----------------------------------------------------------------------------
ICurve*
ICurve*
Voronoi::GetCurve( int nId) const
{
// verifico validità indice
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
return nullptr ;
return nullptr ;
// ne faccio una copia
ICurve* pCrv = m_vpCrvs[nId]->Clone() ;
if ( pCrv == nullptr)
return nullptr ;
return nullptr ;
// la porto nel riferimento globale
pCrv->ToGlob( m_Frame) ;
return pCrv ;
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::GetVroniPlane( Plane3d& plPlane) const
{
if ( ! IsValid())
@@ -383,13 +383,13 @@ Voronoi::GetVroniPlane( Plane3d& plPlane) const
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcVoronoi( int nBound)
{
{
// se già stato calcolato con lo stesso bound non devo fare nulla
if ( m_bVDComputed && nBound == m_nBound)
return true ;
// se già stato calcolato reset dei dati
if ( m_bVDComputed)
m_vroni->ResetVoronoiDiagram() ;
@@ -398,9 +398,9 @@ Voronoi::CalcVoronoi( int nBound)
m_nBound = max( nBound, VORONOI_STD_BOUND) ;
// calcolo
m_bVDComputed = true ;
m_bVDComputed = true ;
string sTmp = "" ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
return true ;
}
@@ -416,7 +416,7 @@ Voronoi::GetBisectorCurve( int i)
int nType = m_vroni->GetBisectorType( i) ;
// linea
if ( nType == BisectorType::LINE) {
if ( nType == BisectorType::LINE) {
// recupero i dati del bisettore da vroni
Point3d ptS, ptE ;
double dParS, dParE ;
@@ -434,7 +434,7 @@ Voronoi::GetBisectorCurve( int i)
pLine->SetTempParam( dParS, 0) ;
pLine->SetTempParam( dParE, 1) ;
pLine->ToGlob( m_Frame) ;
return pLine ;
return pLine ;
}
// degenerate hyperellipse ( arco)
@@ -454,20 +454,20 @@ Voronoi::GetBisectorCurve( int i)
pArc->SetTempParam( dParS, 0) ;
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
pArc->ToGlob( m_Frame) ;
return pArc ;
return pArc ;
}
// bisettore generico
else if ( nType != BisectorType::NONE) {
// approssimo linearmente il bisettore
int nPoints = m_vroni->GetApproxedBisectorPointsNbr( i) ;
if ( nPoints < 2)
return nullptr ;
CurveComposite* pCompo = CreateBasicCurveComposite() ;
if ( pCompo == nullptr)
return nullptr ;
// verifico se devo leggere i punti del bisettore al contrario per averlo orientato dal parametro minore al maggiore
bool bInvert = false ;
double dPar1, dPar2 ;
@@ -481,13 +481,13 @@ Voronoi::GetBisectorCurve( int i)
m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ;
pCompo->AddPoint( pt) ;
int nCrvCount = 0 ;
double dParPrev = dParS ;
int j = bInvert ? nPoints - 2 : 1 ;
while ( ( bInvert && j >= 0) || ( ! bInvert && j < nPoints)) {
double dPar ;
m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ;
if ( pCompo->AddLine( pt)) {
if ( pCompo->AddLine( pt)) {
// setto i parametri sulla sottocurva
pCompo->SetCurveTempParam( nCrvCount, dParPrev, 0) ;
pCompo->SetCurveTempParam( nCrvCount, dPar, 1) ;
@@ -501,7 +501,7 @@ Voronoi::GetBisectorCurve( int i)
else
j ++ ;
}
// setto parametri sulla curva
pCompo->SetTempParam( dParS, 0) ;
pCompo->SetTempParam( dParPrev, 1) ;
@@ -521,12 +521,12 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
if ( ! IsValid())
return false ;
try {
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed || nBound != m_nBound)
CalcVoronoi( nBound) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// recupero la curva del bisettore
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
@@ -546,7 +546,7 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
{
vCrvs.clear() ;
@@ -561,21 +561,21 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
bRight = false ;
else if ( nSide == WMAT_RIGHT)
bLeft = false ;
try {
try {
if ( ! m_bVDComputed)
CalcVoronoi() ;
// calcolo medial axis
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se il lato appartiene al medial axis
if ( m_vroni->IsWMATEdge( i)) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
}
// libero la memoria di vroni utilizzata per calcolare bisettore
@@ -590,7 +590,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
{
vOffs.clear() ;
@@ -603,29 +603,29 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
for ( auto pCrv : m_vpCrvs)
vOffs.emplace_back( pCrv->Clone()) ;
}
// calcolo offset
ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ;
return false ;
// sistemo le curve di offset calcolate con vroni
for ( auto pCrv : OffsList) {
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
// eventuale inversione
if ( dOffs > EPS_SMALL)
vResult[i]->Invert() ;
// sistemo il punto di inizio
if ( vResult[i]->IsClosed())
if ( vResult[i]->IsClosed())
AdjustOffsetStart( vResult[i]) ;
// identifico i raccordi
// identifico i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0)
IdentifyFillets( vResult[i], dOffs) ;
@@ -643,17 +643,17 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
if ( ! AdjustCurveFillets( vOffs, dOffs, nType)) {
vOffs.clear() ;
return false ;
}
}
// porto nel frame globale
for ( int i = 0 ; i < int( vOffs.size()) ; i++)
vOffs[i]->ToGlob( m_Frame) ;
vOffs[i]->ToGlob( m_Frame) ;
return true ;
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
{
// calcola, se possibile, le curve di offset del valore richiesto come curve singole, andando a recuperare i tratti del
@@ -667,22 +667,22 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
if ( ! IsValid())
return false ;
try {
try {
if ( ! m_bVDComputed)
CalcVoronoi() ;
// individuo il lato richiesto
// individuo il lato richiesto
bool bLeft = ( dOffs < 0) ;
bool bRight = ! bLeft ;
bool bRight = ! bLeft ;
for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) {
if ( ! m_vpCrvs[i]->IsClosed()) {
// se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra
bLeft = true ;
bRight = true ;
break ;
break ;
}
}
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
// seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
@@ -695,7 +695,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
m_vroni->GetBisectorParams( i, dParS, dParE) ;
if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
if ( bLeft && bRight) {
// recupero i siti di riferimento
@@ -707,7 +707,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
pCrv->SetTempProp( nOrigCrv1, 1) ;
int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef)
continue ;
continue ;
}
if ( nOrigCrv2 != -1) {
// verifico il lato rispetto al secondo sito
@@ -716,18 +716,18 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
int nSide = GetOffsetCurveSide( pCrv) ;
if ( nSide != nSideRef)
continue ;
}
}
}
vCrvs.emplace_back( Release( pCrv)) ;
}
}
}
vCrvs.emplace_back( Release( pCrv)) ;
}
}
}
}
// concateno le curve ottenute
if ( vCrvs.size() == 1)
vOffs.emplace_back( Release( vCrvs[0])) ;
else if ( ! vCrvs.empty()) {
else if ( ! vCrvs.empty()) {
ChainCurves chainC ;
chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ;
for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) {
@@ -754,14 +754,14 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
vCrvs[nInd]->Invert() ;
// aggiungo alla composita
if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd])))
return false ;
return false ;
}
if ( pCrvCompo->IsValid()) {
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
vOffs.emplace_back( Release( pCrvCompo)) ;
}
}
}
}
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
@@ -775,11 +775,11 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
{
// calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto
vResult.clear() ;
if ( abs( dOffs) < EPS_SMALL)
@@ -792,12 +792,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
// verifico se necessario ricalcolo Voronoi
UpdateVoronoi( dOffs) ;
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
// la chiusura solo sulla prima curva. Eventualmente da estendere)
bool bLeft = true, bRight = true ;
if ( m_vpCrvs[0]->IsClosed()) {
bLeft = dOffs < 0 ;
bRight = ! bLeft ;
bRight = ! bLeft ;
}
// calcolo medial axis
@@ -826,12 +826,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
double dPar ;
Point3d ptTemp ;
Vector3d vtDir ;
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
return false ;
vtDir.Normalize() ;
vResult.emplace_back( pt, vtDir) ;
}
}
}
// libero la memoria di vroni utilizzata per calcolare bisettori
@@ -846,23 +846,23 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids,
bool bMergeOnlySameProps)
{
vCrvs.clear() ;
if ( ! IsValid())
return false ;
// se offset nullo errore
if ( abs( dOffs) < EPS_SMALL)
return false ;
ICRVCOMPOPLIST OffsList ;
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
return false ;
// sistemo le curve di offset calcolate con vroni
bool bClosed = m_vpCrvs[0]->IsClosed() ;
for ( auto pCrvOffs : OffsList) {
@@ -910,7 +910,7 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
{
OffsList.clear() ;
@@ -931,21 +931,21 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
// recupero le curve di offset da vroni
int nOffsCnt = m_vroni->GetOffsetCount() ;
int nOffsCnt = m_vroni->GetOffsetCount() ;
for ( int i = 0 ; i < nOffsCnt ; i++) {
Point3d ptSChain = P_INVALID ;
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
for ( int j = 0 ; j < nCrvCnt ; j ++) {
// recupero la sottocurva da vroni
// recupero la sottocurva da vroni
Point3d ptS, ptE, ptC ;
int nType ;
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
if ( j == 0)
pCrvOffs->AddPoint( ptS) ;
pCrvOffs->AddPoint( ptS) ;
// se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze)
// ma controllo se appartiene ad una catena di tratti infinitesimi
@@ -954,7 +954,7 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
if ( ! AreSamePointApprox( ptSChain, ptE)) {
if ( ! pCrvOffs->AddLine( ptE))
return false ;
ptSChain = P_INVALID ;
ptSChain = P_INVALID ;
}
}
else {
@@ -970,16 +970,16 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
if ( ! pCrvOffs->AddLine( ptE))
return false ;
}
else {
else {
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
if ( ! pArc->SetC2P( ptC, ptS, ptE)) {
// se raggio minore di EPS_SMALL approssimo con linea
if ( AreSamePointApprox( ptC, ptS)) {
if ( ! pCrvOffs->AddLine( ptE))
return false ;
return false ;
}
else
return false ;
return false ;
}
else {
// verifico orientamento
@@ -988,25 +988,25 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
pArc->ToExplementary() ;
// aggiungo alla composita
if ( ! pCrvOffs->AddCurve( Release( pArc)))
return false ;
}
return false ;
}
}
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
// aperta e chiusa)
if ( nOrigCrv == -1) {
int nOrigCrvCnt = 1 ;
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
}
}
}
}
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
@@ -1014,8 +1014,8 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
// aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
OffsList.push_back( Release( pCrvOffs)) ;
}
OffsList.push_back( Release( pCrvOffs)) ;
}
// libero la memoria di vroni dedicata agli offset
m_vroni->apiFreeOffsetData() ;
@@ -1029,11 +1029,11 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
}
//----------------------------------------------------------------------------
bool
bool
Voronoi::UpdateVoronoi( double dOffs)
{
// calcolo il bound necessario per l'offset desiderato
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
if ( ! m_bVDComputed || dNeededBound > m_nBound) {
// aggiorno il valore del bound
int nBound = ( int)( ceil( dNeededBound) + 0.5) ;
@@ -1045,9 +1045,9 @@ Voronoi::UpdateVoronoi( double dOffs)
}
//----------------------------------------------------------------------------
ICRVCOMPOPOVECTOR
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
{
ICRVCOMPOPOVECTOR
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
{
ICRVCOMPOPOVECTOR vResult ;
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
@@ -1065,13 +1065,13 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
// controllo la curva complessiva
int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ;
if ( nSide == nSideRef)
vResult.emplace_back( pCompo->Clone()) ;
vResult.emplace_back( pCompo->Clone()) ;
}
else {
else {
// scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato
PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ;
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
bool bKeep = true ;
bool bKeep = true ;
double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ;
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
bKeep = false ;
@@ -1087,8 +1087,8 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
if ( pCompoCurr->IsValid()) {
vResult.emplace_back( Release( pCompoCurr)) ;
pCompoCurr.Set( CreateBasicCurveComposite()) ;
}
}
}
}
}
// salvo eventuale ultima curva
if ( pCompoCurr->IsValid())
@@ -1102,17 +1102,17 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
vResult.pop_back() ;
}
}
return vResult ;
}
//---------------------------------------------------------------------------
int
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
{
int
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
{
if ( pCrv == nullptr)
return -1 ;
Point3d ptM ; pCrv->GetMidPoint( ptM) ;
// recupero curva e sottocurva di riferimento dalle temp prop
@@ -1121,8 +1121,8 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
if ( pCompoOrig != nullptr)
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
if ( pCompoOrig != nullptr)
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
}
DistPointCurve distPC( ptM, *pCrvRef) ;
@@ -1132,9 +1132,9 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
}
//---------------------------------------------------------------------------
bool
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
{
bool
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
{
for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) {
// cerco il tratto associato alla prima sottocurva originale
int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ;
@@ -1154,15 +1154,15 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
//---------------------------------------------------------------------------
bool
Voronoi::Translate( const Vector3d & vtMove)
{
Voronoi::Translate( const Vector3d & vtMove)
{
if ( ! IsValid())
return false ;
return m_Frame.Translate( vtMove) ;
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{
if ( ! IsValid())
@@ -1171,7 +1171,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
if ( ! IsValid())
@@ -1180,7 +1180,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::ToGlob( const Frame3d& frRef)
{
if ( ! IsValid())
@@ -1189,7 +1189,7 @@ Voronoi::ToGlob( const Frame3d& frRef)
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::ToLoc( const Frame3d& frRef)
{
if ( ! IsValid())
@@ -1198,7 +1198,7 @@ Voronoi::ToLoc( const Frame3d& frRef)
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
if ( ! IsValid())
@@ -1207,7 +1207,7 @@ Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
}
//---------------------------------------------------------------------------
bool
bool
Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
{
if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1)
@@ -1221,14 +1221,14 @@ Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed)
CalcVoronoi() ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno
if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) {
// calcolo i parametri del bisettore
double dParS, dParE ;
m_vroni->GetBisectorParams( i, dParS, dParE) ;
dOffs = max( { dParS, dParE, dOffs}) ;
dOffs = max( { dParS, dParE, dOffs}) ;
}
}