EgtGeomKernel :

- tolta da ChainCurves riduzione tolleranza con dimensione pezzi
- aggiunte DistPointTriangle, IntersPlaneTria, IntersPlaneSurfTm
- correzioni a IntersCrvCompoCrvCompo per topologia intersezioni
- completamente riscritta IntersCoplanarLineTria per robustezza topologica.
This commit is contained in:
Dario Sassi
2017-10-21 17:01:23 +00:00
parent 5bcd4bb67d
commit 9770d57793
14 changed files with 909 additions and 340 deletions
-4
View File
@@ -52,10 +52,6 @@ ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
// li inserisco nel PointGrid3d
m_PointGrid.InsertPoint( ptStart, nV) ;
m_PointGrid.InsertPoint( ptEnd, - nV) ;
// verifico il valore di tolleranza rispetto alla distanza tra gli estremi dell'entità (ignoro curve chiuse)
double dDist = Dist( ptStart, ptEnd) ;
if ( dDist > EPS_SMALL && m_dToler > dDist / 2)
m_dToler = max( dDist / 2, EPS_SMALL) ;
return true ;
}
+95
View File
@@ -0,0 +1,95 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2017
//----------------------------------------------------------------------------
// File : DistPointTria.cpp Data : 19.10.17 Versione : 1.8j4
// Contenuto : Implementazione della classe distanza punto da triangolo.
//
//
//
// Modifiche : 19.10.17 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "DistPointLine.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
//----------------------------------------------------------------------------
DistPointTriangle::DistPointTriangle( const Point3d& ptP, const Triangle3d& Tria)
{
if ( &Tria == nullptr || ! Tria.IsValid()) {
// distanza non calcolabile
m_dSqDist = - 1 ;
return ;
}
// eseguo calcoli e determino il quadrato della distanza
Calculate( ptP, Tria) ;
// dichiaro distanza non ancora calcolata
m_dDist = - 1 ;
}
//----------------------------------------------------------------------------
void
DistPointTriangle::Calculate( const Point3d& ptP, const Triangle3d& Tria)
{
// Proiezione del punto sul piano del triangolo
Point3d ptQ = ptP - (( ptP - Tria.GetP( 0)) * Tria.GetN()) * Tria.GetN() ;
// Verifico se il punto proiettato sta nel triangolo
if ( PointInTria( ptQ, Tria) != PTT_OUT) {
m_dSqDist = SqDist( ptP, ptQ) ;
m_ptMinDist = ptQ ;
return ;
}
// Determino la minima distanza dai tre lati
for ( int i = 0 ; i < 3 ; ++ i) {
DistPointLine dstPL( ptQ, Tria.GetP( i), Tria.GetP( ( i + 1) % 3)) ;
double dSqDist ;
if ( dstPL.GetSqDist( dSqDist) && ( m_dSqDist < 0 || dSqDist < m_dSqDist)) {
m_dSqDist = dSqDist ;
dstPL.GetMinDistPoint( m_ptMinDist) ;
}
}
}
//----------------------------------------------------------------------------
bool
DistPointTriangle::GetSqDist( double& dSqDist)
{
if ( m_dSqDist < 0)
return false ;
dSqDist = m_dSqDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointTriangle::GetDist( double& dDist)
{
if ( m_dSqDist < 0)
return false ;
if ( m_dDist < 0)
m_dDist = sqrt( m_dSqDist) ;
dDist = m_dDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointTriangle::GetMinDistPoint( Point3d& ptMinDist)
{
if ( m_dSqDist < 0)
return false ;
ptMinDist = m_ptMinDist ;
return true ;
}
+5
View File
@@ -267,7 +267,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CurveByApprox.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
<ClCompile Include="CurveCompositeOffset.cpp" />
<ClCompile Include="DistPointTria.cpp" />
<ClCompile Include="IntersPlanePlane.cpp" />
<ClCompile Include="IntersPlaneSurfTm.cpp" />
<ClCompile Include="IntersPlaneTria.cpp" />
<ClCompile Include="OffsetCurve.cpp" />
<ClCompile Include="DistPointArc.cpp" />
<ClCompile Include="DistPointCrvAux.cpp" />
@@ -388,6 +391,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EgkCurveLine.h" />
<ClInclude Include="..\Include\EGkCurvePointDiffGeom.h" />
<ClInclude Include="..\Include\EGkDistPointCurve.h" />
<ClInclude Include="..\Include\EGkDistPointTria.h" />
<ClInclude Include="..\Include\EGkDllMain.h" />
<ClInclude Include="..\Include\EGkExtText.h" />
<ClInclude Include="..\Include\EGkFilletChamfer.h" />
@@ -408,6 +412,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkIntersLineSurfTm.h" />
<ClInclude Include="..\Include\EGkIntersLineTria.h" />
<ClInclude Include="..\Include\EGkIntersPlanePlane.h" />
<ClInclude Include="..\Include\EGkIntersPlaneTria.h" />
<ClInclude Include="..\Include\EGkLinePerpTwoCurves.h" />
<ClInclude Include="..\Include\EGkLinePntMinDistCurve.h" />
<ClInclude Include="..\Include\EGkLinePntPerpCurve.h" />
+15
View File
@@ -363,6 +363,15 @@
<ClCompile Include="IntersPlanePlane.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersPlaneTria.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersPlaneSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="DistPointTria.cpp">
<Filter>File di origine\GeoDist</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -791,6 +800,12 @@
<ClInclude Include="..\Include\EGkIntersPlanePlane.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersPlaneTria.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkDistPointTria.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+232 -196
View File
@@ -170,213 +170,249 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
}
// sistemazione di intersezioni coincidenti
// sistemazione di intersezioni coincidenti con ordinamento su prima curva A
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
for ( int j = 0 ; j < m_nNumInters ; ++ j) {
// se i due indici coincidono, passo oltre
if ( i == j)
continue ;
// calcolo sottoindici
int ki = 0 ; // del successivo si prende sempre il primo
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) &&
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) {
// caso DET-NULL -> NULL-DET per prima curva
if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy != ICCT_NULL) {
// per la prima curva tengo i determinati
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
break ;
}
// precedente
int j = i - 1 ;
if ( j < 0) {
if ( bCrvAClosed && m_nNumInters > 1)
j = m_nNumInters - 1 ;
else
continue ;
}
// calcolo sottoindici
int ki = 0 ; // del successivo si prende sempre il primo
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) &&
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) {
// caso DET-NULL -> NULL-DET per prima curva
if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy != ICCT_NULL) {
// per la prima curva tengo i determinati
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// caso NULL-DET -> DET-NULL per prima curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy != ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// per la prima curva tengo i determinati
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
break ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// caso DET-NULL -> NULL-DET per seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy != ICCT_NULL) {
// per la seconda curva tengo i determinati
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
break ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// caso NULL-DET -> DET-NULL per seconda curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy != ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
// per la seconda curva tengo i determinati
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
break ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// caso NULL-NULL per corrente di prima curva
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
EraseCurrentInfo( i, j) ;
break ;
}
// caso NULL-NULL per precedente di prima curva
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-DET -> DET-NULL per prima curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy != ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// per la prima curva tengo i determinati
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-NULL per corrente di prima curva
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
EraseCurrentInfo( i, j) ;
}
// caso NULL-NULL per precedente di prima curva
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
EraseOtherInfo( i, j) ;
}
}
}
// sistemazione di intersezioni coincidenti con ordinamento su seconda curva B
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// precedente
int j = i - 1 ;
if ( j < 0) {
if ( bCrvAClosed && m_nNumInters > 1)
j = m_nNumInters - 1 ;
else
continue ;
}
// calcolo sottoindici
int ki = 0 ; // del successivo si prende sempre il primo
int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap
// verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL)
if ( AreSamePointXYEpsilon( m_Info[j].IciA[kj].ptI, m_Info[i].IciA[ki].ptI, 10 * EPS_SMALL) &&
AreSamePointXYEpsilon( m_Info[j].IciB[kj].ptI, m_Info[i].IciB[ki].ptI, 10 * EPS_SMALL) &&
CompatibleParamA( m_Info[j], m_Info[i], bCrvAClosed, dCrvASpan) &&
CompatibleParamB( m_Info[j], m_Info[i], bCrvBClosed, dCrvBSpan)) {
// caso DET-NULL -> NULL-DET per seconda curva
if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy != ICCT_NULL) {
// per la seconda curva tengo i determinati
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-DET -> DET-NULL per seconda curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy != ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
// per la seconda curva tengo i determinati
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ;
// se entrambi overlap non cancello
if ( m_Info[j].bOverlap && m_Info[i].bOverlap)
continue ;
// cancello un singolo
if ( m_Info[i].bOverlap) {
EraseOtherInfo( i, j) ;
}
else {
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-NULL per corrente di seconda curva
else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
EraseCurrentInfo( i, j) ;
}
// caso NULL-NULL per precedente di seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciB[0].nPrevTy = m_Info[j].IciB[0].nPrevTy ;
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
EraseOtherInfo( i, j) ;
}
}
}
// ripristino ordinamento su prima curva
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterA) ;
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva A e cerco di risolverle per continuità
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se il tipo di accostamento per la curva A non è definito
+4 -4
View File
@@ -162,17 +162,17 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ;
// verifica posizione intersezione su prima linea
int nPos1 = ICurve::PP_NULL ; // fuori
if ( ( m_Info.IciA[0].dU * vtDir1).IsSmall())
if ( abs( m_Info.IciA[0].dU * dLen1XY) < EPS_SMALL)
nPos1 = ICurve::PP_START ; // vicino a inizio
else if ( (( 1 - m_Info.IciA[0].dU) * vtDir1).IsSmall())
else if ( abs(( 1 - m_Info.IciA[0].dU) * dLen1XY) < EPS_SMALL)
nPos1 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
nPos1 = ICurve::PP_MID ; // nell'interno
// verifica posizione intersezione su seconda linea
int nPos2 = ICurve::PP_NULL ; // fuori
if ( ( m_Info.IciB[0].dU * vtDir2).IsSmall())
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
nPos2 = ICurve::PP_START ; // vicino a inizio
else if ( (( 1 - m_Info.IciB[0].dU) * vtDir2).IsSmall())
else if ( abs(( 1 - m_Info.IciB[0].dU) * dLen2XY) < EPS_SMALL)
nPos2 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
nPos2 = ICurve::PP_MID ; // nell'interno
+244 -127
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
// EgalTech 2015-2017
//----------------------------------------------------------------------------
// File : IntersLinePlane.cpp Data : 18.02.15 Versione : 1.6b7
// File : IntersLineTria.cpp Data : 16.10.17 Versione : 1.8j4
// Contenuto : Implementazione della intersezione linea/triangolo.
//
//
@@ -16,19 +16,17 @@
#include "ProjPlane.h"
#include "CurveLine.h"
#include "IntersLineLine.h"
#include "IntersLineTria.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include <array>
//----------------------------------------------------------------------------
static int IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2) ;
using namespace std ;
//----------------------------------------------------------------------------
int
IntersLineTria( const Point3d& ptL1, const Point3d& ptL2, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
{
Vector3d vtL = ptL2 - ptL1 ;
double dLen = vtL.Len() ;
@@ -36,19 +34,19 @@ IntersLineTria( const Point3d& ptL1, const Point3d& ptL2, const Triangle3d& trTr
vtL /= dLen ;
else
vtL = V_NULL ;
return IntersLineTria( ptL1, vtL, dLen, trTria, ptInt, ptInt2) ;
return IntersLineTria( ptL1, vtL, dLen, trTria, ptInt, ptInt2, bFinite) ;
}
//----------------------------------------------------------------------------
int
IntersLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
{
// determino il piano del triangolo
Plane3d plPlane ;
plPlane.Set( trTria.GetP( 0), trTria.GetN()) ;
// calcolo l'intersezione tra il segmento di linea e il piano del triangolo
int nRes = IntersLinePlane( ptL, vtL, dLen, plPlane, ptInt) ;
int nRes = IntersLinePlane( ptL, vtL, dLen, plPlane, ptInt, bFinite) ;
// se non c'è intersezione
if ( nRes == ILPT_NO)
return ILTT_NO ;
@@ -68,134 +66,253 @@ IntersLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Tria
}
// se la linea giace nel piano del triangolo
else {
return IntersCoplanarLineTria( ptL, vtL, dLen, trTria, ptInt, ptInt2) ;
return IntersCoplanarLineTria( ptL, vtL, dLen, trTria, ptInt, ptInt2, bFinite) ;
}
}
//----------------------------------------------------------------------------
int
IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
{
// verifico se il segmento è completamente contenuto nel triangolo
ptInt = ptL ;
ptInt2 = ptL + vtL * dLen ;
int nPTT = PointInTria( ptInt, trTria) ;
int nPTT2 = PointInTria( ptInt2, trTria) ;
if ( ( nPTT == PTT_IN && nPTT2 != PTT_OUT) || ( nPTT != PTT_OUT && nPTT2 == PTT_IN))
return ILTT_SEGM ;
if ( nPTT == PTT_VERT && nPTT2 == PTT_VERT)
return ILTT_SEGM_ON_EDGE ;
if ( ( nPTT == PTT_VERT || nPTT == PTT_EDGE) && ( nPTT2 == PTT_VERT || nPTT2 == PTT_EDGE)) {
Point3d ptMed = Media( ptInt, ptInt2, 0.5) ;
if ( PointInTria( ptMed, trTria) == PTT_IN)
return ILTT_SEGM ;
else
// Normale alla linea giacente nel piano
Vector3d vtN = vtL ^ trTria.GetN() ;
vtN.Normalize() ;
// calcolo le distanze dei vertici del triangolo dalla retta
array< double, 3> vDist ;
for ( int i = 0 ; i < 3 ; ++i)
vDist[i] = ( trTria.GetP( i) - ptL) * vtN ;
// verifico posizione del triangolo rispetto alla retta
array<int, 3> vPos = { 0, 0, 0} ;
int nVertPos = 0 ; int nVertNeg = 0 ;
for ( int i = 0 ; i < 3 ; ++i) {
if ( vDist[i] > EPS_SMALL) {
vPos[i] = 1 ;
++ nVertPos ;
}
else if ( vDist[i] < -EPS_SMALL) {
vPos[i] = -1 ;
++ nVertNeg ;
}
}
// Se il triangolo giace tutto da una parte della retta, nessuna intersezione
if ( nVertPos == 3 || nVertNeg == 3) {
return ILTT_NO ;
}
// Se altrimenti il triangolo giace sulla retta (triangolo schiacciato), sovrapposizione
else if ( nVertPos == 0 && nVertNeg == 0) {
// Determino i vertici estremi sulla retta
double dUmin = ( trTria.GetP( 0) - ptL) * vtL ;
double dUmax = ( trTria.GetP( 1) - ptL) * vtL ;
ptInt = trTria.GetP( 0) ;
ptInt2 = trTria.GetP( 1) ;
if ( dUmin > dUmax) {
swap( dUmin, dUmax) ;
swap( ptInt, ptInt2) ;
}
double dU2 = ( trTria.GetP( 2) - ptL) * vtL ;
if ( dU2 < dUmin)
ptInt = trTria.GetP( 2) ;
else if ( dU2 > dUmax)
ptInt2 = trTria.GetP( 2) ;
// Se linea infinita
if ( ! bFinite) {
return ILTT_SEGM_ON_EDGE ;
}
// se segmento nullo, basta verificare la posizione del punto iniziale
if ( dLen < EPS_SMALL || vtL.IsSmall()) {
switch ( nPTT) {
case PTT_OUT :
return ILTT_NO ;
case PTT_VERT :
return ILTT_VERT ;
case PTT_EDGE :
return ILTT_EDGE ;
default :
return ILTT_IN ;
}
}
// definisco un riferimento coincidente con il piano del triangolo
Frame3d frRef ;
if ( ! frRef.Set( trTria.GetP( 0), trTria.GetN(), ( trTria.GetP( 1) - trTria.GetP( 0))))
return ILTT_NO ;
// esprimo il triangolo e il segmento in questo riferimento
Triangle3d trTriaL = trTria ;
trTriaL.ToLoc( frRef) ;
Point3d ptLL = ptL ;
ptLL.ToLoc( frRef) ;
Vector3d vtLL = vtL ;
vtLL.ToLoc( frRef) ;
// calcolo le intersezioni tra i lati del triangolo e il segmento
CurveLine LineLL ;
LineLL.Set( ptLL, ptLL + vtLL * dLen) ;
int nNumInt = 0 ;
IntCrvCrvInfo IntCCI[3] ;
for ( int i = 0 ; i < 3 ; ++ i) {
CurveLine LineTL ;
LineTL.Set( trTriaL.GetP( i), trTriaL.GetP( ( i + 1) % 3)) ;
IntersLineLine IntLL( LineLL, LineTL) ;
if ( IntLL.GetIntCrvCrvInfo( IntCCI[nNumInt]))
++ nNumInt ;
}
// se nessuna intersezione
if ( nNumInt == 0)
return ILTT_NO ;
// se una sola intersezione
else if ( nNumInt == 1) {
// punto di intersezione
Point3d ptIntL = IntCCI[0].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
// se è l'inizio del segmento ( e il resto del segmento deve essere per forza esterno)
if ( AreSamePointApprox( ptIntL, LineLL.GetStart()))
return ( ( nPTT == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ;
// se è la fine del segmento ( e il resto del segmento deve essere per forza esterno)
else if ( AreSamePointApprox( ptIntL, LineLL.GetEnd()))
return ( ( nPTT2 == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ;
// altrimenti è un punto intermedio
// Altrimenti linea finita
else {
// se l'inizio è nel triangolo
if ( nPTT == PTT_IN) {
ptInt = ptL ;
ptInt2 = ptInt ;
return ILTT_SEGM ;
}
// se altrimenti è la fine nel triangolo
else if ( nPTT2 == PTT_IN) {
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM ;
}
// altrimenti entrambi esterni, è un vertice
else
// se massimo coincide con inizio segmento di retta
if ( abs( dUmax) < EPS_SMALL) {
ptInt = ptInt2 ;
return ILTT_VERT ;
}
}
// se 2 intersezioni
else if ( nNumInt == 2) {
// punti di intersezione
Point3d ptIntL = IntCCI[0].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
Point3d ptInt2L = IntCCI[1].IciA[0].ptI ;
ptInt2 = ptInt2L ;
ptInt2.ToGlob( frRef) ;
// se coincidono, deve essere un vertice
if ( AreSamePointApprox( ptIntL, ptInt2L))
return ILTT_VERT ;
// altrimenti è un tratto
else {
// le ordino secondo il verso positivo della linea
if ( ( ptInt - ptL) * vtL > ( ptInt2 - ptL) * vtL)
std::swap( ptInt, ptInt2) ;
return ILTT_SEGM ;
}
}
// altrimenti 3 intersezioni, una deve coincidere con un lato le altre due sono i suoi vertici
else {
for ( int i = 0 ; i < 3 ; ++ i) {
if ( IntCCI[i].bOverlap) {
// punti di intersezione
Point3d ptIntL = IntCCI[i].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
Point3d ptInt2L = IntCCI[i].IciA[1].ptI ;
ptInt2 = ptInt2L ;
ptInt2.ToGlob( frRef) ;
}
// se minimo coincide con fine segmento di retta
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
return ILTT_VERT ;
}
// se segmento non si sovrappone
else if ( dUmax < 0 || dUmin > dLen) {
return ILTT_NO ;
}
// altrimenti sovrapposizione parziale
else {
if ( dUmin < 0)
ptInt = ptL ;
if ( dUmax > dLen)
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM_ON_EDGE ;
}
}
}
return ILTT_NO ;
}
// se altrimenti due vertici del triangolo giacciono sulla linea
else if ( nVertPos + nVertNeg == 1) {
// Determino i vertici sulla linea
int nCount = 0 ;
for ( int i = 0 ; i < 3 ; ++i) {
if ( vPos[i] == 0) {
if ( nCount == 0)
ptInt = trTria.GetP( i) ;
else
ptInt2 = trTria.GetP( i) ;
nCount ++ ;
}
}
// Ordino i vertici sulla linea
double dUmin = ( ptInt - ptL) * vtL ;
double dUmax = ( ptInt2 - ptL) * vtL ;
if ( dUmin > dUmax) {
swap( dUmin, dUmax) ;
swap( ptInt, ptInt2) ;
}
// Se linea infinita
if ( ! bFinite) {
return ILTT_SEGM_ON_EDGE ;
}
// Altrimenti linea finita
else {
// se massimo coincide con inizio segmento di retta
if ( abs( dUmax) < EPS_SMALL) {
ptInt = ptInt2 ;
return ILTT_VERT ;
}
// se minimo coincide con fine segmento di retta
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
return ILTT_VERT ;
}
// se segmento non si sovrappone
else if ( dUmax < 0 || dUmin > dLen) {
return ILTT_NO ;
}
// altrimenti sovrapposizione parziale
else {
if ( dUmin < 0)
ptInt = ptL ;
if ( dUmax > dLen)
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM_ON_EDGE ;
}
}
}
// se altrimenti un vertice del triangolo giace sulla retta e gli altri due sono dalla stessa parte
else if ( ( nVertPos == 2 && nVertNeg == 0) || ( nVertPos == 0 && nVertNeg == 2)) {
// Determino quale è il vertice sulla linea
for ( int i = 0 ; i < 3 ; ++i) {
if ( vPos[i] == 0) {
ptInt = trTria.GetP( i) ;
break ;
}
}
// Se linea infinita
if ( ! bFinite) {
return ILTT_VERT ;
}
// Altrimenti linea finita
else {
// devo verificare che il vertice stia sul segmento
double dU = ( ptInt - ptL) * vtL ;
if ( dU < -EPS_SMALL || dU > dLen + EPS_SMALL)
return ILTT_NO ;
else
return ILTT_VERT ;
}
}
// se altrimenti un vertice del triangolo giace sulla retta e gli altri due sono da parti opposte
else if ( nVertPos == 1 && nVertNeg == 1) {
// Determino il vertice sulla linea e gli altri due da interpolare
int nP, nM ;
for ( int i = 0 ; i < 3 ; ++i) {
if ( vPos[i] == 0)
ptInt = trTria.GetP( i) ;
else if ( vPos[i] > 0)
nP = i ;
else
nM = i ;
}
// Calcolo l'intersezione con la linea
double dCoeff = abs( vDist[nP]) / ( abs( vDist[nP]) + abs( vDist[nM])) ;
ptInt2 = Media( trTria.GetP( nP), trTria.GetP( nM), dCoeff) ;
// Ordino i vertici sulla linea
double dUmin = ( ptInt - ptL) * vtL ;
double dUmax = ( ptInt2 - ptL) * vtL ;
if ( dUmin > dUmax) {
swap( dUmin, dUmax) ;
swap( ptInt, ptInt2) ;
}
// Se linea infinita
if ( ! bFinite) {
return ILTT_SEGM ;
}
// Altrimenti linea finita
else {
// se massimo coincide con inizio segmento di retta
if ( abs( dUmax) < EPS_SMALL) {
ptInt = ptInt2 ;
return ILTT_EDGE ;
}
// se minimo coincide con fine segmento di retta
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
return ILTT_EDGE ;
}
// se segmento non si sovrappone
else if ( dUmax < 0 || dUmin > dLen) {
return ILTT_NO ;
}
// altrimenti sovrapposizione parziale
else {
if ( dUmin < 0)
ptInt = ptL ;
if ( dUmax > dLen)
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM ;
}
}
}
// altrimenti due vertici giaccio da una parte e uno da quella opposta
else {
// Determino le intersezioni
int nCount = 0 ;
for ( int i = 0 ; i < 3 ; ++ i) {
int j = ( i + 1) % 3 ;
if ( vPos[i] != vPos[j]) {
double dCoeff = abs( vDist[i]) / ( abs( vDist[i]) + abs( vDist[j])) ;
( nCount == 0 ? ptInt : ptInt2) = Media( trTria.GetP( i), trTria.GetP( j), dCoeff) ;
++ nCount ;
}
}
// Ordino i vertici sulla linea
double dUmin = ( ptInt - ptL) * vtL ;
double dUmax = ( ptInt2 - ptL) * vtL ;
if ( dUmin > dUmax) {
swap( dUmin, dUmax) ;
swap( ptInt, ptInt2) ;
}
// Se linea infinita
if ( ! bFinite) {
return ILTT_SEGM ;
}
// Altrimenti linea finita
else {
// se massimo coincide con inizio segmento di retta
if ( abs( dUmax) < EPS_SMALL) {
ptInt = ptInt2 ;
return ILTT_EDGE ;
}
// se minimo coincide con fine segmento di retta
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
return ILTT_EDGE ;
}
// se segmento non si sovrappone
else if ( dUmax < 0 || dUmin > dLen) {
return ILTT_NO ;
}
// altrimenti sovrapposizione parziale
else {
if ( dUmin < 0)
ptInt = ptL ;
if ( dUmax > dLen)
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM ;
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2017
//----------------------------------------------------------------------------
// File : IntersLineTria.cpp Data : 16.10.17 Versione : 1.8j4
// Contenuto : Dichiarazione di funzioni intersezione linea/triangolo.
//
//
//
// Modifiche : 16.10.17 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkIntersLineTria.h"
//----------------------------------------------------------------------------
int IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2, bool bFinite = true) ;
+2 -2
View File
@@ -6,15 +6,15 @@
//
//
//
// Modifiche : 15.12.17 DS Creazione modulo.
// Modifiche : 15.10.17 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
//----------------------------------------------------------------------------
int
+206
View File
@@ -0,0 +1,206 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2017
//----------------------------------------------------------------------------
// File : IntersPlaneSurfTm.cpp Data : 16.10.17 Versione : 1.8j4
// Contenuto : Implementazione della intersezione piano/superficie trimesh.
//
//
//
// Modifiche : 16.10.17 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "IntersLineSurfTm.h"
#include "CurveLine.h"
#include "DistPointLine.h"
#include "HashGrids3d.h"
#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
#include <array>
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di un piano con una superficie TriMesh
//----------------------------------------------------------------------------
bool
IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
{
// verifico piano
if ( &plPlane == nullptr || plPlane.GetVersN().IsSmall())
return false ;
// verifico superficie
if ( &Stm == nullptr || ! Stm.IsValid())
return false ;
// verifico parametri di ritorno
if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr)
return false ;
vPnt.clear() ;
vBpt.clear() ;
vTria.clear() ;
// per ricerca veloce di punti ripetuti
PointGrid3d PtGrid ;
PtGrid.Init( 100) ;
// per ricerca veloce di linee ripetute
HashGrids3d LnGrid ;
LnGrid.SetActivationGrid( true) ;
// per ricerca veloce di triangoli ripetuti
HashGrids3d TrGrid ;
TrGrid.SetActivationGrid( true) ;
// cerco i triangoli intersecati dal piano
Triangle3d Tria ;
int nT = Stm.GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// intersezione tra il piano e il triangolo
Point3d ptInt, ptInt2 ;
int nRes = IntersPlaneTria( plPlane, Tria, ptInt, ptInt2) ;
// se vertice
if ( nRes == IPTT_VERT) {
// verifico se punto già inserito
int nId ;
if ( ! PtGrid.Find( ptInt, 10 * EPS_SMALL, nId)) {
vPnt.emplace_back( ptInt) ;
PtGrid.InsertPoint( ptInt, int( vPnt.size()) - 1) ;
}
}
// se altrimenti segmento
else if ( nRes == IPTT_EDGE || nRes == IPTT_YES) {
// se abbastanza lungo
if ( ! AreSamePointApprox( ptInt, ptInt2)) {
// verifico se già inserito
bool bFound = false ;
BBox3d b3Line( ptInt, ptInt2) ;
INTVECTOR vnIds ;
if ( LnGrid.Find( b3Line, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
int nA = vnIds[i] ;
const Point3d& ptOth = vBpt[nA].first ;
const Point3d& ptOth2 = vBpt[nA].second ;
if ( ( AreSamePointEpsilon( ptInt, ptOth, 10 * EPS_SMALL) &&
AreSamePointEpsilon( ptInt2, ptOth2, 10 * EPS_SMALL)) ||
( AreSamePointEpsilon( ptInt, ptOth2, 10 * EPS_SMALL) &&
AreSamePointEpsilon( ptInt2, ptOth, 10 * EPS_SMALL))) {
bFound = true ;
break ;
}
}
}
// se non inserito, procedo
if ( ! bFound) {
vBpt.emplace_back( ptInt, ptInt2) ;
LnGrid.Add( int( vBpt.size()) - 1, b3Line) ;
LnGrid.Update() ;
}
}
}
// se altrimenti l'intero triangolo
else if ( nRes == IPTT_OVERLAPS) {
// verifico se triangolo già inserito
bool bFound = false ;
BBox3d b3Tria( Tria.GetP( 0), Tria.GetP( 1)) ;
b3Tria.Add( Tria.GetP( 2)) ;
INTVECTOR vnIds ;
if ( TrGrid.Find( b3Tria, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
int nA = vnIds[i] ;
const Triangle3d& trOth = vTria[nA] ;
array< bool, 3> bOth = { false, false, false} ;
for ( int j = 0 ; j < 3 ; ++ j) {
for ( int k = 0 ; k < 3 ; ++ k) {
if ( ! bOth[k])
bOth[k] = AreSamePointEpsilon( Tria.GetP( j), trOth.GetP( k), 10 * EPS_SMALL) ;
}
}
if ( bOth[0] && bOth[1] && bOth[2]) {
bFound = true ;
break ;
}
}
}
// se non inserito, procedo
if ( ! bFound) {
vTria.emplace_back( Tria) ;
TrGrid.Add( int( vTria.size()) - 1, b3Tria) ;
TrGrid.Update() ;
}
}
// passo al prossimo triangolo
nT = Stm.GetNextTriangle( nT, Tria) ;
}
// rimuovo i punti che stanno sui segmenti
for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
BBox3d b3Pnt( vPnt[i]) ;
b3Pnt.Expand( 10 * EPS_SMALL) ;
INTVECTOR vnIds ;
if ( LnGrid.Find( b3Pnt, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
double dSqDist ;
if ( DistPointLine( vPnt[i], vBpt[nA].first, vBpt[nA].second).GetSqDist( dSqDist) && dSqDist < 100 * SQ_EPS_SMALL) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vPnt.erase( vPnt.begin() + i) ;
}
// rimuovo i punti che stanno sui triangoli
for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
BBox3d b3Pnt( vPnt[i]) ;
b3Pnt.Expand( 10 * EPS_SMALL) ;
INTVECTOR vnIds ;
if ( TrGrid.Find( b3Pnt, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
const Triangle3d& trOth = vTria[nA] ;
double dSqDist ;
if ( DistPointTriangle( vPnt[i], trOth).GetSqDist( dSqDist) && dSqDist < 100 * SQ_EPS_SMALL) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vPnt.erase( vPnt.begin() + i) ;
}
// rimuovo i segmenti che stanno sui triangoli
for ( int i = int( vBpt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
Point3d ptStart = vBpt[i].first ;
Point3d ptEnd = vBpt[i].second ;
BBox3d b3Line( ptStart, ptEnd) ;
INTVECTOR vnIds ;
if ( TrGrid.Find( b3Line, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
const Triangle3d& trOth = vTria[nA] ;
Point3d ptInt, ptInt2 ;
if ( IntersLineTria( ptStart, ptEnd, trOth, ptInt, ptInt2) == ILTT_SEGM_ON_EDGE) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vBpt.erase( vBpt.begin() + i) ;
}
return true ;
}
+63
View File
@@ -0,0 +1,63 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2017
//----------------------------------------------------------------------------
// File : IntersPlaneTria.cpp Data : 16.10.17 Versione : 1.8j3
// Contenuto : Implementazione della intersezione piano/triangolo.
//
//
//
// Modifiche : 16.10.17 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersLineTria.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include <array>
using namespace std ;
//----------------------------------------------------------------------------
int
IntersPlaneTria( const Plane3d& plPlane, const Triangle3d& trTria, Point3d& ptInt, Point3d& ptInt2)
{
// calcolo le distanze dei vertici del triangolo dal piano
array< double, 3> vDist ;
for ( int i = 0 ; i < 3 ; ++i)
vDist[i] = ( ( trTria.GetP( i) - ORIG) * plPlane.GetVersN() - plPlane.GetDist()) ;
// verifico posizione del triangolo rispetto al piano
int nVertPos = 0 ; int nVertNeg = 0 ;
for ( auto& dDist : vDist) {
if ( dDist > EPS_SMALL)
++ nVertPos ;
else if ( dDist < -EPS_SMALL)
++ nVertNeg ;
}
// se il triangolo giace nel piano, sovrapposizione
if ( nVertPos == 0 && nVertNeg == 0)
return IPTT_OVERLAPS ;
// se altrimenti il triangolo giace tutto da una parte del piano, nessuna intersezione
else if ( nVertPos == 3 || nVertNeg == 3)
return IPTT_NO ;
// intersezione tra il piano e il piano del triangolo
Plane3d plTria ;
plTria.Set( trTria.GetP( 0), trTria.GetN()) ;
Point3d ptL ; Vector3d vtL ;
if ( IntersPlanePlane( plPlane, plTria, ptL, vtL) != IPPT_YES)
return IPTT_NO ;
// interseco la linea con il triangolo (giace nel suo piano)
int nRes = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria, ptInt, ptInt2, false) ;
switch( nRes) {
case ILTT_NO : return IPTT_NO ;
case ILTT_SEGM : return IPTT_YES ;
case ILTT_SEGM_ON_EDGE : return IPTT_EDGE ;
case ILTT_VERT : return IPTT_VERT ;
case ILTT_EDGE : return IPTT_NO ;
default : return IPTT_NO ;
}
}
+1 -1
View File
@@ -1747,7 +1747,7 @@ static int nIndexVsIndex10[6][2] = { { 60 , 5 },
static int Cases10Plus[6][2][12] = {
/* 195: 0, 1, 6, 7, */ {{ 7, 5, 9, 9, 8, 7, 1, 0, 11, 11, 3, 1 },// 0
/* 195: 0, 1, 6, 7, */ {{ 7, 5, 9, 9, 8, 7, 1, 10, 11, 11, 3, 1 },// 0
{ 2, 4, 4, 7, 5, 9, 8, 1, 10, 11, 3, -1}},
/* 85: 0, 2, 4, 6, */ {{ 0, 4, 1, 4, 5, 1, 3, 2, 6, 3, 6, 7 },// 1
+5 -4
View File
@@ -845,17 +845,18 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
( ! bLeftSide && dCrossXY > 0 && dCros2XY > 0)) {
// calcolo del punto di intersezione tra i segmenti precP-currP e nextP-next2P, allungati al centro
CurveLine Line1, Line2 ;
if ( Line1.Set( precP->first, currP->first) && Line1.ExtendEndByLen( 1000) &&
Line2.Set( nextP->first, nex2P->first) && Line2.ExtendStartByLen( 1000)) {
if ( Line1.Set( precP->first, currP->first) &&
Line2.Set( nextP->first, nex2P->first)) {
// se la normale non coincide con l'asse Z, devo portare le linee nel riferimento OCS di questa
Frame3d frNorm ;
if ( ! vtN.IsZplus() && ! vtN.IsZminus())
frNorm.Set( ORIG, vtN) ;
Line1.ToLoc( frNorm) ;
Line2.ToLoc( frNorm) ;
IntersLineLine IntLL( Line1, Line2) ;
IntersLineLine IntLL( Line1, Line2, false) ;
IntCrvCrvInfo IntInfo ;
if ( IntLL.GetIntCrvCrvInfo( IntInfo) && ! IntInfo.bOverlap) {
if ( IntLL.GetIntCrvCrvInfo( IntInfo) &&
! IntInfo.bOverlap && IntInfo.IciA[0].dU > 1 && IntInfo.IciB[0].dU < 0) {
Point3d ptInt = 0.5 * ( IntInfo.IciA[0].ptI + IntInfo.IciB[0].ptI) ;
ptInt.ToGlob( frNorm) ;
// verifico che distanza dell'intersezione dal segmento currP-nextP sia inferiore a tolleranza corrente
+16 -2
View File
@@ -319,8 +319,9 @@ bool
SurfFlatRegion::MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop)
{
// concateno le curve
double dToler = 5 * EPS_SMALL ;
ChainCurves chainC ;
chainC.Init( false, 5 * EPS_SMALL, int( vpCurve.size())) ;
chainC.Init( false, dToler, int( vpCurve.size())) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++i) {
// recupero i dati della curva necessari al concatenamento e li assegno
Point3d ptStart, ptEnd ;
@@ -342,13 +343,26 @@ SurfFlatRegion::MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop)
// recupero le curve e le inserisco nella nuova curva composita
for ( auto i : vIds) {
// la aggiungo alla curva composta
if ( ! pCrvCompo->AddCurve( vpCurve[i-1], true, 5 * EPS_SMALL))
if ( ! pCrvCompo->AddCurve( vpCurve[i-1], true, dToler))
return false ;
vpCurve[i-1] = nullptr ;
}
// aggiorno il nuovo punto vicino
if ( pCrvCompo->GetCurveCount() > 0)
pCrvCompo->GetEndPoint( ptNearStart) ;
// se lunghezza curva inferiore a 2 volte la tolleranza, la salto
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 2. * dToler)
continue ;
// se curva chiusa entro 2 volte la tolleranza ma considerata aperta, la chiudo bene
Point3d ptStart, ptEnd ;
if ( pCrvCompo->GetStartPoint( ptStart) &&
pCrvCompo->GetEndPoint( ptEnd) &&
AreSamePointEpsilon( ptStart, ptEnd, 2. * dToler) &&
! AreSamePointApprox( ptStart, ptEnd)) {
// porto il punto finale a coincidere esattamente con l'inizio
pCrvCompo->ModifyEnd( ptStart) ;
}
// compatto la nuova curva
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
// inserisco la curva composita nel gruppo destinazione