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:
DarioS
2022-03-14 09:03:13 +01:00
parent de34cfb7e8
commit f353e65e61
10 changed files with 251 additions and 2241 deletions
+84 -84
View File
@@ -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) ;
}
}