EgtGeomKernel :

- correzioni al VM 5 assi con bilineari.
This commit is contained in:
Daniele Bariletti
2025-07-23 14:56:20 +02:00
parent dd23b848ac
commit ffe3d44cac
+234 -129
View File
@@ -25,6 +25,7 @@
#include "/EgtDev/Include/ENkPolynomialRoots.h"
#include "/EgtDev/Include/EGkGeoObjSave.h" // debug
#include <future>
#include <numeric>
using namespace std ;
@@ -1567,16 +1568,18 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
for ( int i = 0 ; i < nSub ; ++i) {
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart2[i], vPntTopStart2[i+1], vPntTopEnd2[i], vPntTopEnd2[i+1]})) ;
}
// chiudo il volume con le superici verticali in avanti
for ( int i = 0 ; i < nSub ; ++i) {
// chiudo il volume con le superici verticali, 1o volume, interne
for ( int i = 0 ; i < nSub ; ++i)
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart[i+1], vPntTipStart[i], vPntTopStart2[nSub - i - 1], vPntTopStart2[nSub - i]})) ;
// chiudo il volume con le superici verticali, 2o volume, interne
for ( int i = 0 ; i < nSub ; ++i)
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipEnd2[i], vPntTipEnd2[i+1], vPntTopEnd[nSub - i], vPntTopEnd[nSub - i -1]})) ;
}
// chiudo il volume con le superici verticali indietro
for ( int i = 0 ; i < nSub ; ++i) {
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart2[i+1], vPntTipStart2[i], vPntTopStart[nSub - i - 1], vPntTopStart[nSub - i]})) ;
// chiudo il volume con le superici verticali, 1o volume, esterne
for ( int i = 0 ; i < nSub ; ++i)
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipEnd[i], vPntTipEnd[i+1], vPntTopEnd2[nSub - i], vPntTopEnd2[nSub - i - 1]})) ;
}
// chiudo il volume con le superici verticali, 2o volume, esterne
for ( int i = 0 ; i < nSub ; ++i)
vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart2[i+1], vPntTipStart2[i], vPntTopStart[nSub - i - 1], vPntTopStart[nSub - i]})) ;
}
}
else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX) {
@@ -1738,97 +1741,137 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
// scorro tutti gli spilloni interessati
int nAllStepsSurfs = nTotSurf * nStepCnt ;
vector<INTVECTOR> vvnSurf ;
if( n5AxisType != VolZmap::Move5Axis::ACROSS) {
vvnSurf.emplace_back() ;
vvnSurf[0].resize( nAllStepsSurfs) ;
iota( vvnSurf[0].begin(), vvnSurf[0].end(), 0) ;
}
else {
vvnSurf.resize( 2) ;
// superfici laterali
vvnSurf[0] = {0, 1} ;
vvnSurf[1] = {0, 1} ;
int nSurf = 2 ;
// superfici inferiori in avanti
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[0].push_back( nSurf) ;
//superfici superiori indietro
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[1].push_back( nSurf) ;
//superfici inferiori indietro
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[1].push_back( nSurf) ;
//superfici superiori in avanti
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[0].push_back( nSurf) ;
// superfici verticali in avanti interne
for ( int i = 0 ; i < nSub ; ++i, ++nSurf )
vvnSurf[0].push_back( nSurf) ;
// superfici verticali indietro interne
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[1].push_back( nSurf) ;
// superfici verticali in avanti esterne
for ( int i = 0 ; i < nSub ; ++i, ++nSurf )
vvnSurf[0].push_back( nSurf) ;
// superfici verticali indietro esterne
for ( int i = 0 ; i < nSub ; ++i, ++nSurf)
vvnSurf[1].push_back( nSurf) ;
// N.B. : avanti e indietro sono riferiti al caso dSide >0 , in caso dSide <0 si invertono
// ai fini della divisione in due volumi diversi non importa chi sia il primo e chi il secondo volume
}
for ( int i = nStartI ; i <= nEndI ; ++ i) {
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
Point3d r( dX, dY, 0) ;
PNTVEC3DVECTOR vInters ;
vector<PNTVEC3DVECTOR> vvInters( vvnSurf.size()) ;
vector<INTINTVECTOR> vvStartEnds( vvnSurf.size()) ;
//debug
INTVECTOR vSurfInters ;
for(int v = 0 ; v < int(vvnSurf.size()) ; ++v) {
// interseco con le bilineari
for( int s : vvnSurf[v]) {
// verifico che lo spillone faccia interferenza con il box della superficie
if ( vSurfBox[s].SqDistFromPointXY( r) < EPS_ZERO) {
double D1 = ( d[s].x - r.x) * q.z - ( d[s].z - r.z) * q.x ;
double D2 = ( d[s].y - r.y) * q.z - ( d[s].z - r.z) * q.y ;
// interseco con le bilineari
for( int s = 0 ; s < nAllStepsSurfs ; ++s) {
// verifico che lo spillone faccia interferenza con il box della superficie
if ( vSurfBox[s].SqDistFromPointXY( r) < EPS_ZERO) {
double D1 = ( d[s].x - r.x) * q.z - ( d[s].z - r.z) * q.x ;
double D2 = ( d[s].y - r.y) * q.z - ( d[s].z - r.z) * q.y ;
DBLVECTOR vdCoeff, vdRoots ;
vdCoeff = { (B2[s] * D1 - B1[s] * D2), ( A2[s] * D1 - A1[s] * D2 + B2[s] * C1[s] - B1[s] * C2[s]), ( A2[s] * C1[s] - A1[s] * C2[s])} ;
int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ;
if ( nRoots != 0) {
double dU1 = 0, dV1 = 0 ;
double dU2 = 0, dV2 = 0 ;
if ( vdRoots[0] > 0 - EPS_ZERO && vdRoots[0] < 1 + EPS_ZERO) {
dV1 = vdRoots[0] ;
dU1 = (dV1 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV1 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ;
if ( dU1 > - EPS_ZERO && dU1 < 1 + EPS_ZERO) {
Point3d ptBez1 ;
Vector3d vtN1 ;
vSurfBez[s]->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez1, vtN1) ;
vtN1 *= -1 ;
UpdateMaxMin( ptBez1, vtN1, vvInters[v]) ;
DBLVECTOR vdCoeff, vdRoots ;
vdCoeff = { (B2[s] * D1 - B1[s] * D2), ( A2[s] * D1 - A1[s] * D2 + B2[s] * C1[s] - B1[s] * C2[s]), ( A2[s] * C1[s] - A1[s] * C2[s])} ;
int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ;
if ( nRoots != 0) {
double dU1 = 0, dV1 = 0 ;
double dU2 = 0, dV2 = 0 ;
if ( vdRoots[0] > 0 - EPS_ZERO && vdRoots[0] < 1 + EPS_ZERO) {
dV1 = vdRoots[0] ;
dU1 = (dV1 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV1 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ;
if ( dU1 > - EPS_ZERO && dU1 < 1 + EPS_ZERO) {
Point3d ptBez1 ;
Vector3d vtN1 ;
vSurfBez[s]->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez1, vtN1) ;
vtN1 *= -1 ;
UpdateMaxMin( ptBez1, vtN1, vInters) ;
//debug
vSurfInters.push_back( s) ;
//debug
vSurfInters.push_back( s) ;
}
}
}
if ( nRoots > 1 && vdRoots[1] > 0 - EPS_ZERO && vdRoots[1] < 1 + EPS_ZERO) {
dV2 = vdRoots[1] ;
dU2 = (dV2 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV2 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ;
if ( dU2 > - EPS_ZERO && dU2 < 1 + EPS_ZERO) {
Point3d ptBez2 ;
Vector3d vtN2 ;
vSurfBez[s]->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez2, vtN2) ;
vtN2 *= -1 ;
UpdateMaxMin( ptBez2, vtN2, vInters) ;
if ( nRoots > 1 && vdRoots[1] > 0 - EPS_ZERO && vdRoots[1] < 1 + EPS_ZERO) {
dV2 = vdRoots[1] ;
dU2 = (dV2 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV2 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ;
if ( dU2 > - EPS_ZERO && dU2 < 1 + EPS_ZERO) {
Point3d ptBez2 ;
Vector3d vtN2 ;
vSurfBez[s]->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez2, vtN2) ;
vtN2 *= -1 ;
UpdateMaxMin( ptBez2, vtN2, vvInters[v]) ;
//debug
vSurfInters.push_back( s) ;
//debug
vSurfInters.push_back( s) ;
}
}
}
}
}
}
INTINTVECTOR vStartEnds ;
if ( vInters.size() > 2) {
sort( vInters.begin(), vInters.end(), []( PNTVEC3D& a, PNTVEC3D& b){ return a.first.z < b.first.z ;}) ;
INTINT pStartEnd ;
bool bDirStart = vInters.front().second * Z_AX > 0 ;
bool bFirstEndFound = false ;
pStartEnd.first = 0 ;
for ( int w = 1 ; w < int( vInters.size()) ; ++w) {
bool bDir = vInters[w].second * Z_AX > 0 ;
// se è l'ultimo punto esco
if ( w == int( vInters.size() - 1) && bDirStart != bDir) {
pStartEnd.second = w ;
vStartEnds.push_back( pStartEnd) ;
break ;
}
// sennò scorro finché non trovo l'uscita più lontana ( prima di un altro ingresso o eventualmente l'ultima inters)
else if( bDirStart != bDir)
bFirstEndFound = true ;
// se trovo di nuovo un'intersezione orientata come la prima dello spillone allora ho un nuovo start e posso chiudere l'intervallo precedente
else if( bFirstEndFound && bDirStart == bDir) {
pStartEnd.second = w - 1 ;
bFirstEndFound = false ;
vStartEnds.push_back( pStartEnd) ;
pStartEnd.first = w ;
pStartEnd.second = -1 ;
if ( vvInters[v].size() > 2 ) {
sort( vvInters[v].begin(), vvInters[v].end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.z < b.first.z ; }) ;
INTINT pStartEnd ;
bool bDirStart = vvInters[v].front().second * Z_AX > 0 ;
bool bFirstEndFound = false ;
pStartEnd.first = 0 ;
for ( int w = 1 ; w < int( vvInters[v].size()) ; ++w) {
bool bDir = vvInters[v][w].second * Z_AX > 0 ;
// se è l'ultimo punto esco
if ( w == int( vvInters[v].size() - 1) && bDirStart != bDir) {
pStartEnd.second = w ;
vvStartEnds[v].push_back(pStartEnd) ;
break ;
}
// sennò scorro finché non trovo l'uscita più lontana ( prima di un altro ingresso o eventualmente l'ultima inters)
else if( bDirStart != bDir)
bFirstEndFound = true ;
// se trovo di nuovo un'intersezione orientata come la prima dello spillone allora ho un nuovo start e posso chiudere l'intervallo precedente
else if( bFirstEndFound && bDirStart == bDir) {
pStartEnd.second = w - 1 ;
bFirstEndFound = false ;
vvStartEnds[v].push_back(pStartEnd) ;
pStartEnd.first = w ;
pStartEnd.second = -1 ;
}
}
for( auto p : vvStartEnds[v] )
SubtractIntervals(nGrid, i, j, vvInters[v][p.first].first.z, vvInters[v][p.second].first.z, vvInters[v][p.first].second, vvInters[v][p.second].second, nToolNum) ;
}
for( auto p : vStartEnds)
SubtractIntervals(nGrid, i, j, vInters[p.first].first.z, vInters[p.second].first.z, vInters[p.first].second, vInters[p.second].second, nToolNum) ;
else if ( vvInters[v].size() == 2){
vvStartEnds[v].push_back(INTINT(0, 1)) ;
SubtractIntervals( nGrid, i, j, vvInters[v].front().first.z, vvInters[v].back().first.z, vvInters[v].front().second, vvInters[v].back().second, nToolNum) ;
}
else if ( vvInters[v].size() == 1)
return false ;
}
else if ( vInters.size() == 2){
vStartEnds.push_back( INTINT(0,1)) ;
SubtractIntervals( nGrid, i, j, vInters.front().first.z, vInters.back().first.z, vInters.front().second, vInters.back().second, nToolNum) ;
}
else if ( vInters.size() == 1)
return false ;
// interseco con la prima metà del tool in posizione iniziale e con la seconda metà del tool in posizione finale
PNTVEC3DVECTOR vIntersTool ;
@@ -1992,32 +2035,42 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
}
}
}
// se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari
// se non ho neanche questa intersezione allora posso buttare via tutto
if ( ! vbUpdate[p] && vInters.size() != 0) {
int c = 0 ;
int nClosePair = -1 ;
bool bStartOrEndPair = false ; // true = start ; false = end
if ( ! vbUpdate[p]) {
int nVol = -1 ;
bool bStartOrEndPair = false ; // true = start ; false = end
double dMinDist = INFINITO ;
for ( auto& pair : vStartEnds) {
double dDist = Dist( vPntInters[p], vInters[pair.first].first) ;
if ( dDist < dMinDist ) {
dMinDist = dDist ;
bStartOrEndPair = true ;
nClosePair = c ;
int nClosePair = -1 ;
for( int v = 0 ; v < int( vvnSurf.size()) ; ++v) {
if ( vvInters[v].size() != 0) {
int c = 0 ;
for ( auto& pair : vvStartEnds[v]) {
double dDist = Dist( vPntInters[p], vvInters[v][pair.first].first) ;
if ( dDist < dMinDist ) {
dMinDist = dDist ;
bStartOrEndPair = true ;
nClosePair = c ;
nVol = v ;
}
dDist = Dist( vPntInters[p], vvInters[v][pair.second].first) ;
if ( dDist < dMinDist) {
dMinDist = dDist ;
bStartOrEndPair = false ;
nClosePair = c ;
nVol = v ;
}
++c ;
}
}
dDist = Dist( vPntInters[p], vInters[pair.second].first) ;
if ( dDist < dMinDist) {
dMinDist = dDist ;
bStartOrEndPair = false ;
nClosePair = c ;
}
++c ;
}
if( bStartOrEndPair)
vPntInters[p] = vInters[vStartEnds[nClosePair].first].first ;
else
vPntInters[p] = vInters[vStartEnds[nClosePair].second].first ;
if( nClosePair != -1) {
if( bStartOrEndPair)
vPntInters[p] = vvInters[nVol][vvStartEnds[nVol][nClosePair].first].first ;
else
vPntInters[p] = vvInters[nVol][vvStartEnds[nVol][nClosePair].second].first ;
}
}
}
// base superiore
@@ -2088,32 +2141,44 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
}
}
}
// se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari
// se non ho neanche questa intersezione allora posso buttare via tutto
if ( ! vbUpdate[p] && vInters.size() != 0) {
int c = 0 ;
int nClosePair = -1 ;
bool bStartOrEndPair = false ; // true = start ; false = end
if ( ! vbUpdate[p]) {
int nVol = -1 ;
bool bStartOrEndPair = false ; // true = start ; false = end
double dMinDist = INFINITO ;
for ( auto& pair : vStartEnds) {
double dDist = Dist( vPntInters[p], vInters[pair.first].first) ;
if ( dDist < dMinDist ) {
dMinDist = dDist ;
bStartOrEndPair = true ;
nClosePair = c ;
int nClosePair = -1 ; // coppia più vicina
for( int v = 0 ; v < int( vvnSurf.size()) ; ++v) {
// se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari
// se non ho neanche questa intersezione allora posso buttare via tutto
if ( vvInters[v].size() != 0 ) {
int c = 0 ;
for ( auto& pair : vvStartEnds[v]) {
double dDist = Dist( vPntInters[p], vvInters[v][pair.first].first) ;
if ( dDist < dMinDist ) {
dMinDist = dDist ;
bStartOrEndPair = true ;
nClosePair = c ;
nVol = v ;
}
dDist = Dist( vPntInters[p], vvInters[v][pair.second].first) ;
if ( dDist < dMinDist) {
dMinDist = dDist ;
bStartOrEndPair = false ;
nClosePair = c ;
nVol = v ;
}
++c ;
}
}
dDist = Dist( vPntInters[p], vInters[pair.second].first) ;
if ( dDist < dMinDist) {
dMinDist = dDist ;
bStartOrEndPair = false ;
nClosePair = c ;
}
++c ;
}
if( bStartOrEndPair)
vPntInters[p] = vInters[vStartEnds[nClosePair].first].first ;
else
vPntInters[p] = vInters[vStartEnds[nClosePair].second].first ;
if( nClosePair != -1) {
if( bStartOrEndPair)
vPntInters[p] = vvInters[nVol][vvStartEnds[nVol][nClosePair].first].first ;
else
vPntInters[p] = vvInters[nVol][vvStartEnds[nVol][nClosePair].second].first ;
}
}
}
else if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS &&
@@ -2196,14 +2261,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
Vector3d vtNTop ;
vSurfBez[nSurf]->GetPointNrmD1D2( 0.5, 0, ISurfBezier::Side::FROM_MINUS,ISurfBezier::Side::FROM_MINUS, ptCTop, vtNTop) ;
Vector3d vtIntTop = vPntInters[p] - ptCTop ;
//debug
double dX = vtIntTop.x * vtNTop.x ;
double dY = vtIntTop.y * vtNTop.y ;
double dZ = vtIntTop.z * vtNTop.z ;
double dRes = vtIntTop * vtNTop ;
//debug
bUnderTop = vtIntTop * vtNTop < 0 ;
}
}
@@ -2266,6 +2323,54 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
}
}
// se solo una delle due intersezioni è da scartare, allora la sostituisco con un punto all'interno della più vicina intersezione con
// il volume identificato dalle bilineari
int nPointToAdjust = -1 ;
if( vbUpdate[0] && ! vbUpdate[1])
nPointToAdjust = 1 ;
if( ! vbUpdate[0] && vbUpdate[1])
nPointToAdjust = 0 ;
if ( nPointToAdjust != -1) {
// se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari
// se non ho neanche questa intersezione allora posso buttare via tutto
int nVol = -1 ;
bool bStartOrEndPair = false ; // true = start ; false = end
double dMinDist = INFINITO ;
int nClosePair = -1 ; // coppia più vicina
for( int v = 0 ; v < int( vvnSurf.size()) ; ++v) {
// se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari
// se non ho neanche questa intersezione allora posso buttare via tutto
if ( vvInters[v].size() != 0 ) {
int c = 0 ;
for ( auto& pair : vvStartEnds[v]) {
double dDist = Dist( vPntInters[nPointToAdjust], vvInters[v][pair.first].first) ;
if ( dDist < dMinDist ) {
dMinDist = dDist ;
bStartOrEndPair = true ;
nClosePair = c ;
nVol = v ;
}
dDist = Dist( vPntInters[nPointToAdjust], vvInters[v][pair.second].first) ;
if ( dDist < dMinDist) {
dMinDist = dDist ;
bStartOrEndPair = false ;
nClosePair = c ;
nVol = v ;
}
++c ;
}
}
}
if( nClosePair != -1) {
if( bStartOrEndPair)
vPntInters[nPointToAdjust] = vvInters[nVol][vvStartEnds[nVol][nClosePair].first].first ;
else
vPntInters[nPointToAdjust] = vvInters[nVol][vvStartEnds[nVol][nClosePair].second].first ;
vbUpdate[nPointToAdjust] = true ;
}
}
if ( vbUpdate[0]) {
UpdateMaxMin( vPntInters[0], vVtIntersNorm[0], vIntersTool) ;