EgtGeomKernel 2.4c1 :
- migliorato calcolo distanza minima tra due linee - eliminate da Trimesh parti inutili - in Trimesh calcolo Loop di una faccia risolto problema di ciclo infinito - in Trimesh aggiunta funzione per eliminare triangoli esattamente sovrapposti.
This commit is contained in:
+84
-84
@@ -18,6 +18,8 @@
|
||||
#include "/EgtDev/Include/EGkGeoConst.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistLineLine::DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1,
|
||||
const Point3d& ptSt2, const Point3d& ptEn2,
|
||||
@@ -57,6 +59,7 @@ DistLineLine::GetSqDist( double& dSqDist)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
|
||||
dSqDist = m_dSqDist ;
|
||||
return true ;
|
||||
}
|
||||
@@ -67,7 +70,10 @@ DistLineLine::GetDist( double& dDist)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
dDist = sqrt( m_dSqDist) ;
|
||||
|
||||
if ( m_dDist < 0)
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -84,55 +90,48 @@ DistLineLine::GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistLineLine::GetParamsAtMinDistPoints( double& dPar1, double& dPar2)
|
||||
DistLineLine::GetPositionsAtMinDistPoints( double& dPos1, double& dPos2)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
dPar1 = m_dPar1 ;
|
||||
dPar2 = m_dPar2 ;
|
||||
dPos1 = m_dPos1 ;
|
||||
dPos2 = m_dPos2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calcola la distanza fra i due elemnti lineari, i punti di minima distanza e
|
||||
// i loro rispettivi parametri.
|
||||
// Se la coppia di punti di minima distanza non è unica ne viene scelta una
|
||||
// in base a comodità di calcolo.
|
||||
// Calcola la distanza fra i due elementi lineari, i punti di minima distanza e le loro posizioni.
|
||||
// Se i due elementi sono paralleli i punti di minimo sono scelti secondo convenienza.
|
||||
void
|
||||
DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1, bool bIsSegment2)
|
||||
{
|
||||
// Caso di elementi lineari paralleli/antiparalleli
|
||||
// Se elementi paralleli o antiparalleli
|
||||
if ( AreSameOrOppositeVectorExact( vtD1, vtD2)) {
|
||||
// Almeno un elemento è una retta
|
||||
if ( ! ( bIsSegment1 && bIsSegment2)) {
|
||||
// Il primo elemento è segmento, quindi deve essere una retta il secondo
|
||||
if ( bIsSegment1) {
|
||||
Vector3d vtStSt = ptSt1 - ptSt2 ;
|
||||
double dLong = vtStSt * vtD2 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD2 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = dLong ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
|
||||
}
|
||||
// Il primo elemento è una retta
|
||||
else {
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dLong = vtStSt * vtD1 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD1 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dPar1 = dLong ;
|
||||
m_dPar2 = 0 ;
|
||||
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 ;
|
||||
}
|
||||
// Se il primo elemento è una retta infinita
|
||||
if ( ! bIsSegment1) {
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dLong = vtStSt * vtD1 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD1 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dPos1 = dLong ;
|
||||
m_dPos2 = 0 ;
|
||||
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 ;
|
||||
}
|
||||
// se altrimenti il secondo elemento è una retta infinita
|
||||
else if ( ! bIsSegment2) {
|
||||
Vector3d vtStSt = ptSt1 - ptSt2 ;
|
||||
double dLong = vtStSt * vtD2 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD2 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = dLong ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
|
||||
}
|
||||
// Entrambi gli elementi sono segmenti
|
||||
// altrimenti entrambi gli elementi sono segmenti
|
||||
else {
|
||||
Point3d ptEn1 = ptSt1 + dLen1 * vtD1 ;
|
||||
Point3d ptEn2 = ptSt2 + dLen2 * vtD2 ;
|
||||
@@ -140,7 +139,7 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
|
||||
Vector3d vtStEn = ptEn2 - ptSt1 ;
|
||||
double dStU = vtStSt * vtD1 ;
|
||||
double dEnU = vtStEn * vtD1 ;
|
||||
// Classifico i punti del segmento segmento in base alla loro
|
||||
// Classifico i punti del secondo segmento in base alla loro
|
||||
// coordinata rispetto all'ordinamento generato dal primo.
|
||||
double dMinPar, dMaxPar ;
|
||||
Point3d ptMinPar, ptMaxPar ;
|
||||
@@ -159,70 +158,71 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
|
||||
// Possibili posizioni reciproche dei segmenti
|
||||
if ( dMinPar > dLen1) {
|
||||
m_dSqDist = SqDist( ptEn1, ptMinPar) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_ptMinDist1 = ptEn1 ;
|
||||
m_ptMinDist2 = ptMinPar ;
|
||||
m_dPar1 = dLen1 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = dLen1 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else if ( dMinPar > 0) {
|
||||
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_ptMinDist1 = ptSt1 + dMinPar * vtD1 ;
|
||||
m_ptMinDist2 = ptMinPar ;
|
||||
m_dPar1 = dMinPar ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = dMinPar ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else if ( dMaxPar > 0) {
|
||||
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + ( ptSt1 - ptSt2) * vtD2 * vtD2 ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else {
|
||||
m_dSqDist = SqDist( ptSt1, ptMaxPar) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptMaxPar ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
// Caso generale
|
||||
Vector3d vtDist0 = ptSt2 - ptSt1 ;
|
||||
double dDist01 = vtDist0 * vtD1 ;
|
||||
double dDist02 = vtDist0 * vtD2 ;
|
||||
double dDotD1D2 = vtD1 * vtD2 ;
|
||||
double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dMin1 = - INFINITO ;
|
||||
double dMax1 = INFINITO ;
|
||||
double dMin2 = - INFINITO ;
|
||||
double dMax2 = INFINITO ;
|
||||
double dSt1On2 = ( ptSt1 - ptSt2) * vtD2 ;
|
||||
double dEn1On2 = ( ptSt1 + dLen1 * vtD1 - ptSt2) * vtD2 ;
|
||||
if ( bIsSegment1) {
|
||||
dMin1 = 0 ;
|
||||
dMax1 = dLen1 ;
|
||||
dMin2 = std::min( dSt1On2, dEn1On2) ;
|
||||
dMax2 = std::max( dSt1On2, dEn1On2) ;
|
||||
else {
|
||||
// Posizioni a distanza minima tra rette illimitate
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dDist01 = vtStSt * vtD1 ;
|
||||
double dDist02 = vtStSt * vtD2 ;
|
||||
double dDotD1D2 = vtD1 * vtD2 ;
|
||||
double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
// Posizioni minime e massime sui segmenti
|
||||
double dMin1 = ( bIsSegment1 ? 0 : -INFINITO) ;
|
||||
double dMax1 = ( bIsSegment1 ? dLen1 : INFINITO) ;
|
||||
double dMin2 = ( bIsSegment2 ? 0 : -INFINITO) ;
|
||||
double dMax2 = ( bIsSegment2 ? dLen2 : INFINITO) ;
|
||||
// Se entrambe le posizioni stanno nei segmenti
|
||||
if ( dT1 >= dMin1 && dT1 <= dMax1 && dT2 >= dMin2 && dT2 <= dMax2) {
|
||||
m_dPos1 = dT1 ;
|
||||
m_dPos2 = dT2 ;
|
||||
}
|
||||
// se altrimenti solo la prima sta nel segmento
|
||||
else if ( dT1 >= dMin1 && dT1 <= dMax1) {
|
||||
m_dPos2 = Clamp( dT2, dMin2, dMax2) ;
|
||||
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
|
||||
}
|
||||
// se altrimenti solo la seconda sta nel segmento
|
||||
else if ( dT2 >= dMin2 && dT2 <= dMax2) {
|
||||
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
|
||||
}
|
||||
// altrimenti nessuna sta nel suo segmento
|
||||
else {
|
||||
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
|
||||
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
|
||||
}
|
||||
m_ptMinDist1 = ptSt1 + m_dPos1 * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 + m_dPos2 * vtD2 ;
|
||||
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
|
||||
}
|
||||
if ( bIsSegment2) {
|
||||
double dSt2On1 = ( ptSt2 - ptSt1) * vtD1 ;
|
||||
double dEn2On1 = ( ptSt2 + dLen2 * vtD2 - ptSt1) * vtD1 ;
|
||||
dMin1 = std::max( dMin1, std::min( dSt2On1, dEn2On1)) ;
|
||||
dMax1 = std::min( dMax1, std::max( dSt2On1, dEn2On1)) ;
|
||||
dMin2 = std::max( dMin2, 0.) ;
|
||||
dMax2 = std::min( dMax2, dLen2) ;
|
||||
}
|
||||
m_dPar1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPar2 = Clamp( dT2, dMin2, dMax2) ;
|
||||
m_ptMinDist1 = ptSt1 + m_dPar1 * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 + m_dPar2 * vtD2 ;
|
||||
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user