EgtGeomKernel :
- correzioni e miglioramenti per il VM5assi con superfici bezier di grado 3x1.
This commit is contained in:
+346
-122
@@ -25,6 +25,7 @@
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h" // debug
|
||||
#include "SurfBezier.h"
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
|
||||
@@ -1132,8 +1133,8 @@ GetAlongAcrossRotation( const Vector3d& vtDir1, const Vector3d& vtDir2, const Ve
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateMaxMin( Point3d& ptBez, Vector3d& vtN, PNTVEC3DVECTOR& vInters) const
|
||||
static bool
|
||||
UpdateMaxMin( Point3d& ptBez, Vector3d& vtN, PNTVEC3DVECTOR& vInters)
|
||||
{
|
||||
if ( ! AreSameVectorExact( vtN, V_NULL))
|
||||
vInters.emplace_back( PNTVEC3D( ptBez, vtN)) ;
|
||||
@@ -1310,7 +1311,7 @@ VolZmap::GenTool_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR&
|
||||
return true ;
|
||||
}
|
||||
|
||||
#if true
|
||||
#if false
|
||||
//debug
|
||||
#define TEST
|
||||
static vector<IGeoObj*> vGeo ;
|
||||
@@ -1318,6 +1319,226 @@ VolZmap::GenTool_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR&
|
||||
//debug
|
||||
#endif
|
||||
|
||||
static void
|
||||
SortGroupInters( PNTVEC3DVECTOR& vInters, INTINTVECTOR& vStartEnds, const Vector3d& vMainAx) {
|
||||
if( AreSameVectorExact(vMainAx, Z_AX))
|
||||
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.z < b.first.z ; }) ;
|
||||
else if( AreSameVectorExact(vMainAx, Y_AX))
|
||||
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.y < b.first.y ; }) ;
|
||||
else if( AreSameVectorExact(vMainAx, X_AX))
|
||||
sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.x < b.first.x ; }) ;
|
||||
// devo controllare che le intersezioni estreme abbiano direzione opposta
|
||||
// in caso contrario potrei avere ad uno dei due estremi due punti quasi coincidenti e stare prendendo per più esterno quello con la normale sbagliata
|
||||
bool bExtremesAreOpposite = ( vInters.front().second * vMainAx) * (vInters.back().second * vMainAx) < 0 ;
|
||||
if ( ! bExtremesAreOpposite) {
|
||||
// se ad uno dei due estremi trovo due punti quasi coincidenti scambio le normali dei due punti di intersezione
|
||||
bool bAtStart = false ;
|
||||
bool bAtEnd = false ;
|
||||
if( AreSameVectorExact(vMainAx, Z_AX)) {
|
||||
bAtStart = (vInters[0].first.z - vInters[1].first.z) < EPS_SMALL ;
|
||||
bAtEnd = (vInters.back().first.z - vInters.end()[-2].first.z) < EPS_SMALL ;
|
||||
}
|
||||
else if ( AreSameVectorExact(vMainAx, Y_AX) ) {
|
||||
bAtStart = (vInters[0].first.y - vInters[1].first.y) < EPS_SMALL ;
|
||||
bAtEnd = (vInters.back().first.y - vInters.end()[-2].first.y) < EPS_SMALL ;
|
||||
}
|
||||
else if ( AreSameVectorExact(vMainAx, X_AX) ) {
|
||||
bAtStart = (vInters[0].first.x - vInters[1].first.x) < EPS_SMALL ;
|
||||
bAtEnd = (vInters.back().first.x - vInters.end()[-2].first.x) < EPS_SMALL ;
|
||||
}
|
||||
if( bAtStart)
|
||||
swap( vInters[0].second, vInters[1].second) ;
|
||||
else if( bAtEnd)
|
||||
swap( vInters.back().second, vInters.end()[-2].second) ;
|
||||
}
|
||||
|
||||
INTINT pStartEnd ;
|
||||
bool bDirStart = vInters.front().second * vMainAx > 0 ;
|
||||
bool bFirstEndFound = false ;
|
||||
pStartEnd.first = 0 ;
|
||||
for ( int w = 1 ; w < int( vInters.size()) ; ++w) {
|
||||
bool bDir = vInters[w].second * vMainAx > 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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SurfBezForInters {
|
||||
SurfBezier sBez ;
|
||||
BBox3d bbSurf ;
|
||||
Vector3d a3, a2, a1, a0, b3, b2, b1, b0 ;
|
||||
};
|
||||
|
||||
static bool
|
||||
IntersLineBezierSurfSet( const Point3d& ptLineStart, const Vector3d& vtLineDir, const vector<SurfBezForInters>& vSurfBez, PNTVEC3DVECTOR& vInters, INTVECTOR& vSurfInters) {
|
||||
Point3d r = ptLineStart ;
|
||||
Vector3d q = vtLineDir ;
|
||||
|
||||
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
|
||||
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
|
||||
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
|
||||
Frame3d frRot ;
|
||||
if( bNeedToRotX)
|
||||
frRot.Set( ORIG, X_AX) ;
|
||||
if( bNeedToRotY)
|
||||
frRot.Set( ORIG, Y_AX) ;
|
||||
if ( bNeedToRot ) {
|
||||
r.ToLoc( frRot) ;
|
||||
q.ToLoc( frRot) ;
|
||||
}
|
||||
// interseco con le bezier
|
||||
for( int s = 0 ; s < int( vSurfBez.size()) ; ++s) {
|
||||
const SurfBezForInters& srf = vSurfBez[s] ;
|
||||
BBox3d bbox = srf.bbSurf ;
|
||||
if( bNeedToRot)
|
||||
bbox.ToLoc( frRot) ;
|
||||
// verifico che lo spillone faccia interferenza con il box della superficie
|
||||
if ( bbox.SqDistFromPointXY( r) < EPS_ZERO) {
|
||||
//const Vector3d& a3 = srf.a3 ;
|
||||
//const Vector3d& a2 = srf.a2 ;
|
||||
//const Vector3d& a1 = srf.a1 ;
|
||||
//const Vector3d& a0 = srf.a0 ;
|
||||
//const Vector3d& b3 = srf.b3 ;
|
||||
//const Vector3d& b2 = srf.b2 ;
|
||||
//const Vector3d& b1 = srf.b1 ;
|
||||
//const Vector3d& b0 = srf.b0 ;
|
||||
|
||||
// se la linea è parallela all'asse X o Y allora ruoto tutto di 45 gradi rispetto a Z
|
||||
Vector3d a3, a2, a1, a0, b3, b2, b1, b0 ;
|
||||
if ( ! bNeedToRot) {
|
||||
a3 = srf.a3 ;
|
||||
a2 = srf.a2 ;
|
||||
a1 = srf.a1 ;
|
||||
a0 = srf.a0 ;
|
||||
b3 = srf.b3 ;
|
||||
b2 = srf.b2 ;
|
||||
b1 = srf.b1 ;
|
||||
b0 = srf.b0 ;
|
||||
}
|
||||
else {
|
||||
SurfBezier sBezRot = srf.sBez ;
|
||||
sBezRot.ToLoc( frRot) ;
|
||||
PNTVECTOR vPntCtrl = sBezRot.GetAllControlPoints() ;
|
||||
|
||||
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
|
||||
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
|
||||
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
|
||||
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
|
||||
Vector3d E = vPntCtrl[0] - ORIG ;
|
||||
Vector3d F = vPntCtrl[1] - ORIG ;
|
||||
Vector3d G = vPntCtrl[2] - ORIG ;
|
||||
Vector3d H = vPntCtrl[3] - ORIG ;
|
||||
|
||||
a3 = -A + 3*B - 3*C + D ;
|
||||
a2 = 3*A - 6*B + 3*C ;
|
||||
a1 = -3*A +3*B ;
|
||||
a0 = A ;
|
||||
|
||||
b3 = -E + 3*F - 3*G + H ;
|
||||
b2 = 3*E - 6*F + 3*G ;
|
||||
b1 = -3*E + 3*F ;
|
||||
b0 = E ;
|
||||
}
|
||||
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
// coefficienti dal grado più basso al grado più alto
|
||||
vdCoeff = { // c0
|
||||
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
|
||||
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
|
||||
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
|
||||
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
|
||||
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
|
||||
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
|
||||
|
||||
// c1
|
||||
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
|
||||
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
|
||||
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
|
||||
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
|
||||
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
|
||||
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
|
||||
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
|
||||
|
||||
// c2
|
||||
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
|
||||
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
|
||||
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
|
||||
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
|
||||
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
|
||||
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
|
||||
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
|
||||
|
||||
// c3
|
||||
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
|
||||
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
|
||||
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
|
||||
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
|
||||
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
|
||||
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
|
||||
|
||||
// c4
|
||||
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
|
||||
|
||||
// c5
|
||||
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
|
||||
|
||||
// c6
|
||||
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
|
||||
q.y*q.z*a3.z*b3.z - q.z*q.z*a3.y*b3.x + // 4
|
||||
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
|
||||
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
|
||||
for( int w = 0 ; w < nRoots ; ++w) {
|
||||
double dU = 0, dV = 0 ;
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
|
||||
dU = vdRoots[w] ;
|
||||
// verifico che non sia una soluzione con molteplicità > 1
|
||||
bool bAlreadyFound = false ;
|
||||
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
|
||||
bAlreadyFound = abs( dU - vdRoots[k]) < EPS_PARAM ;
|
||||
if( ! bAlreadyFound) {
|
||||
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
|
||||
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
|
||||
dV = - ( vBeta.x - r.x) / vAlpha.x ;
|
||||
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
|
||||
Point3d ptBez ;
|
||||
Vector3d vtN ;
|
||||
srf.sBez.GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez, vtN) ;
|
||||
vtN *= -1 ;
|
||||
UpdateMaxMin( ptBez, vtN, vInters) ;
|
||||
|
||||
//debug
|
||||
vSurfInters.push_back( s) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe,
|
||||
@@ -1348,18 +1569,8 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
else if( n5AxisType == VolZmap::Move5Axis::ACROSS)
|
||||
nTotSurf = 2 * nStepCnt + nSub * 4 * nStepCnt + nSub * 2 + 16 ; // come caso ALONG
|
||||
|
||||
VCT3DVECTOR a3( nTotSurf) ;
|
||||
VCT3DVECTOR a2( nTotSurf) ;
|
||||
VCT3DVECTOR a1( nTotSurf) ;
|
||||
VCT3DVECTOR a0( nTotSurf) ;
|
||||
VCT3DVECTOR b3( nTotSurf) ;
|
||||
VCT3DVECTOR b2( nTotSurf) ;
|
||||
VCT3DVECTOR b1( nTotSurf) ;
|
||||
VCT3DVECTOR b0( nTotSurf) ;
|
||||
|
||||
int nSurfInd = 0 ;
|
||||
ISURFBEZPOVECTOR vSurfBez( nTotSurf * nStepCnt) ;
|
||||
BOXVECTOR vSurfBox( nTotSurf * nStepCnt) ;
|
||||
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
||||
double dSide = 0 ;
|
||||
// punti per le bilineari, sulle posizioni del tool alle estremità del movimento
|
||||
PNTVECTOR vPntTipStartExF ;
|
||||
@@ -1901,17 +2112,16 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
|
||||
// inizializzo le superfici bilineari e i parametri per le intersezioni
|
||||
for( int z = 0 ; z < int( vvPtCtrl.size()) ; ++z) {
|
||||
vSurfBez[nSurfInd].Set( CreateSurfBezier()) ;
|
||||
vSurfBez[nSurfInd]->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 0, vvPtCtrl[z][0]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 1, vvPtCtrl[z][1]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 2, vvPtCtrl[z][2]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 3, vvPtCtrl[z][3]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 4, vvPtCtrl[z][4]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 5, vvPtCtrl[z][5]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 6, vvPtCtrl[z][6]) ;
|
||||
vSurfBez[nSurfInd]->SetControlPoint( 7, vvPtCtrl[z][7]) ;
|
||||
vSurfBox[nSurfInd].Add( vvPtCtrl[z]) ;
|
||||
vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 2, vvPtCtrl[z][2]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 3, vvPtCtrl[z][3]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 4, vvPtCtrl[z][4]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 5, vvPtCtrl[z][5]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 6, vvPtCtrl[z][6]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 7, vvPtCtrl[z][7]) ;
|
||||
vSurfBez[nSurfInd].bbSurf.Add( vvPtCtrl[z]) ;
|
||||
|
||||
Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ;
|
||||
Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ;
|
||||
@@ -1919,22 +2129,22 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
Vector3d D = vvPtCtrl[z][7] - vvPtCtrl[z][3] ;
|
||||
Vector3d E = vvPtCtrl[z][0] - ORIG ;
|
||||
Vector3d F = vvPtCtrl[z][1] - ORIG ;
|
||||
Vector3d G = vvPtCtrl[z][2] - ORIG;
|
||||
Vector3d G = vvPtCtrl[z][2] - ORIG ;
|
||||
Vector3d H = vvPtCtrl[z][3] - ORIG ;
|
||||
|
||||
a3[nSurfInd] = -A + 3*B - 3*C + D ;
|
||||
a2[nSurfInd] = 3*A - 6*B + 3*C ;
|
||||
a1[nSurfInd] = -3*A +3*B ;
|
||||
a0[nSurfInd] = A ;
|
||||
vSurfBez[nSurfInd].a3 = -A + 3*B - 3*C + D ;
|
||||
vSurfBez[nSurfInd].a2 = 3*A - 6*B + 3*C ;
|
||||
vSurfBez[nSurfInd].a1 = -3*A +3*B ;
|
||||
vSurfBez[nSurfInd].a0 = A ;
|
||||
|
||||
b3[nSurfInd] = -E + 3*F - 3*G + H ;
|
||||
b2[nSurfInd] = 3*E - 6*F + 3*G ;
|
||||
b1[nSurfInd] = -3*E + 3*F ;
|
||||
b0[nSurfInd] = E ;
|
||||
vSurfBez[nSurfInd].b3 = -E + 3*F - 3*G + H ;
|
||||
vSurfBez[nSurfInd].b2 = 3*E - 6*F + 3*G ;
|
||||
vSurfBez[nSurfInd].b1 = -3*E + 3*F ;
|
||||
vSurfBez[nSurfInd].b0 = E ;
|
||||
|
||||
#ifdef TEST
|
||||
if ( nGrid == 0)
|
||||
vGeo.push_back( vSurfBez[nSurfInd]->Clone()) ;
|
||||
vGeo.push_back( vSurfBez[nSurfInd].sBez.Clone()) ;
|
||||
#endif
|
||||
++ nSurfInd ;
|
||||
}
|
||||
@@ -1950,34 +2160,30 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
//debug
|
||||
#endif
|
||||
|
||||
|
||||
//BBox3d bbStartCyl = GetCylMoveBBox( ptS[0], ptS[0], vtLs[0], dMaxRad, dHeight) ;
|
||||
//BBox3d bbEndCyl = GetCylMoveBBox( ptE.back(), ptE.back(), vtLe.back(), dMaxRad, dHeight) ;
|
||||
|
||||
//// se sono nel caso di un cono calcolo già i parametri utili
|
||||
//Point3d ptVS, ptVE ;
|
||||
//double dTan = 0, dMinH, dMaxH ;
|
||||
//Point3d ptP1T = ptS[0] - vtLs[0] * dHeight ;
|
||||
//Point3d ptP2T = ptE.back() - vtLe.back() * dHeight ;
|
||||
//if ( dMinRad < EPS_SMALL) {
|
||||
// ptVS = ptP1T ;
|
||||
// ptVE = ptP2T ;
|
||||
// dMinH = 0 ;
|
||||
// dMaxH = dHeight ;
|
||||
// dTan = dMaxRad / dHeight ;
|
||||
//}
|
||||
//else {
|
||||
// dTan = (dMaxRad - dMinRad) / dHeight ;
|
||||
// dMaxH = dMaxRad * dTan ;
|
||||
// dMinH = dMaxH - dHeight ;
|
||||
// ptVS = ptS[0] - vtLs[0] * dMaxH ;
|
||||
// ptVE = ptE.back() - vtLe.back() * dMaxH ;
|
||||
//}
|
||||
|
||||
// scorro tutti gli spilloni interessati
|
||||
int nAllStepsSurfs = nTotSurf * nStepCnt ;
|
||||
int j = 0 ;
|
||||
int nLastForwardJ = -1 ;
|
||||
struct IntervalsToSubtract {
|
||||
int i = 0 ;
|
||||
int j = 0 ;
|
||||
bool bUseOnlyExtremes = false ;
|
||||
PNTVEC3DVECTOR vInters ;
|
||||
INTINTVECTOR vStartEnds ;
|
||||
IntervalsToSubtract( int nI, int nJ, PNTVEC3DVECTOR& vPntInt, INTINTVECTOR& vSE, bool bUseExtremes) : i( nI), j( nJ), bUseOnlyExtremes( bUseExtremes), vInters( vPntInt), vStartEnds( vSE) {}
|
||||
} ;
|
||||
bool bUseOnlyExtremes = false ;
|
||||
bool bFirstAmbiguousCaseType = false ;
|
||||
bool bForward = true ;
|
||||
bool bAllSameType = false ;
|
||||
vector<IntervalsToSubtract> vIntervalsToSubtr ;
|
||||
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
||||
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
||||
nLastForwardJ = -1 ;
|
||||
j = nStartJ ;
|
||||
bAllSameType = false ;
|
||||
bForward = true ;
|
||||
bFirstAmbiguousCaseType = false ;
|
||||
while ( j <= nEndJ && j > nLastForwardJ) {
|
||||
double dX = ( i + 0.5) * m_dStep ;
|
||||
double dY = ( j + 0.5) * m_dStep ;
|
||||
Point3d r( dX, dY, 0) ;
|
||||
@@ -1986,70 +2192,70 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
|
||||
//debug
|
||||
INTVECTOR vSurfInters ;
|
||||
// interseco con le bilineari
|
||||
for( int s = 0 ; s < int( vSurfBez.size()) ; ++s) {
|
||||
// verifico che lo spillone faccia interferenza con il box della superficie
|
||||
if ( vSurfBox[s].SqDistFromPointXY( r) < EPS_ZERO) {
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
// coefficienti dal grado più basso al grado più alto
|
||||
vdCoeff = { - a0[s].y * b0[s].x + r.x * a0[s].y + a0[s].x * b0[s].y - r.y * a0[s].x,
|
||||
- a1[s].y * b0[s].x - a0[s].y * b1[s].x + r.x * a1[s].y + a1[s].x * b0[s].y + a0[s].x * b1[s].y - r.y * a1[s].x,
|
||||
- a2[s].y * b0[s].x - a1[s].y * b1[s].x - a0[s].y * b2[s].x + r.x * a2[s].y + a2[s].x * b0[s].y + a1[s].x * b1[s].y + a0[s].x * b2[s].y - r.y * a2[s].x,
|
||||
- a3[s].y * b0[s].x - a2[s].y * b1[s].x - a1[s].y * b2[s].x - a0[s].y * b3[s].x + r.x * a3[s].y + a3[s].x * b0[s].y + a2[s].x * b1[s].y + a1[s].x * b2[s].y + a0[s].x * b3[s].y - r.y * a3[s].x,
|
||||
- a3[s].y * b1[s].x - a2[s].y * b2[s].x - a1[s].y * b3[s].x + a3[s].x * b1[s].y + a2[s].x * b2[s].y + a1[s].x * b3[s].y,
|
||||
- a3[s].y * b2[s].x - a2[s].y * b3[s].x + a3[s].x * b2[s].y + a2[s].x * b3[s].y,
|
||||
- a3[s].y * b3[s].x + a3[s].x * b3[s].y} ;
|
||||
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
|
||||
for( int w = 0 ; w < nRoots ; ++w) {
|
||||
double dU = 0, dV = 0 ;
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
|
||||
dU = vdRoots[w] ;
|
||||
Vector3d vAlpha = a3[s] * pow(dU, 3) + a2[s] * pow( dU, 2) + a1[s] * dU + a0[s] ;
|
||||
Vector3d vBeta = b3[s] * pow(dU, 3) + b2[s] * pow( dU, 2) + b1[s] * dU + b0[s] ;
|
||||
dV = - ( vBeta.x - r.x) / vAlpha.x ;
|
||||
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
|
||||
Point3d ptBez ;
|
||||
Vector3d vtN ;
|
||||
vSurfBez[s]->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez, vtN) ;
|
||||
vtN *= -1 ;
|
||||
UpdateMaxMin( ptBez, vtN, vInters) ;
|
||||
|
||||
//debug
|
||||
vSurfInters.push_back( s) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//debug
|
||||
IntersLineBezierSurfSet( r, q, vSurfBez, vInters, vSurfInters) ;
|
||||
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 ;
|
||||
}
|
||||
SortGroupInters( vInters, vStartEnds, Z_AX) ;
|
||||
if ( bForward && vStartEnds.size() > 1) {
|
||||
// se ho più di un intervallo da togliere allora devo capire se sono dentro il volume spazzato dal tool o no
|
||||
nLastForwardJ = j ;
|
||||
j = nEndJ + 1 ;
|
||||
bForward = false ;
|
||||
}
|
||||
if ( ! bForward && vStartEnds.size() > 1) {
|
||||
// salvo la prima intersezione dubbia e comincio a scorrere al contrario per trovare l'ultima e capire se è dello stesso tipo della prima
|
||||
|
||||
if( ! bAllSameType) {
|
||||
bUseOnlyExtremes = false ;
|
||||
// calcolo le intersezioni anche sugli altri due spilloni passanti per un punto a metà tra due dei vari intervalli
|
||||
// ho almeno due intervalli; prendo un punto a metà tra la fine del primo e l'inzio del secondo
|
||||
Point3d ptLineStart = (vInters[vStartEnds[0].second].first + vInters[vStartEnds[1].first].first ) / 2 ;
|
||||
Vector3d vtLineStart = X_AX ;
|
||||
PNTVEC3DVECTOR vIntersX ;
|
||||
INTVECTOR vSurfX ;
|
||||
INTINTVECTOR vStartEndsX ;
|
||||
bool bXInclude = false ;
|
||||
IntersLineBezierSurfSet( ptLineStart, vtLineStart, vSurfBez, vIntersX, vSurfX) ;
|
||||
if( vIntersX.size() > 0) {
|
||||
SortGroupInters( vIntersX, vStartEndsX, X_AX) ;
|
||||
// se ho più di una intersezione e il punto di studio è compreso tra questi punti allora le info lungo questa direzione mi dicono che sono interno al volume spazzato
|
||||
bXInclude = vIntersX[vStartEndsX.front().first].first.x < ptLineStart.x && vIntersX[vStartEndsX.back().second].first.x > ptLineStart.x ;
|
||||
}
|
||||
|
||||
vtLineStart = Y_AX ;
|
||||
PNTVEC3DVECTOR vIntersY ;
|
||||
INTVECTOR vSurfY ;
|
||||
INTINTVECTOR vStartEndsY ;
|
||||
bool bYInclude = false ;
|
||||
IntersLineBezierSurfSet( ptLineStart, vtLineStart, vSurfBez, vIntersY, vSurfY) ;
|
||||
if ( vIntersY.size() > 1) {
|
||||
SortGroupInters( vIntersY, vStartEndsY, Y_AX) ;
|
||||
// se ho più di una intersezione e il punto di studio è compreso tra questi punti allora le info lungo questa direzione mi dicono che sono interno al volume spazzato
|
||||
bYInclude = vIntersY[vStartEndsY.front().first].first.y < ptLineStart.y && vIntersY[vStartEndsY.back().second].first.y > ptLineStart.y ;
|
||||
}
|
||||
|
||||
// se anche gli spilloni nelle altre due direzioni fanno intersezione sia a destra che a sinistra rispetto al punto a metà tra gli intervalli, allora sono all'interno del volume
|
||||
if( bXInclude && bYInclude)
|
||||
bUseOnlyExtremes = true ;
|
||||
}
|
||||
|
||||
int nJToSave = j ;
|
||||
if( j == nEndJ + 1) {
|
||||
nJToSave = nLastForwardJ ;
|
||||
bFirstAmbiguousCaseType = bUseOnlyExtremes ;
|
||||
}
|
||||
else {
|
||||
// se ho trovato un caso ambiguo ( scorrendo al contrario) che è uguale al primo che ho trovato scorrendo dritto allora posso considerare tutti gli spilloni restanti di
|
||||
// questo tipo e calcolare solo le intersezioni
|
||||
if ( bUseOnlyExtremes == bFirstAmbiguousCaseType)
|
||||
bAllSameType = true ;
|
||||
}
|
||||
vIntervalsToSubtr.emplace_back( i, nJToSave, vInters, vStartEnds, bUseOnlyExtremes) ;
|
||||
}
|
||||
else {
|
||||
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) ;
|
||||
}
|
||||
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 ( vInters.size() == 2){
|
||||
vStartEnds.push_back(INTINT(0, 1)) ;
|
||||
@@ -2057,6 +2263,24 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt
|
||||
}
|
||||
else if ( vInters.size() == 1)
|
||||
return false ;
|
||||
|
||||
if ( bForward)
|
||||
++j ;
|
||||
else
|
||||
--j ;
|
||||
}
|
||||
}
|
||||
|
||||
for ( IntervalsToSubtract& intToSub : vIntervalsToSubtr) {
|
||||
if ( intToSub.bUseOnlyExtremes)
|
||||
SubtractIntervals( nGrid, intToSub.i, intToSub.j, intToSub.vInters.front().first.z, intToSub.vInters.back().first.z, intToSub.vInters.front().second, intToSub.vInters.back().second, nToolNum) ;
|
||||
else {
|
||||
// scorro le intersezione su questo spillone togliendo gli intervalli usando vStartEnds
|
||||
for ( int z = 0 ; z < int( intToSub.vStartEnds.size()) ; ++z) {
|
||||
int nStart = intToSub.vStartEnds[z].first ;
|
||||
int nEnd = intToSub.vStartEnds[z].second ;
|
||||
SubtractIntervals( nGrid, intToSub.i, intToSub.j, intToSub.vInters[nStart].first.z, intToSub.vInters[nEnd].first.z, intToSub.vInters[nStart].second, intToSub.vInters[nEnd].second, nToolNum) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user