//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // Contenuto : Implementazione della classe Volume Zmap (tre griglie) // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineSurfTm.h" #include "\EgtDev\Include\EgtNumUtils.h" using namespace std ; //---------------------------------------------------------------------------- bool VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) { // Il box è allineato agli assi dU1 = - INFINITO ; dU2 = INFINITO ; // confronto con piani YZ (perpendicolari ad asse X) if ( vtV.x > EPS_ZERO) { dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ; dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ; } else if ( vtV.x < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ; dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ; } else if ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL) return false ; // confronto con piani ZX (perpendicolari ad asse Y) if ( vtV.y > EPS_ZERO) { dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ; dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ; } else if ( vtV.y < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ; dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ; } else if ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL) return false ; // confronto con piani XZ (perpendicolari ad asse Z) if ( vtV.z > EPS_ZERO) { dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ; dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ; } else if ( vtV.z < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ; dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ; } else if ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL) return false ; return ( dU2 >= dU1) ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineZMapBBox( unsigned int nGrid, const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) { // Punti estremi del box dello Zmap Point3d ptMin = ORIG ; Point3d ptMax = ptMin + Vector3d( m_nVNx[nGrid] * m_dStep, m_nVNy[nGrid] * m_dStep, m_dVMaxZ[nGrid]) ; return ( IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) && ( dU1 > 0 || dU2 > 0)) ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineDexel( unsigned int nGrid, const Point3d& ptP, const Vector3d& vtV, unsigned int nI, unsigned int nJ, double& dU1, double& dU2) { // Determino l'indice del dexel e il doppio del numero di suo intervalli unsigned int nDexelPos = nJ * m_nVNx[nGrid] + nI ; unsigned int nDexelSize = unsigned int( m_TriZValues[nGrid][nDexelPos].size()) ; // Se non c'è materiale non devo fare alcunché if ( nDexelSize == 0) return false ; // Determino estremi nel piano XY intrinseco del dexel double dXmin = nI * m_dStep ; double dYmin = nJ * m_dStep ; double dXmax = ( nI + 1) * m_dStep ; double dYmax = ( nJ + 1) * m_dStep ; // ciclo sugli intervalli dU1 = INFINITO ; dU2 = - INFINITO ; bool bInters = false ; for ( unsigned int nIndex = 0 ; nIndex < nDexelSize ; nIndex += 2) { // estremi del box del singolo intervallo Point3d ptE1( dXmin, dYmin, m_TriZValues[nGrid][nDexelPos][nIndex]) ; Point3d ptE2( dXmax, dYmax, m_TriZValues[nGrid][nDexelPos][nIndex+1]) ; double dt1, dt2 ; if ( IntersLineBox( ptP, vtV, ptE1, ptE2, dt1, dt2)) { bInters = true ; dU1 = min( dU1, dt1) ; dU2 = max( dU2, dt2) ; } } return bInters ; } //---------------------------------------------------------------------------- bool VolZmap::GetDepth( const Point3d& ptPGlob, const Vector3d& vtDir, double& dInLength, double& dOutLength) { // Porto il raggio nel riferimento intrinseco Point3d ptP = ptPGlob ; ptP.ToLoc( m_MapFrame[0]) ; Vector3d vtV = vtDir ; vtV.ToLoc( m_MapFrame[0]) ; vtV.Normalize() ; // Studio dell'intersezione fra semiretta e BBox dello Zmap double dU1, dU2 ; bool bTest = IntersLineZMapBBox( 0, ptP, vtV, dU1, dU2) ; // Semiretta esterna al box dello Zmap if ( ! bTest) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } Point3d ptI, ptF ; // Una sola intersezione valida ( punto interno, intersezione valida 2) if ( dU1 < 0 && dU2 > 0) { ptI = ptP ; ptF = ptP + dU2 * vtV ; } // due soluzioni valide ( punto esterno) else { ptI = ptP + dU1 * vtV ; ptF = ptP + dU2 * vtV ; } // Determinazione degli indici i j dei punti ptI e ptF int nIi = Clamp( int( floor( ptI.x / m_dStep)), 0, m_nVNx[0] - 1) ; int nIj = Clamp( int( floor( ptI.y / m_dStep)), 0, m_nVNy[0] - 1) ; int nFi = Clamp( int( floor( ptF.x / m_dStep)), 0, m_nVNx[0] - 1) ; int nFj = Clamp( int( floor( ptF.y / m_dStep)), 0, m_nVNy[0] - 1) ; // Inizializzo distanze dInLength = INFINITO ; dOutLength = - INFINITO ; // Variazioni double dDeltaX = ptF.x - ptI.x ; double dDeltaY = ptF.y - ptI.y ; // se inclinazione da asse X minore di 45 gradi (in assoluto) if ( abs( dDeltaY) <= abs( dDeltaX)) { // mi muovo lungo X (i) int nIncrI = ( nFi >= nIi ? 1 : - 1) ; for ( int i = nIi, j = nIj ; i != nFi + nIncrI ; i += nIncrI) { // Controllo con nuovo i e j corrente (considero il bordo sinistro del dexel) double dU1, dU2 ; if ( IntersLineDexel( 0, ptP, vtV, i, j, dU1, dU2)) { dInLength = min( dInLength, dU1) ; dOutLength = max( dOutLength, dU2) ; } // Mi sposto sul bordo destro del dexel double dMoveX = ( ( i + max( nIncrI, 0)) * m_dStep - ptI.x) ; double dMoveY = dMoveX * dDeltaY / dDeltaX ; double dY = ptI.y + dMoveY ; int OldJ = j ; j = Clamp( int( floor( dY / m_dStep)), 0, m_nVNy[0] - 1) ; // Analisi del dexel if ( j != OldJ) { double dU1, dU2 ; if ( IntersLineDexel( 0, ptP, vtV, i, j, dU1, dU2)) { dInLength = min( dInLength, dU1) ; dOutLength = max( dOutLength, dU2) ; } } } } // altrimenti else { // mi muovo lungo Y (j) int nIncrJ = ( nFj >= nIj ? 1 : - 1) ; for ( int i = nIi, j = nIj ; j != nFj + nIncrJ ; j += nIncrJ) { // Controllo con nuovo j e i corrente (considero il bordo sotto del dexel) double dU1, dU2 ; if ( IntersLineDexel( 0, ptP, vtV, i, j, dU1, dU2)) { dInLength = min( dInLength, dU1) ; dOutLength = max( dOutLength, dU2) ; } // Mi sposto sul bordo sopra del dexel double dMoveY = ( ( j + max( nIncrJ, 0)) * m_dStep - ptI.y) ; double dMoveX = dMoveY * dDeltaX / dDeltaY ; double dX = ptI.x + dMoveX ; int OldI = i ; i = Clamp( int( floor( dX / m_dStep)), 0, m_nVNx[0] - 1) ; // Analisi del dexel if ( i != OldI) { double dU1, dU2 ; if ( IntersLineDexel( 0, ptP, vtV, i, j, dU1, dU2)) { dInLength = min( dInLength, dU1) ; dOutLength = max( dOutLength, dU2) ; } } } } // Se non abbiamo incontrato materiale if ( dInLength > dOutLength - EPS_SMALL) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } // Se parto dall'interno if ( dInLength < - EPS_SMALL) dInLength = - 1 ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag) { // BBox BBox3d b3Box( ORIG, ORIG + vtDiag) ; // lo porto nel riferimento intrinseco dello Zmap b3Box.LocToLoc( frBox, m_MapFrame[0]) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nVNx[0] * m_dStep, m_nVNy[0] * m_dStep, m_dVMaxZ[0])) ; // Se non interferiscono, posso uscire BBox3d b3Int ; if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) return true ; // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nVNx[0] -1) ; int nEnI = Clamp( int( b3Int.GetMax().x / m_dStep), 0, m_nVNx[0] -1) ; int nStJ = Clamp( int( b3Int.GetMin().y / m_dStep), 0, m_nVNy[0] -1) ; int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nVNy[0] -1) ; // Vettore direzione dei dexel nel riferimento del Box Vector3d vtK = Z_AX ; vtK.LocToLoc( m_MapFrame[0], frBox) ; // Riferimento intrinseco dei dexel nel riferimento del box Point3d ptO = ORIG ; ptO.LocToLoc( m_MapFrame[0], frBox) ; Vector3d vtX = X_AX ; vtX.LocToLoc( m_MapFrame[0], frBox) ; Vector3d vtY = Y_AX ; vtY.LocToLoc( m_MapFrame[0], frBox) ; // Ciclo di intersezione dei dexel con il BBox for ( int i = nStI ; i <= nEnI ; ++ i) { for ( int j = nStJ ; j <= nEnJ ; ++ j) { int nPos = j * m_nVNx[0] + i ; int nSize = int( m_TriZValues[0][nPos].size()) ; if ( nSize == 0) continue ; Point3d ptC = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; double dZmin, dZmax ; if ( IntersLineBox( ptC, vtK, ORIG, ORIG + vtDiag, dZmin, dZmax)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 2) { if ( ! ( dZmax < m_TriZValues[0][nPos][nIndex] - EPS_SMALL || dZmin > m_TriZValues[0][nPos][nIndex + 1] + EPS_SMALL)) return false ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& CylFrame, double dL, double dR, Point3d& ptInt1, Point3d& ptInt2) { // NB: L'origine del sistema di riferimento deve essere // nel centro della circonferenza di base e l'asse di simmetria // deve coincidere con l'asse x. // La funzione restituisce true in caso di intersezione, // false altrimenti. Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Trasformazione delle coordinate ptP.ToLoc( CylFrame) ; vtV.ToLoc( CylFrame) ; DBLVECTOR vdCoef(3) ; DBLVECTOR vdRoots ; double dSqRad = dR * dR ; vdCoef[0] = ptP.y * ptP.y + ptP.z * ptP.z - dSqRad ; vdCoef[1] = 2 * ( ptP.y * vtV.y + ptP.z * vtV.z) ; vdCoef[2] = vtV.y * vtV.y + vtV.z * vtV.z ; // Computo radici int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Nessuna soluzione if ( nRoot == 0) { if ( abs( vtV.x) > EPS_ZERO) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; if ( ptInt1.y * ptInt1.y + ptInt1.z * ptInt1.z <= dSqRad && ptInt2.y * ptInt2.y + ptInt2.z * ptInt2.z <= dSqRad) { ptInt1.ToGlob( CylFrame) ; ptInt2.ToGlob( CylFrame) ; return true ; } // Nessuna intersezione else return false ; } // Nessuna intersezione else return false ; } // L'equazione ammette o due soluzioni (eventualmente // coincidenti) oppure nessuna o infinite se la la retta // appartiene alla superficie if ( nRoot == 2) { ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; if ( ptInt1.x > ptInt2.x) swap( ptInt1, ptInt2) ; if ( ptInt1.x < 0 && ptInt2.x >= 0 && ptInt2.x <= dL) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; } else if ( ptInt1.x < 0 && ptInt2.x > dL) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x >= 0 && ptInt2.x <= dL) { ; } else if ( ptInt1.x >= 0 && ptInt1.x < dL && ptInt2.x >= dL) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } // Intersezioni esterne alla regione di interesse // (quella compresa fra 0 e dL) else return false ; // Riporto le coordinate nel sistema di riferimento griglia ptInt1.ToGlob( CylFrame) ; ptInt2.ToGlob( CylFrame) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersZLineCylinder( const Point3d& ptLine, const Point3d& ptBase, const Point3d& ptTop, const Vector3d& vtDir, double dCylR, double& dInfZ, double& dSupZ) { // NB: Le coordinate sono espresse nel sistema griglia // La funzione restituisce true in caso di intersezione, // false altrimenti. double dSqRad = dCylR * dCylR ; // Cilindro verticale if ( AreSamePointXYApprox( ptBase, ptTop)) { // Intersezione if ( SqDistXY( ptLine, ptBase) <= dSqRad) { dInfZ = min( ptBase.z, ptTop.z) ; dSupZ = max( ptBase.z, ptTop.z) ; return true ; } // Non vi è intersezione else return false ; } // Cilindro non verticale else { // Studio delle simmetrie Point3d ptS = ( ptBase.z < ptTop.z ? ptBase : ptTop) ; Point3d ptE = ( ptBase.z < ptTop.z ? ptTop : ptBase) ; Vector3d vtV1 = ptE - ptS ; vtV1.z = 0 ; double dLenXY = vtV1.LenXY() ; double dSZ = ptS.z ; double dEZ = ptE.z ; double dDeltaZ = dEZ - dSZ ; Vector3d vtL( ptLine.x - ptS.x, ptLine.y - ptS.y, 0) ; // vtV1 e vtV2 formano un sistema ortonormale // sul piano e insieme a ptSxy formano un sistema // di riferimento bidimensionale vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; double dLen = ( ptE - ptS).Len() ; // Sono seno e coseno dell'angolo complementare // rispetto a quello formato dal vettore movimento // con il piano, per questo motivo si ha dCos con // dDeltaZ e dSin con dLenXY double dCos = dDeltaZ / dLen ; double dSin = dLenXY / dLen ; // Nuove coordinate piane del punto double dLocX1 = vtL * vtV1 ; double dLocX2 = vtL * vtV2 ; double dSqRoot = sqrt( dSqRad - dLocX2 * dLocX2) ; double dX1_0 = dCos * dSqRoot ; if ( dLocX1 >= - dX1_0 && dLocX1 <= dLenXY + dX1_0 && abs( dLocX2) < dCylR) { // Minimi if ( dLocX1 < dX1_0) { double dDotS = vtDir * ( ptS - ORIG) ; // Qui usiamo ptLine perché servono coordinate griglia dInfZ = ( dDotS - vtDir.x * ptLine.x - vtDir.y * ptLine.y) / vtDir.z ; } else { double dZ0 = - dSin * dSqRoot ; dInfZ = dSZ + dZ0 + ( dLocX1 - dX1_0) * dDeltaZ / dLenXY ; } // Massimi if ( dLocX1 < dLenXY - dX1_0) { double dZ0 = dSin * dSqRoot ; dSupZ = dSZ + dZ0 + ( dLocX1 - dX1_0) * dDeltaZ / dLenXY ; } else { double dDotE = vtDir * ( ptE - ORIG) ; // Qui usiamo ptLine perché servono coordinate griglia dSupZ = ( dDotE - vtDir.x * ptLine.x - vtDir.y * ptLine.y) / vtDir.z ; } return true ; } return false ; } } //---------------------------------------------------------------------------- bool VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& ConusFrame, double dTan, double dl, double dL, Point3d& ptInt1, Point3d& ptInt2) { // NB: L'origine del sistema di riferimento deve essere // nel vertice del cono e l'asse di simmetria deve coincidere // con l'asse x. // La funzione restituisce true in caso di intersezione, // false altrimenti. Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Trasformazione delle coordinate ptP.ToLoc( ConusFrame) ; vtV.ToLoc( ConusFrame) ; DBLVECTOR vdCoef(3) ; DBLVECTOR vdRoots ; double dSqTan = dTan * dTan ; vdCoef[0] = dSqTan * ptP.x * ptP.x - ptP.y * ptP.y - ptP.z * ptP.z ; vdCoef[1] = 2 * ( dSqTan * ptP.x * vtV.x - ptP.y * vtV.y - ptP.z * vtV.z) ; vdCoef[2] = dSqTan * vtV.x * vtV.x - vtV.y * vtV.y - vtV.z * vtV.z ; // Computo radici int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Nessuna soluzione if ( nRoot == 0) return false ; // Una soluzione: la retta iterseca superficie // laterale e un piano if ( nRoot == 1) { ptInt1 = ptP + vdRoots[0] * vtV ; if ( ptInt1.x >= dl && ptInt1.x < dL) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x >= 0 && ptInt1.x < dl) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } // Riporto le coordinate nel sistema di riferimento // griglia ptInt1.ToGlob( ConusFrame) ; ptInt2.ToGlob( ConusFrame) ; } // Due soluzioni: la retta interseca due volte la // superficie laterale else if ( nRoot == 2) { ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; if ( ptInt1.x > ptInt2.x) { swap( ptInt1, ptInt2) ; } if ( ptInt1.x < 0 && ptInt2.x > 0 && ptInt2.x < dl) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x < 0 && ptInt2.x >= dl && ptInt2.x < dL) { ptInt1 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x > 0 && ptInt1.x < dl && ptInt2.x >= dl && ptInt2.x < dL) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x > 0 && ptInt1.x < dl && ptInt2.x >= dL) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptInt1.x >= dl && ptInt1.x < dL && ptInt2.x < dL) { ; } else if ( ptInt1.x >= dl && ptInt1.x < dL && ptInt2.x >= dL) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } // Intersezioni esterne alla regione di interesse // (quella compresa fra dl e dL) else return false ; // Riporto le coordinate nel sistema di riferimento // griglia ptInt1.ToGlob( ConusFrame) ; ptInt2.ToGlob( ConusFrame) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineEllipticalCylinder( const Frame3d & CircFrame, const Vector3d & vtLineDir, const Point3d & ptLineSt, std::vector & ptInters, double dObCoef, double dSqRad, double dL) { // NB: L'origine del sistema di riferimento deve essere // nel centro della circonferenza di base, la cui tralsazione obliqua // genera il cilindro ellittico, e l'asse x deve essere l'asse // di simmetria di tale circonferenza. // La funzione restituisce true in caso di intersezione, // false altrimenti. // NB: Il Parametro dObCoef è il coeffociente angolare della retta movimento // rispetto all'asse x, e dSqRad è il quadrato del raggio della circonferenza. double dSqCoef = dObCoef * dObCoef ; Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Sistema di riferimanto grigia Frame3d GridFrame ; GridFrame.Set( ORIG, X_AX, Y_AX, Z_AX) ; // Trasformazione delle coordinate ptP.LocToLoc( GridFrame, CircFrame) ; vtV.LocToLoc( GridFrame, CircFrame) ; std::vector vdCoef(3) ; std::vector vdRoots ; vdCoef[0] = dSqCoef * ptP.x * ptP.x + ptP.y * ptP.y + ptP.z * ptP.z - 2 * dObCoef * ptP.x * ptP.y - dSqRad ; vdCoef[1] = 2 * ( dSqCoef * vtV.x * ptP.x + vtV.y * ptP.y + vtV.z * ptP.z - dObCoef * ( vtV.x * ptP.y + vtV.y * ptP.x)) ; vdCoef[2] = dSqCoef * vtV.x * vtV.x + vtV.y * vtV.y + vtV.z * vtV.z - 2 * dObCoef * vtV.x * vtV.y ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; Point3d ptR1, ptR2 ; // Nessuna soluzione if ( nRoot == 0) { if ( abs( vtV.x) > EPS_ZERO) { ptR1 = ptP - ( ptP.x / vtV.x) * vtV ; ptR2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; if ( ptR1.y * ptR1.y + ptR1.z * ptR1.z < dSqRad && ptR1.y * ptR1.y + ptR1.z * ptR1.z < dSqRad) { ptR1.LocToLoc( CircFrame, GridFrame) ; ptR2.LocToLoc( CircFrame, GridFrame) ; ptInters.resize(2) ; ptInters[0] = ptR1 ; ptInters[0] = ptR2 ; return true ; } // Nessuna intersezione else return false ; } // Nessuna intersezione else return false ; } // L'equazione ammette o due soluzioni (eventualmente // coincidenti) oppure nessuna o infinite se la la retta // appartiene alla superficie ptInters.resize(2) ; if ( nRoot == 2) { ptR1 = ptP + vdRoots[0] * vtV ; ptR2 = ptP + vdRoots[1] * vtV ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x >= 0 && ptR1.x < dL && ptR2.x > dL) { ptR1 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptR1.x >= 0 && ptR2.x <= dL) { ; } else if ( ptR1.x < 0 && ptR2.x > dL) { ptR1 = ptP - ( ptP.x / vtV.x) * vtV ; ptR2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; } else if ( ptR1.x < 0 && ptR2.x >= 0 && ptR2.x <= dL) { ptR1 = ptP - ( ptP.x / vtV.x) * vtV ; } // Riporto le coordinate nel sistema di riferimento // griglia ptR1.LocToLoc( CircFrame, GridFrame) ; ptR2.LocToLoc( CircFrame, GridFrame) ; ptInters[0] = ptR1 ; ptInters[1] = ptR2 ; } return true ; }