EgtGeomKernel 1.6x2 :

- modifiche a Zmap per tridexel.
This commit is contained in:
Dario Sassi
2016-12-19 14:35:10 +00:00
parent 3c555f6beb
commit 7ee899b0a2
15 changed files with 9168 additions and 9647 deletions
+736
View File
@@ -0,0 +1,736 @@
//----------------------------------------------------------------------------
// 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 <Point3d> & 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 <double> vdCoef(3) ;
std::vector <double> 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 ;
}