EgtGeomKernel 1.5g2 :

- aggiunte intersezioni tra linee ed archi
- aggiunte intersezioni tra archi e archi
- aggiunte funzioni di utilità per angoli.
This commit is contained in:
Dario Sassi
2014-07-16 09:08:32 +00:00
parent 19fda49699
commit 56d6307a1c
19 changed files with 1357 additions and 99 deletions
+48
View File
@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : Angle.cpp Data : 14.07.14 Versione : 1.5g2
// Contenuto : Implementazione funzioni per gestione angoli.
//
//
//
// Modifiche : 14.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkAngle.h"
#include "/EgtDev/Include/EGkGeoConst.h"
//----------------------------------------------------------------------------
double
AngleNearAngle( double dAngDeg, double dAngRefDeg)
{
// devo portare l'angolo entro +/- un angolo piatto dal riferimento
while ( dAngDeg > dAngRefDeg + ANG_STRAIGHT + EPS_ANG_ZERO)
dAngDeg -= ANG_FULL ;
while ( dAngDeg < dAngRefDeg - ANG_STRAIGHT - EPS_ANG_ZERO)
dAngDeg += ANG_FULL ;
return dAngDeg ;
}
//----------------------------------------------------------------------------
double
DiffAngle( double dAng1Deg, double dAng2Deg)
{
double dAng1Near2Deg = AngleNearAngle( dAng1Deg, dAng2Deg) ;
return ( dAng1Near2Deg - dAng2Deg) ;
}
//----------------------------------------------------------------------------
double
MediaAngle( double dAng1Deg, double dAng2Deg, double dCoeff)
{
double dAng1Near2Deg = AngleNearAngle( dAng1Deg, dAng2Deg) ;
return ( dAng1Near2Deg * ( 1 - dCoeff) + dAng2Deg * dCoeff) ;
}
+48
View File
@@ -20,6 +20,7 @@
#include "GeoObjFactory.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "/EgtDev/Include/EGkAngle.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <new>
@@ -1255,6 +1256,53 @@ CurveArc::InvertN( void)
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::CalcPointAngle( const Point3d& ptP, double& dAngDeg) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// posizione angolare del punto rispetto al centro a partire dalla direzione start
bool bDet ;
if ( ! m_VtS.GetRotation( ( ptP - m_PtCen), m_VtN, dAngDeg, bDet) || ! bDet)
return false ;
if ( m_dAngCenDeg > 0 && dAngDeg < - EPS_ANG_ZERO)
dAngDeg += ANG_FULL ;
else if ( m_dAngCenDeg < 0 && dAngDeg > EPS_ANG_ZERO)
dAngDeg -= ANG_FULL ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::CalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos) const
{
// calcolo la posizione angolare
double dAngDeg ;
if ( ! CalcPointAngle( ptP, dAngDeg))
return false ;
// calcolo parametro
dU = dAngDeg / m_dAngCenDeg ;
// verifica posizione punto su arco
nPos = PP_NULL ; // fuori
if ( fabs( DiffAngle( dAngDeg, 0) * DEGTORAD * m_dRad) < EPS_SMALL) {
nPos = PP_START ; // vicino a inizio
dU = AngleNearAngle( dAngDeg, 0) / m_dAngCenDeg ;
dU = max( dU, 0.) ;
}
else if ( fabs( DiffAngle( dAngDeg, m_dAngCenDeg) * DEGTORAD * m_dRad) < EPS_SMALL) {
nPos = PP_END ; // vicino a fine
dU = AngleNearAngle( dAngDeg, m_dAngCenDeg) / m_dAngCenDeg ;
dU = min( dU, 1.) ;
}
else if ( dU > 0 && dU < 1)
nPos = PP_MID ; // nell'interno
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ChangeRadius( double dNewRadius)
+2
View File
@@ -124,6 +124,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ return m_dAngCenDeg ; }
virtual double GetDeltaN( void) const
{ return m_dDeltaN ; }
virtual bool CalcPointAngle( const Point3d& ptP, double& dAngDeg) const ;
virtual bool CalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos) const ;
virtual bool InvertN( void) ;
virtual bool ChangeRadius( double dNewRadius) ;
virtual bool ChangeDeltaN( double dNewDeltaN) ;
+27
View File
@@ -726,3 +726,30 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
return ( m_PtStart.ToGlob( frOri) && m_PtStart.ToLoc( frDest) &&
m_PtEnd.ToGlob( frOri) && m_PtEnd.ToLoc( frDest)) ;
}
//----------------------------------------------------------------------------
bool
CurveLine::CalcPointParamPosiz( const Point3d& ptP, bool bOnXY, double& dU, int& nPos) const
{
// vettore linea nel piano XY
Vector3d vtDir = m_PtEnd - m_PtStart ;
if ( bOnXY)
vtDir.z = 0 ;
if ( vtDir.IsSmall())
return false ;
// calcolo parametro
dU = ( ptP - m_PtStart) * vtDir / vtDir.SqLen() ;
// verifica posizione intersezione su linea
nPos = ICurve::PP_NULL ; // fuori
if ( ( dU * vtDir).IsSmall()) {
nPos = ICurve::PP_START ; // vicino a inizio
dU = max( dU, 0.) ;
}
else if ( (( 1 - dU) * vtDir).IsSmall()) {
nPos = ICurve::PP_END ; // vicino a fine
dU = min( dU, 1.) ;
}
else if ( dU > 0 && dU < 1)
nPos = ICurve::PP_MID ; // nell'interno
return true ;
}
+1
View File
@@ -103,6 +103,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
{ return m_PtStart ; }
virtual const Point3d& GetEnd( void) const
{ return m_PtEnd ; }
virtual bool CalcPointParamPosiz( const Point3d& ptP, bool bOnXY, double& dU, int& nPos) const ;
public : // IGeoObjRW
virtual int GetNgeId( void) const ;
+11 -27
View File
@@ -44,44 +44,28 @@ DistPointArc::DistPointArc( const Point3d& ptP, const ICurveArc& arArc)
void
DistPointArc::DistPointCircle( const Point3d& ptP, const ICurveArc& arArc)
{
// vettori ausiliari
Vector3d vtDiff = ptP - arArc.GetCenter() ;
double dDistN = vtDiff * arArc.GetNormVersor() ;
Vector3d vtDiffPlane = vtDiff - dDistN * arArc.GetNormVersor() ;
double dDistPlane = fabs( vtDiffPlane.Len() - arArc.GetRadius()) ;
// calcolo della distanza
if ( fabs( dDistPlane) > EPS_ZERO && fabs( dDistN) > EPS_ZERO)
m_dDist = sqrt( dDistPlane * dDistPlane + dDistN * dDistN) ;
else if ( fabs( dDistPlane) > EPS_ZERO)
m_dDist = dDistPlane ;
else if ( fabs( dDistN) > EPS_ZERO)
m_dDist = fabs( dDistN) ;
else
m_dDist = 0 ;
// calcolo del parametro del punto a minima distanza
if ( vtDiffPlane.Normalize()) {
bool bDet ;
double dAngDeg ;
double dParam ;
Point3d ptMinDist ;
arArc.GetStartVersor().GetRotation( vtDiffPlane, arArc.GetNormVersor(), dAngDeg, bDet) ;
if ( arArc.GetAngCenter() > 0 && dAngDeg < 0)
dAngDeg += 360 ;
else if ( arArc.GetAngCenter() < 0 && dAngDeg > 0)
dAngDeg -= 360 ;
dParam = dAngDeg / arArc.GetAngCenter() ;
// se il punto non sta sul centro dell'arco, posso calcolarne la posizione angolare
double dAngDeg ;
if ( arArc.CalcPointAngle( ptP, dAngDeg)) {
double dParam = dAngDeg / arArc.GetAngCenter() ;
if ( dParam < 0)
dParam = 0 ;
else if ( dParam > 1)
dParam = 1 ;
// calcolo del punto di minima distanza
Point3d ptMinDist ;
arArc.GetPointD1D2( dParam, ICurve::FROM_MINUS, ptMinDist) ;
// calcolo del valore di minima distanza
m_dDist = Dist( ptP, ptMinDist) ;
// salvo i dati
m_Info.push_back( MinDistPCInfo( MDPCI_NORMAL, dParam, ptMinDist)) ;
}
// altrimenti tutti i punti della circonferenza sono a minima distanza
else {
// calcolo del valore di minima distanza
m_dDist = sqrt( SqDist( ptP, arArc.GetCenter()) + arArc.GetRadius() * arArc.GetRadius()) ;
// salvo iniziale e finale, come estremi del range
Point3d ptMinDist ;
// tutti i punti della circonferenza sono a minima distanza salvo iniziale e finale
arArc.GetStartPoint( ptMinDist) ;
m_Info.push_back( MinDistPCInfo( MDPCI_START_CONT, 0, ptMinDist)) ;
arArc.GetEndPoint( ptMinDist) ;
BIN
View File
Binary file not shown.
+6
View File
@@ -227,6 +227,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Angle.cpp" />
<ClCompile Include="ArcXxTgArc.cpp" />
<ClCompile Include="Attribs.cpp" />
<ClCompile Include="BBox3d.cpp" />
@@ -258,8 +259,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="GeoObj.cpp" />
<ClCompile Include="GeoPoint3d.cpp" />
<ClCompile Include="GeoVector3d.cpp" />
<ClCompile Include="IntersArcArc.cpp" />
<ClCompile Include="IntersCrvCompoCrvCompo.cpp" />
<ClCompile Include="IntersCurveCurve.cpp" />
<ClCompile Include="IntersLineArc.cpp" />
<ClCompile Include="IntersLineLine.cpp" />
<ClCompile Include="IterManager.cpp" />
<ClCompile Include="LinePntTgCurve.cpp" />
@@ -287,6 +290,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="NgeWriter.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Include\EGkAngle.h" />
<ClInclude Include="..\Include\EGkArcXxTgArc.h" />
<ClInclude Include="..\Include\EGkBBox3d.h" />
<ClInclude Include="..\Include\EGkColor.h" />
@@ -363,7 +367,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="GeoPoint3d.h" />
<ClInclude Include="GeoVector3d.h" />
<ClInclude Include="IdManager.h" />
<ClInclude Include="IntersArcArc.h" />
<ClInclude Include="IntersCrvCompoCrvCompo.h" />
<ClInclude Include="IntersLineArc.h" />
<ClInclude Include="IntersLineLine.h" />
<ClInclude Include="IterManager.h" />
<ClInclude Include="LinePntTgCurve.h" />
+18
View File
@@ -198,6 +198,15 @@
<ClCompile Include="IntersCrvCompoCrvCompo.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersLineArc.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersArcArc.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="Angle.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -485,6 +494,15 @@
<ClInclude Include="IntersCrvCompoCrvCompo.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="IntersLineArc.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="IntersArcArc.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkAngle.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+16 -6
View File
@@ -1831,8 +1831,8 @@ GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams, bool bEndOrStart)
bool
GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart)
{
// 3 parametri : IdSou, IdDest, IdParent
if ( vsParams.size() != 3)
// 1 o 3 parametri : IdSou[, IdDest, IdParent]
if ( vsParams.size() != 1 && vsParams.size() != 3)
return false ;
// recupero la curva composita e il suo riferimento
int nIdCCompo = GetIdParam( vsParams[0]) ;
@@ -1843,7 +1843,10 @@ GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart
if ( ! m_pGDB->GetGlobFrame( nIdCCompo, frSou))
return false ;
// estraggo la opportuna entità
ICurve* pCrv = pCrvCompo->RemoveFirstOrLastCurve( bEndOrStart) ;
PtrOwner<ICurve> pCrv( pCrvCompo->RemoveFirstOrLastCurve( bEndOrStart)) ;
// se 1 solo parametro -> cancellazione
if ( vsParams.size() == 1)
return true ;
// recupero il riferimento del gruppo destinazione
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frDest))
@@ -1852,7 +1855,7 @@ GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart
if ( ! AreSameFrame( frSou, frDest))
pCrv->LocToLoc( frSou, frDest) ;
// inserisco la curva estratta nel DB
return AddGeoObj( vsParams[1], vsParams[2], pCrv) ;
return AddGeoObj( vsParams[1], vsParams[2], ::Release( pCrv)) ;
}
//----------------------------------------------------------------------------
@@ -3162,6 +3165,13 @@ GdbExecutor::GetPointWParam( const string& sParam, const Frame3d& frPnt, Point3d
FromString( vsParams[2], ptP.z) &&
FromString( vsParams[3], dW)) ;
}
// se 3 parti, sono 2 coordinate e un peso
else if ( vsParams.size() == 3) {
ptP.z = 0 ;
return ( FromString( vsParams[0], ptP.x) &&
FromString( vsParams[1], ptP.y) &&
FromString( vsParams[2], dW)) ;
}
// se 2 parti, nome di punto predefinito, punto notevole o già nel DB e un peso
else if ( vsParams.size() == 2) {
// recupero il punto
@@ -4594,12 +4604,12 @@ GdbExecutor::SplitCurveByClass( const STRVECTOR& vsParams)
if ( nIdGrp[nGrp] < GDB_ID_ROOT)
continue ;
// se curva praticamente nulla, vado oltre
if ( fabs( ccClass[i].dParS - ccClass[i].dParE) < 10 * EPS_PARAM)
if ( fabs( ccClass[i].dParE - ccClass[i].dParS) < 10 * EPS_PARAM)
continue ;
// copio la parte di curva che interessa e la porto nel riferimento del gruppo
PtrOwner<ICurve> pSplit( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ;
if ( ! ::IsValid( pSplit))
return false ;
continue ;
pSplit->LocToLoc( frCrv, frGrp[nGrp]) ;
// la inserisco nel gruppo
if ( m_pGDB->AddGeoObj( GDB_ID_NULL, nIdGrp[nGrp], ::Release( pSplit)) == GDB_ID_NULL)
+534
View File
@@ -0,0 +1,534 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : IntersArcArc.cpp Data : 10.07.14 Versione : 1.5g2
// Contenuto : Implementazione della classe intersezione arco/arco.
//
//
//
// Modifiche : 10.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersArcArc.h"
using namespace std ;
//----------------------------------------------------------------------------
IntersArcArc::IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2)
{
// Le intersezioni sono calcolate nel piano XY locale.
// nessuna intersezione trovata
m_bOverlaps = false ;
m_nNumInters = 0 ;
// verifico validità archi
if ( ! Arc1.IsValid() || ! Arc2.IsValid())
return ;
// verifico che l'angolo al centro non superi il giro
if ( fabs( Arc1.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO ||
fabs( Arc2.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO)
return ;
// ne faccio una copia
m_Arc1.CopyFrom( &Arc1) ;
m_Arc2.CopyFrom( &Arc2) ;
// gli archi devono avere il piano coincidente con XY
if ( ! m_Arc1.GetNormVersor().IsZplus() && ! m_Arc1.GetNormVersor().IsZminus())
return ;
if ( ! m_Arc2.GetNormVersor().IsZplus() && ! m_Arc2.GetNormVersor().IsZminus())
return ;
// !!! Gestire gli archi proiettati come ellissi
// verifico sovrapposizione box
BBox3d boxArc1 ;
if ( ! m_Arc1.GetLocalBBox( boxArc1))
return ;
BBox3d boxArc2 ;
if ( ! m_Arc2.GetLocalBBox( boxArc2))
return ;
if ( ! boxArc1.OverlapsXY( boxArc2))
return ;
// versore e distanza tra i centri
Vector3d vtDir = ( m_Arc2.GetCenter() - m_Arc1.GetCenter()) ;
vtDir.z = 0 ;
double dDist = vtDir.LenXY() ;
vtDir /= dDist ;
// cerchi esterni -> nessuna intersezione
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_SMALL)
return ;
// cerchi interni -> nessuna intersezione
if ( dDist < fabs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_SMALL)
return ;
// cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi
if ( dDist < EPS_SMALL && fabs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_SMALL) {
// coefficiente da parametro dell'arco 1 a lunghezza
double dU2L = fabs( m_Arc1.GetAngCenter()) * DEGTORAD * m_Arc1.GetRadius() ;
// determino se sono equiversi o controversi
bool bEqVers = (( m_Arc1.GetAngCenter() * m_Arc1.GetNormVersor().z *
m_Arc2.GetAngCenter() * m_Arc2.GetNormVersor().z) > 0) ;
// calcolo degli estremi degli archi
Point3d ptS1, ptE1 ;
if ( ! m_Arc1.GetStartPoint( ptS1) || ! m_Arc1.GetEndPoint( ptE1))
return ;
Point3d ptS2, ptE2 ;
if ( ! m_Arc2.GetStartPoint( ptS2) || ! m_Arc2.GetEndPoint( ptE2))
return ;
// calcolo del parametro di inizio dell'arco 2 nel riferimento dell'arco 1
double dUS2 ;
int nPosS2 ;
if ( ! m_Arc1.CalcPointParamPosiz( ptS2, dUS2, nPosS2))
return ;
// calcolo dell'ampiezza parametrica dell'arco 2 nel riferimento dell'arco 1
double dDeltaU2 = fabs( m_Arc2.GetAngCenter() / m_Arc1.GetAngCenter()) * ( bEqVers ? 1 : -1) ;
// calcolo dell'ampiezza parametrica di un giro nel riferimento dell'arco 1
double dTurnU = fabs( ANG_FULL / m_Arc1.GetAngCenter()) ;
// determinazione del minimo e massimo parametro dell'arco 2 nel riferimento dell'arco 1
double dU2min = dUS2 ;
double dU2max = dUS2 + dDeltaU2 ;
if ( dU2min > dU2max)
swap( dU2min, dU2max) ;
// se il minimo è negativo, aggiungo un giro
if ( dU2min * dU2L < - EPS_SMALL) {
dU2min += dTurnU ;
dU2max += dTurnU ;
}
// se il minimo di 2 coincide con il massimo di 1 nel primo giro -> un punto estremo
if ( fabs( 1 - dU2min) * dU2L < EPS_SMALL) {
m_Info[0].IciA[0].dU = 1 ;
m_Info[0].IciB[0].dU = ( bEqVers ? 0 : 1) ;
m_Info[0].IciA[0].ptI = ptE1 ;
m_Info[0].IciB[0].ptI = ( bEqVers ? ptS2 : ptE2) ;
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
}
// se invece è minore -> una sovrapposizione
else if ( dU2min < 1) {
// inizio dell'intervallo
m_Info[0].IciA[0].dU = dU2min ;
m_Info[0].IciB[0].dU = ( bEqVers ? 0 : 1) ;
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Info[0].IciB[0].ptI = ( bEqVers ? ptS2 : ptE2) ;
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_ON ;
if ( bEqVers) {
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_ON ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_ON ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
}
// fine dell'intervallo
if ( dU2max < 1) {
m_Info[0].IciA[1].dU = dU2max ;
m_Info[0].IciB[1].dU = ( bEqVers ? 1 : 0) ;
}
else {
m_Info[0].IciA[1].dU = 1 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptE1, m_Info[0].IciB[1].dU, nPos) ;
}
m_Arc1.GetPointD1D2( m_Info[0].IciA[1].dU, ICurve::FROM_MINUS, m_Info[0].IciA[1].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[1].dU, ICurve::FROM_MINUS, m_Info[0].IciB[1].ptI) ;
m_Info[0].IciA[1].nPrevTy = ICCT_ON ;
m_Info[0].IciA[1].nNextTy = ICCT_NULL ;
if ( bEqVers) {
m_Info[0].IciB[1].nPrevTy = ICCT_ON ;
m_Info[0].IciB[1].nNextTy = ICCT_NULL ;
}
else {
m_Info[0].IciB[1].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[1].nNextTy = ICCT_ON ;
}
// dati generali
m_Info[0].bOverlap = true ;
m_Info[0].bCBOverEq = bEqVers ;
m_bOverlaps = true ;
m_nNumInters = 1 ;
}
// se il massimo di 2 coincide con il minimo di 1 nel secondo giro e 1 non completo -> un punto estremo
if ( fabs( dTurnU - dU2max) * dU2L < EPS_SMALL && dTurnU < 1 - EPS_PARAM) {
m_Info[m_nNumInters].IciA[0].dU = 0 ;
m_Info[m_nNumInters].IciB[0].dU = ( bEqVers ? 1 : 0) ;
m_Info[m_nNumInters].IciA[0].ptI = ptS1 ;
m_Info[m_nNumInters].IciB[0].ptI = ( bEqVers ? ptE2 : ptS2) ;
m_Info[m_nNumInters].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciA[0].nNextTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_NULL ;
m_Info[m_nNumInters].bOverlap = false ;
++ m_nNumInters ;
}
// se invece è maggiore -> una sovrapposizione
else if ( dU2max > dTurnU) {
// inizio dell'intervallo
m_Info[m_nNumInters].IciA[0].dU = 0 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptS1, m_Info[m_nNumInters].IciB[0].dU, nPos) ;
m_Info[m_nNumInters].IciA[0].ptI = ptS1 ;
m_Arc2.GetPointD1D2( m_Info[m_nNumInters].IciB[0].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciB[0].ptI) ;
m_Info[m_nNumInters].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciA[0].nNextTy = ICCT_ON ;
if ( bEqVers) {
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_ON ;
}
else {
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_NULL ;
}
// fine dell'intervallo
if ( dU2max - dTurnU < 1) {
m_Info[m_nNumInters].IciA[1].dU = dU2max - dTurnU ;
m_Info[m_nNumInters].IciB[1].dU = ( bEqVers ? 1 : 0) ;
}
else {
m_Info[m_nNumInters].IciA[1].dU = 1 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptE1, m_Info[m_nNumInters].IciB[1].dU, nPos) ;
}
m_Arc1.GetPointD1D2( m_Info[m_nNumInters].IciA[1].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciA[1].ptI) ;
m_Arc2.GetPointD1D2( m_Info[m_nNumInters].IciB[1].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciB[1].ptI) ;
m_Info[m_nNumInters].IciA[1].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciA[1].nNextTy = ICCT_NULL ;
if ( bEqVers) {
m_Info[m_nNumInters].IciB[1].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciB[1].nNextTy = ICCT_NULL ;
}
else {
m_Info[m_nNumInters].IciB[1].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[1].nNextTy = ICCT_ON ;
}
// dati generali
m_Info[m_nNumInters].bOverlap = true ;
m_Info[m_nNumInters].bCBOverEq = bEqVers ;
m_bOverlaps = true ;
++ m_nNumInters ;
}
// se due intersezioni, le ordino in senso crescente del parametro U della prima curva
if ( m_nNumInters == 2) {
if ( m_Info[0].IciA[0].dU > m_Info[1].IciA[0].dU)
swap( m_Info[0], m_Info[1]) ;
}
return ;
}
// cerchi tangenti esterni -> una intersezione
if ( fabs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) {
// calcolo il punto di intersezione
Point3d ptInt = m_Arc1.GetCenter() + vtDir * m_Arc1.GetRadius() ;
// posizione parametrica dell'intersezione sul primo arco
int nPos1 ;
if ( ! m_Arc1.CalcPointParamPosiz( ptInt, m_Info[0].IciA[0].dU, nPos1))
return ;
// posizione parametrica dell'intersezione sul secondo arco
int nPos2 ;
if ( ! m_Arc2.CalcPointParamPosiz( ptInt, m_Info[0].IciB[0].dU, nPos2))
return ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return ;
// calcolo i punti sui due archi (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
// calcolo dati ausiliari
bool bCCW1 = (( m_Arc1.GetAngCenter() > 0 && m_Arc1.GetNormVersor().IsZplus()) ||
( m_Arc1.GetAngCenter() < 0 && m_Arc1.GetNormVersor().IsZminus())) ;
bool bCCW2 = (( m_Arc2.GetAngCenter() > 0 && m_Arc2.GetNormVersor().IsZplus()) ||
( m_Arc2.GetAngCenter() < 0 && m_Arc2.GetNormVersor().IsZminus())) ;
// calcolo tipo di intersezione
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_START) {
if ( bCCW2)
m_Info[0].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_END) {
if ( bCCW2)
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 NULL + NULL
if ( bCCW1)
m_Info[0].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_END) {
// curva 1 NULL + NULL
if ( bCCW1)
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( bCCW2) {
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciA[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciA[0].nNextTy = ICCT_IN ;
}
if ( bCCW1) {
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciB[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciB[0].nNextTy = ICCT_IN ;
}
}
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
return ;
}
// cerchi tangenti interni -> una intersezione
if ( fabs( dDist - fabs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) {
// determino quale dei due contiene l'altro
bool bBiggest1 = ( m_Arc1.GetRadius() > m_Arc2.GetRadius()) ;
// calcolo il punto di intersezione
Point3d ptInt = m_Arc1.GetCenter() + ( bBiggest1 ? vtDir : - vtDir) * m_Arc1.GetRadius() ;
// posizione parametrica dell'intersezione sul primo arco
int nPos1 ;
if ( ! m_Arc1.CalcPointParamPosiz( ptInt, m_Info[0].IciA[0].dU, nPos1))
return ;
// posizione parametrica dell'intersezione sul secondo arco
int nPos2 ;
if ( ! m_Arc2.CalcPointParamPosiz( ptInt, m_Info[0].IciB[0].dU, nPos2))
return ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return ;
// calcolo i punti sui due archi (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
// calcolo dati ausiliari
bool bCCW1 = (( m_Arc1.GetAngCenter() > 0 && m_Arc1.GetNormVersor().IsZplus()) ||
( m_Arc1.GetAngCenter() < 0 && m_Arc1.GetNormVersor().IsZminus())) ;
bool bCCW2 = (( m_Arc2.GetAngCenter() > 0 && m_Arc2.GetNormVersor().IsZplus()) ||
( m_Arc2.GetAngCenter() < 0 && m_Arc2.GetNormVersor().IsZminus())) ;
// calcolo tipo di intersezione
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_START) {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2))
m_Info[0].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_END) {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2))
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 NULL + NULL
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1))
m_Info[0].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_END) {
// curva 1 NULL + NULL
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1))
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2)) {
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciA[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciA[0].nNextTy = ICCT_IN ;
}
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1)) {
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciB[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciB[0].nNextTy = ICCT_IN ;
}
}
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
return ;
}
// due intersezioni
double dA = ( m_Arc1.GetRadius() * m_Arc1.GetRadius() - m_Arc2.GetRadius() * m_Arc2.GetRadius() +
dDist * dDist) / ( 2 * dDist) ;
double dH = sqrt( m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA) ;
Point3d ptRef = m_Arc1.GetCenter() + dA * vtDir ;
Vector3d vtDelta = dH * vtDir ;
vtDelta.Rotate( Z_AX, 0, 1) ;
int nPos1, nPos2 ;
// ---> prima intersezione
// determinazione geometrica e topologica dell'intersezione tra le due curve
if ( CalcSecIntersGeomData( 0, ptRef + vtDelta, nPos1, nPos2) &&
CalcSecIntersTopolData( 0, nPos1, nPos2)) {
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
++ m_nNumInters ;
}
// ---> seconda intersezione
// determinazione geometrica e topologica dell'intersezione tra le due curve
if ( CalcSecIntersGeomData( m_nNumInters, ptRef - vtDelta, nPos1, nPos2) &&
CalcSecIntersTopolData( m_nNumInters, nPos1, nPos2)) {
// aggiorno dati generali di intersezione
m_Info[m_nNumInters].bOverlap = false ;
++ m_nNumInters ;
}
// se due intersezioni, le ordino in senso crescente del parametro U della prima curva
if ( m_nNumInters == 2) {
if ( m_Info[0].IciA[0].dU > m_Info[1].IciA[0].dU)
swap( m_Info[0], m_Info[1]) ;
}
}
//----------------------------------------------------------------------------
bool
IntersArcArc::CalcSecIntersGeomData( int nInt, const Point3d& ptInt, int& nPos1, int& nPos2)
{
// posizione parametrica dell'intersezione sul primo arco
if ( ! m_Arc1.CalcPointParamPosiz( ptInt, m_Info[nInt].IciA[0].dU, nPos1))
return false ;
// posizione parametrica dell'intersezione sul secondo arco
if ( ! m_Arc2.CalcPointParamPosiz( ptInt, m_Info[nInt].IciB[0].dU, nPos2))
return false ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return false ;
// calcolo i punti sulle due curve (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[nInt].IciA[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciB[0].ptI) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersArcArc::CalcSecIntersTopolData( int nInt, int nPos1, int nPos2)
{
// calcolo dati ausiliari
Point3d ptInt1, ptInt2 ;
Vector3d vtDir1, vtDir2 ;
m_Arc1.GetPointD1D2( m_Info[nInt].IciA[0].dU, ICurve::FROM_MINUS, ptInt1, &vtDir1) ;
m_Arc2.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, ptInt2, &vtDir2) ;
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
// calcolo tipo di intersezione
m_Info[nInt].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciA[0].nNextTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_START) {
if ( dCrossXY > 0)
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_END) {
if ( dCrossXY < 0)
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 NULL + NULL
if ( - dCrossXY > 0)
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_END) {
// curva 1 NULL + NULL
if ( - dCrossXY < 0)
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( CrossXY( ( ( ptInt1 - vtDir1) - ( ptInt2 - vtDir2)), vtDir2) > 0) {
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ;
}
else {
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ;
}
if ( CrossXY( ( ( ptInt2 - vtDir2) - ( ptInt1 - vtDir1)), vtDir1) > 0) {
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ;
}
else {
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ;
}
}
return true ;
}
+56
View File
@@ -0,0 +1,56 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : IntersArcArc.h Data : 10.07.14 Versione : 1.5g2
// Contenuto : Dichiarazione della classe intersezione arco/arco.
//
//
//
// Modifiche : 10.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkIntersCurveCurve.h"
#include "CurveArc.h"
//-----------------------------------------------------------------------------
class IntersArcArc
{
friend class IntersCurveCurve ;
public :
IntersArcArc( const ICurveArc& Arc1, const ICurveArc& Arc2) ;
public :
bool GetOverlaps( void)
{ return false ; }
int GetNumInters( void)
{ return m_nNumInters ; }
bool GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
{ if ( nInd < 0 || nInd >= m_nNumInters)
return false ;
aInfo = m_Info[nInd] ;
return true ; }
private :
IntersArcArc( void) ;
bool CalcSecIntersGeomData( int nInt, const Point3d& ptInt, int& nPos1, int& nPos2) ;
bool CalcSecIntersTopolData( int nInt, int nPos1, int nPos2) ;
bool CalcOverlapData( int nInt, bool bEqVers, const Point3d& ptS1, const Point3d& ptE1,
int dUS1, int dUE1, const Point3d& ptS2, const Point3d& ptE2) ;
private :
static const int MAX_INTERS = 2 ;
private :
CurveArc m_Arc1 ;
CurveArc m_Arc2 ;
bool m_bOverlaps ;
int m_nNumInters ;
IntCrvCrvInfo m_Info[MAX_INTERS] ;
} ;
+75 -16
View File
@@ -30,6 +30,7 @@ static bool CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nS
const ICurve& CurveB, double dUB, int& nType) ;
static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
const ICurve& CurveB, double dUB1, double dUB2, int& nType) ;
static bool MoveParamToAvoidTg( double& dU, ICurve::Side nSide, const ICurve& Curve) ;
//----------------------------------------------------------------------------
IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
@@ -645,23 +646,27 @@ CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
const ICurve& CurveB, double dUB, int& nType)
{
// devo studiare un intorno dell'intersezione
// spostandomi leggermente per evitare eventuali problemi di tangenza
Point3d ptP ;
// direzione di arrivo (FROM_MINUS) o partenza (FROM_PLUS) curva A
Vector3d vtADir ;
if ( ! CurveA.IsValidParam( dUA, nSideA) ||
! CurveA.GetPointTang( dUA, nSideA, ptP, vtADir))
double dUAm = dUA ;
if ( ! MoveParamToAvoidTg( dUAm, nSideA, CurveA) ||
! CurveA.GetPointTang( dUAm, nSideA, ptP, vtADir))
return false ;
if ( nSideA == ICurve::FROM_MINUS)
vtADir *= - 1 ;
// direzioni di arrivo (prev) e partenza (next) curva B
Vector3d vtBpDir ;
if ( ! CurveB.IsValidParam( dUB, ICurve::FROM_MINUS) ||
! CurveB.GetPointTang( dUB, ICurve::FROM_MINUS, ptP, vtBpDir))
double dUBp = dUB ;
if ( ! MoveParamToAvoidTg( dUBp, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUBp, ICurve::FROM_MINUS, ptP, vtBpDir))
return false ;
vtBpDir *= - 1 ;
Vector3d vtBnDir ;
if ( ! CurveB.IsValidParam( dUB, ICurve::FROM_PLUS) ||
! CurveB.GetPointTang( dUB, ICurve::FROM_PLUS, ptP, vtBnDir))
double dUBn = dUB ;
if ( ! MoveParamToAvoidTg( dUBn, ICurve::FROM_PLUS, CurveB) ||
! CurveB.GetPointTang( dUBn, ICurve::FROM_PLUS, ptP, vtBnDir))
return false ;
// angolo del versore DirA rispetto a DirBn
double dAngADeg ;
@@ -692,30 +697,35 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
Point3d ptP ;
// direzione di arrivo (FROM_MINUS) o partenza (FROM_PLUS) curva A
Vector3d vtADir ;
if ( ! CurveA.IsValidParam( dUA, nSideA) ||
! CurveA.GetPointTang( dUA, nSideA, ptP, vtADir))
double dUAm = dUA ;
if ( ! MoveParamToAvoidTg( dUAm, nSideA, CurveA) ||
! CurveA.GetPointTang( dUAm, nSideA, ptP, vtADir))
return false ;
if ( nSideA == ICurve::FROM_MINUS)
vtADir *= - 1 ;
// direzioni di arrivo (prev) e partenza (next) curva B (P1)
Vector3d vtB1pDir ;
if ( ! CurveB.IsValidParam( dUB1, ICurve::FROM_MINUS) ||
! CurveB.GetPointTang( dUB1, ICurve::FROM_MINUS, ptP, vtB1pDir))
double dUB1p = dUB1 ;
if ( ! MoveParamToAvoidTg( dUB1p, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUB1p, ICurve::FROM_MINUS, ptP, vtB1pDir))
return false ;
vtB1pDir *= - 1 ;
Vector3d vtB1nDir ;
if ( ! CurveB.IsValidParam( dUB1, ICurve::FROM_PLUS) ||
! CurveB.GetPointTang( dUB1, ICurve::FROM_PLUS, ptP, vtB1nDir))
double dUB1n = dUB1 ;
if ( ! MoveParamToAvoidTg( dUB1n, ICurve::FROM_PLUS, CurveB) ||
! CurveB.GetPointTang( dUB1n, ICurve::FROM_PLUS, ptP, vtB1nDir))
return false ;
// direzioni di arrivo (prev) e partenza (next) curva B (P2)
Vector3d vtB2pDir ;
if ( ! CurveB.IsValidParam( dUB2, ICurve::FROM_MINUS) ||
! CurveB.GetPointTang( dUB2, ICurve::FROM_MINUS, ptP, vtB2pDir))
double dUB2p = dUB2 ;
if ( ! MoveParamToAvoidTg( dUB2p, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUB2p, ICurve::FROM_MINUS, ptP, vtB2pDir))
return false ;
vtB2pDir *= - 1 ;
Vector3d vtB2nDir ;
if ( ! CurveB.IsValidParam( dUB2, ICurve::FROM_PLUS) ||
! CurveB.GetPointTang( dUB2, ICurve::FROM_PLUS, ptP, vtB2nDir))
double dUB2n = dUB2 ;
if ( ! MoveParamToAvoidTg( dUB2n, ICurve::FROM_PLUS, CurveB) ||
! CurveB.GetPointTang( dUB2n, ICurve::FROM_PLUS, ptP, vtB2nDir))
return false ;
// angolo del versore DirA rispetto a DirB1n
double dAngADeg ;
@@ -751,3 +761,52 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
nType = ICCT_OUT ;
return true ;
}
//----------------------------------------------------------------------------
static bool
MoveParamToAvoidTg( double& dU, ICurve::Side nSide, const ICurve& Curve)
{
// verifico che il parametro sia accettabile
if ( ! Curve.IsValidParam( dU, nSide))
return false ;
// determino un incremento piccolo ma valido del parametro U
double dDeltaU = 1000 * EPS_PARAM ;
Point3d ptPos ;
Vector3d vtDer1 ;
if ( Curve.GetPointD1D2( dU, nSide, ptPos, &vtDer1)) {
double dDer1 = vtDer1.LenXY() ;
if ( dDer1 > EPS_ZERO)
dDeltaU = 10 * EPS_SMALL / dDer1 ;
}
// cerco di spostarmi per evitare eventuali problemi di tangenza
if ( nSide == ICurve::FROM_MINUS) {
double dUm = dU - dDeltaU ;
if ( ! Curve.IsValidParam( dUm, nSide)) {
if ( Curve.IsClosed()) {
double dStart, dEnd ;
Curve.GetDomain( dStart, dEnd) ;
dUm = ( dEnd - dStart) - dDeltaU ;
}
else
dUm = dU ;
}
dU = dUm ;
return true ;
}
else { // nSide == ICurve::FROM_PLUS
double dUm = dU + dDeltaU ;
if ( ! Curve.IsValidParam( dUm, nSide)) {
if ( Curve.IsClosed()) {
double dStart, dEnd ;
Curve.GetDomain( dStart, dEnd) ;
dUm = dStart + dDeltaU ;
}
else
dUm = dU ;
}
dU = dUm ;
return true ;
}
}
+143 -26
View File
@@ -13,12 +13,16 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "IntersLineLine.h"
#include "IntersLineArc.h"
#include "IntersArcArc.h"
#include "IntersCrvCompoCrvCompo.h"
#include "CurveLine.h"
#include "CurveComposite.h"
#include "/EgtDev/Include/EGkIntersCurveCurve.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGtPointerOwner.h"
#include <algorithm>
@@ -30,11 +34,11 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
// Le intersezioni sono calcolate nel piano XY locale.
// Il flag bAreSegments vale solo per intersezione tra due linee e riguarda entrambe.
// reset
// inizializzazioni
m_bOverlaps = false ;
m_nNumInters = 0 ;
m_pCurve[0] = nullptr ;
m_pCurve[1] = nullptr ;
m_pCurve[0] = &CurveA ;
m_pCurve[1] = &CurveB ;
// chiamo calcolatore opportuno
switch ( CurveA.GetType()) {
@@ -44,6 +48,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
LineLineCalculate( CurveA, CurveB, bAreSegments) ;
break ;
case CRV_ARC :
LineArcCalculate( CurveA, CurveB) ;
break ;
case CRV_BEZ :
break ;
@@ -53,6 +58,19 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
}
break ;
case CRV_ARC :
switch ( CurveB.GetType()) {
case CRV_LINE :
ArcLineCalculate( CurveA, CurveB) ;
break ;
case CRV_ARC :
ArcArcCalculate( CurveA, CurveB) ;
break ;
case CRV_BEZ :
break ;
case CRV_COMPO :
ArcCrvCompoCalculate( CurveA, CurveB) ;
break ;
}
break ;
case CRV_BEZ :
break ;
@@ -62,6 +80,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
CrvCompoLineCalculate( CurveA, CurveB) ;
break ;
case CRV_ARC :
CrvCompoArcCalculate( CurveA, CurveB) ;
break ;
case CRV_BEZ :
break ;
@@ -71,10 +90,6 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
}
break ;
}
// salvo i puntatori alle curve
m_pCurve[0] = &CurveA ;
m_pCurve[1] = &CurveB ;
}
//----------------------------------------------------------------------------
@@ -86,11 +101,25 @@ IntersCurveCurve::LineLineCalculate( const ICurve& CurveA, const ICurve& CurveB,
if ( intLnLn.m_nNumInters > 0) {
m_bOverlaps = intLnLn.m_bOverlaps ;
m_nNumInters = intLnLn.m_nNumInters ;
for ( int i = 0 ; i < m_nNumInters ; ++ i)
if ( m_nNumInters == 1)
m_Info.push_back( intLnLn.m_Info) ;
}
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::LineArcCalculate( const ICurve& CurveA, const ICurve& CurveB)
{
IntersLineArc intLnAr( *GetCurveLine( &CurveA), *GetCurveArc( &CurveB)) ;
if ( intLnAr.m_nNumInters > 0) {
m_bOverlaps = false ;
m_nNumInters = intLnAr.m_nNumInters ;
for ( int i = 0 ; i < m_nNumInters ; ++ i)
m_Info.push_back( intLnAr.m_Info[i]) ;
}
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::LineCrvCompoCalculate( const ICurve& CurveA, const ICurve& CurveB)
@@ -102,6 +131,47 @@ IntersCurveCurve::LineCrvCompoCalculate( const ICurve& CurveA, const ICurve& Cur
CrvCompoCrvCompoCalculate( crvCompo, CurveB) ;
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::ArcLineCalculate( const ICurve& CurveA, const ICurve& CurveB)
{
IntersLineArc intLnAr( *GetCurveLine( &CurveB), *GetCurveArc( &CurveA)) ;
if ( intLnAr.m_nNumInters > 0) {
m_bOverlaps = false ;
m_nNumInters = intLnAr.m_nNumInters ;
for ( int i = 0 ; i < m_nNumInters ; ++ i)
m_Info.push_back( intLnAr.m_Info[i]) ;
// devo scambiare opportunamente le info di intersezione tra A e B
SwapInfoAB( m_Info, 0) ;
}
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::ArcArcCalculate( const ICurve& CurveA, const ICurve& CurveB)
{
IntersArcArc intArAr( *GetCurveArc( &CurveA), *GetCurveArc( &CurveB)) ;
if ( intArAr.m_nNumInters > 0) {
m_bOverlaps = intArAr.m_bOverlaps ;
m_nNumInters = intArAr.m_nNumInters ;
for ( int i = 0 ; i < m_nNumInters ; ++ i)
m_Info.push_back( intArAr.m_Info[i]) ;
}
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::ArcCrvCompoCalculate( const ICurve& CurveA, const ICurve& CurveB)
{
// trasformo l'arco in curva composita
CurveComposite crvCompo ;
crvCompo.CopyFrom( &CurveA) ;
// eseguo l'intersezione tra curve composite
CrvCompoCrvCompoCalculate( crvCompo, CurveB) ;
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::CrvCompoLineCalculate( const ICurve& CurveA, const ICurve& CurveB)
@@ -113,6 +183,17 @@ IntersCurveCurve::CrvCompoLineCalculate( const ICurve& CurveA, const ICurve& Cur
CrvCompoCrvCompoCalculate( CurveA, crvCompo) ;
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::CrvCompoArcCalculate( const ICurve& CurveA, const ICurve& CurveB)
{
// trasformo l'arco in curva composita
CurveComposite crvCompo ;
crvCompo.CopyFrom( &CurveB) ;
// eseguo l'intersezione tra curve composite
CrvCompoCrvCompoCalculate( CurveA, crvCompo) ;
}
//----------------------------------------------------------------------------
void
IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve& CurveB)
@@ -239,21 +320,8 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
// devo scambiare opportunamente le info di intersezione tra A e B
// copia temporanea delle info di intersezione
ICCIVECTOR InfoTmp = m_Info ;
// eseguo lo scambio
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// scambio le informazioni tra A e B
swap( InfoTmp[i].IciA[0], InfoTmp[i].IciB[0]) ;
swap( InfoTmp[i].IciA[1], InfoTmp[i].IciB[1]) ;
// riordino eventuali sovrapposizioni controverse
if ( InfoTmp[i].bOverlap && ! InfoTmp[i].bCBOverEq) {
swap( InfoTmp[i].IciA[0], InfoTmp[i].IciA[1]) ;
swap( InfoTmp[i].IciB[0], InfoTmp[i].IciB[1]) ;
}
}
// ordino le intersezioni secondo l'ordine crescente del parametro della prima curva
stable_sort( InfoTmp.begin(), InfoTmp.end(), SortGreater) ;
// verifiche su intersezioni in zone non-manifold
OrderNonManifoldInters( InfoTmp, *(m_pCurve[1]), *(m_pCurve[0])) ;
// esecuzione scambio e controlli
SwapInfoAB( InfoTmp, 1) ;
// se esiste almeno una intersezione
if ( m_nNumInters >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
@@ -266,6 +334,31 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
return false ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::SwapInfoAB( ICCIVECTOR& Info, int IndCrvOrd)
{
if ( IndCrvOrd < 0 || IndCrvOrd > 1)
return false ;
// eseguo lo scambio
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// scambio le informazioni tra A e B
swap( Info[i].IciA[0], Info[i].IciB[0]) ;
swap( Info[i].IciA[1], Info[i].IciB[1]) ;
// riordino eventuali sovrapposizioni controverse
if ( Info[i].bOverlap && ! Info[i].bCBOverEq) {
swap( Info[i].IciA[0], Info[i].IciA[1]) ;
swap( Info[i].IciB[0], Info[i].IciB[1]) ;
}
}
// ordino le intersezioni secondo l'ordine crescente del parametro della prima curva
stable_sort( Info.begin(), Info.end(), SortGreater) ;
// verifiche su intersezioni in zone non-manifold
OrderNonManifoldInters( Info, *(m_pCurve[IndCrvOrd]), *(m_pCurve[1-IndCrvOrd])) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, CRVCVECTOR& ccClass)
@@ -352,17 +445,21 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
double dStartPar, dEndPar ;
if ( ! pCurveA->GetDomain( dStartPar, dEndPar))
return false ;
// se i box delle due curve non interferiscono è sicuramente esterna
// se i box delle due curve non interferiscono è sicuramente default
BBox3d boxCrvA, boxCrvB ;
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
! pCurveB->GetLocalBBox( boxCrvB))
return false ;
if ( ! boxCrvA.OverlapsXY( boxCrvB)) {
// determino il tipo di esterno
int nClass ;
if ( ! GetCurveOutClass( pCurveB, nClass))
return false ;
// assegno i dati
CrvClass segClass ;
segClass.dParS = dStartPar ;
segClass.dParE = dEndPar ;
segClass.nClass = CRVC_OUT ;
segClass.nClass = nClass ;
ccClass.push_back( segClass) ;
return true ;
}
@@ -377,7 +474,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
return false ;
// calcolo l'intersezione
IntersCurveCurve iCC( clLine, *pCurveB) ;
// dichiaro la curva esterna per default
// dichiaro la classe della curva per default
int nClass = CRVC_OUT ;
// se c'è almeno una intersezione
if ( iCC.GetNumInters() > 0) {
@@ -387,6 +484,12 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
nClass = CRVC_IN ;
}
// altrimenti sono esterni tra loro
else {
// determino il tipo di esterno
if ( ! GetCurveOutClass( pCurveB, nClass))
return false ;
}
// assegno i dati
CrvClass segClass ;
segClass.dParS = dStartPar ;
@@ -395,3 +498,17 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
ccClass.push_back( segClass) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
{
PolyLine PL ;
if ( ! pCurve->ApproxWithLines( LIN_TOL_APPROX, ANG_TOL_APPROX_DEG, PL))
return false ;
double dArea ;
if ( ! PL.GetAreaXY( dArea))
return false ;
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
return true ;
}
+273
View File
@@ -0,0 +1,273 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : IntersLineArc.cpp Data : 07.07.14 Versione : 1.5g2
// Contenuto : Implementazione della classe intersezione linea/arco.
//
//
//
// Modifiche : 07.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersLineArc.h"
using namespace std ;
//----------------------------------------------------------------------------
IntersLineArc::IntersLineArc( const ICurveLine& Line, const ICurveArc& Arc)
{
// Le intersezioni sono calcolate nel piano XY locale.
// nessuna intersezione trovata
m_nNumInters = 0 ;
// verifico validità linea e arco
if ( ! Line.IsValid() || ! Arc.IsValid())
return ;
// l'arco deve avere il piano coincidente con XY
if ( ! Arc.GetNormVersor().IsZplus() && ! Arc.GetNormVersor().IsZminus())
return ;
// verifico che l'angolo al centro non superi il giro
if ( fabs( Arc.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO)
return ;
// !!! Gestire l'arco proiettato come ellisse
// verifico sovrapposizione box
BBox3d boxLine ;
if ( ! Line.GetLocalBBox( boxLine))
return ;
BBox3d boxArc ;
if ( ! Arc.GetLocalBBox( boxArc))
return ;
if ( ! boxLine.OverlapsXY( boxArc))
return ;
// linea : copia e Direzione
m_Line.CopyFrom( &Line) ;
m_vtDirL = m_Line.GetEnd() - m_Line.GetStart() ;
if ( m_vtDirL.SqLenXY() < EPS_SMALL * EPS_SMALL)
return ;
// arco : copia
m_Arc.CopyFrom( &Arc) ;
// punto proiezione del centro arco sulla linea
double dU = (( m_Arc.GetCenter() - m_Line.GetStart()) * m_vtDirL) / m_vtDirL.SqLenXY() ;
Point3d ptPrjCen = m_Line.GetStart() + m_vtDirL * dU ;
// quadrato della distanza tra centro e punto proiezione
double dSqDist = ( ptPrjCen - m_Arc.GetCenter()).SqLenXY() ;
// differenza tra quadrato del raggio e quadrato della distanza
double dSqDelta = m_Arc.GetRadius() * m_Arc.GetRadius() - dSqDist ;
// se distanza maggiore del raggio -> nessuna intersezione
if ( dSqDelta < - 2 * m_Arc.GetRadius() * EPS_SMALL)
return ;
// se distanza uguale al raggio -> una intersezione tangente (è la proiezione)
if ( dSqDelta < 2 * m_Arc.GetRadius() * EPS_SMALL) {
// determinazione geometrica dell'intersezione tra le due curve
int nPosL, nPosA ;
if ( ! CalcIntersGeomData( 0, ptPrjCen, nPosL, nPosA))
return ;
// determinazione topologica dell'intersezione tra le due curve
if ( ! CalcTgIntersTopolData( 0, nPosL, nPosA))
return ;
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
return ;
}
// distanza minore del raggio -> due intersezioni
double dDelta = sqrt( dSqDelta) ;
Vector3d vtDelta = m_vtDirL * dDelta / m_vtDirL.LenXY() ;
int nPosL, nPosA ;
// ---> prima intersezione
// determinazione geometrica e topologica dell'intersezione tra le due curve
if ( CalcIntersGeomData( 0, ptPrjCen - vtDelta, nPosL, nPosA) &&
CalcSecIntersTopolData( 0, nPosL, nPosA)) {
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
++ m_nNumInters ;
}
// ---> seconda intersezione
// determinazione geometrica e topologica dell'intersezione tra le due curve
if ( CalcIntersGeomData( m_nNumInters, ptPrjCen + vtDelta, nPosL, nPosA) &&
CalcSecIntersTopolData( m_nNumInters, nPosL, nPosA)) {
// aggiorno dati generali di intersezione
m_Info[m_nNumInters].bOverlap = false ;
++ m_nNumInters ;
}
}
//----------------------------------------------------------------------------
bool
IntersLineArc::CalcIntersGeomData( int nInt, const Point3d& ptInt, int& nPosL, int& nPosA)
{
// posizione parametrica dell'intersezione sulla linea
if ( ! m_Line.CalcPointParamPosiz( ptInt, true, m_Info[nInt].IciA[0].dU, nPosL))
return false ;
// posizione parametrica dell'intersezione sull'arco
if ( ! m_Arc.CalcPointParamPosiz( ptInt, m_Info[nInt].IciB[0].dU, nPosA))
return false ;
// se soluzione non accettata, esco
if ( nPosL == ICurve::PP_NULL || nPosA == ICurve::PP_NULL)
return false ;
// calcolo i punti sulle due curve (possono differire in Z)
m_Info[nInt].IciA[0].ptI = m_Line.GetStart() + m_Info[nInt].IciA[0].dU * m_vtDirL ;
m_Arc.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciB[0].ptI) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersLineArc::CalcTgIntersTopolData( int nInt, int nPosL, int nPosA)
{
// calcolo dati ausiliari
bool bCCW = (( m_Arc.GetAngCenter() > 0 && m_Arc.GetNormVersor().IsZplus()) ||
( m_Arc.GetAngCenter() < 0 && m_Arc.GetNormVersor().IsZminus())) ;
double dCrossXY = CrossXY( m_vtDirL, ( m_Arc.GetCenter() - m_Info[nInt].IciB[0].ptI)) ;
// calcolo tipo di intersezione
m_Info[nInt].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciA[0].nNextTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPosL == ICurve::PP_START || nPosL == ICurve::PP_END) &&
( nPosA == ICurve::PP_START || nPosA == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di L interseca il mezzo di A
else if ( nPosL == ICurve::PP_START) {
if ( bCCW)
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva B NULL + NULL
}
// la fine di L interseca il mezzo di A
else if ( nPosL == ICurve::PP_END) {
if ( bCCW)
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva B NULL + NULL
}
// l'inizio di A interseca il mezzo di L
else if ( nPosA == ICurve::PP_START) {
// curva A NULL + NULL
if ( - dCrossXY > 0)
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di A interseca il mezzo di L
else if ( nPosA == ICurve::PP_END) {
// curva A NULL + NULL
if ( - dCrossXY > 0)
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( bCCW) { // OUT + OUT
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ;
}
else { // IN + IN
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ;
}
if ( - dCrossXY > 0) { // OUT + OUT
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ;
}
else { // IN + IN
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
IntersLineArc::CalcSecIntersTopolData( int nInt, int nPosL, int nPosA)
{
// calcolo dati ausiliari
Point3d ptIntA ;
Vector3d vtDirA ;
m_Arc.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, ptIntA, &vtDirA) ;
double dCrossXY = CrossXY( m_vtDirL, vtDirA) ;
// calcolo tipo di intersezione
m_Info[nInt].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciA[0].nNextTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[nInt].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPosL == ICurve::PP_START || nPosL == ICurve::PP_END) &&
( nPosA == ICurve::PP_START || nPosA == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPosL == ICurve::PP_START) {
if ( dCrossXY > 0)
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva B NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPosL == ICurve::PP_END) {
if ( dCrossXY < 0)
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva B NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPosA == ICurve::PP_START) {
// curva A NULL + NULL
if ( - dCrossXY > 0)
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPosA == ICurve::PP_END) {
// curva A NULL + NULL
if ( - dCrossXY < 0)
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( CrossXY( ( m_Line.GetStart() - ( ptIntA - vtDirA)), vtDirA) > 0) {
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ;
}
else {
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ;
}
if ( CrossXY( ( ( ptIntA - vtDirA) - m_Line.GetStart()), m_vtDirL) > 0) {
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ;
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ;
}
else {
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ;
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ;
}
}
return true ;
}
+56
View File
@@ -0,0 +1,56 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : IntersLineArc.h Data : 07.07.14 Versione : 1.5g2
// Contenuto : Dichiarazione della classe intersezione linea/arco.
//
//
//
// Modifiche : 07.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkIntersCurveCurve.h"
#include "CurveLine.h"
#include "CurveArc.h"
//-----------------------------------------------------------------------------
class IntersLineArc
{
friend class IntersCurveCurve ;
public :
IntersLineArc( const ICurveLine& Line, const ICurveArc& Arc) ;
public :
bool GetOverlaps( void)
{ return false ; }
int GetNumInters( void)
{ return m_nNumInters ; }
bool GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
{ if ( nInd < 0 || nInd >= m_nNumInters)
return false ;
aInfo = m_Info[nInd] ;
return true ; }
private :
IntersLineArc( void) ;
bool CalcIntersGeomData( int nInt, const Point3d& ptInt, int& nPosL, int& nPosA) ;
bool CalcTgIntersTopolData( int nInt, int nPosL, int nPosA) ;
bool CalcSecIntersTopolData( int nInt, int nPosL, int nPosA) ;
private :
static const int MAX_INTERS = 2 ;
private :
CurveLine m_Line ;
Vector3d m_vtDirL ;
CurveArc m_Arc ;
int m_nNumInters ;
IntCrvCrvInfo m_Info[MAX_INTERS] ;
} ;
+15 -18
View File
@@ -158,26 +158,24 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
// posizioni parametriche dell'intersezione sulle linee
m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ;
m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ;
// tipo di posizione
enum IntPos { IP_NULL = 0, IP_START = 1, IP_MID = 2, IP_END = 3} ;
// verifica posizione intersezione su prima linea
int nPos1 = IP_NULL ; // fuori
int nPos1 = ICurve::PP_NULL ; // fuori
if ( ( m_Info.IciA[0].dU * vtDir1).IsSmall())
nPos1 = IP_START ; // vicino a inizio
nPos1 = ICurve::PP_START ; // vicino a inizio
else if ( (( 1 - m_Info.IciA[0].dU) * vtDir1).IsSmall())
nPos1 = IP_END ; // vicino a fine
nPos1 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
nPos1 = IP_MID ; // nell'interno
nPos1 = ICurve::PP_MID ; // nell'interno
// verifica posizione intersezione su seconda linea
int nPos2 = IP_NULL ; // fuori
int nPos2 = ICurve::PP_NULL ; // fuori
if ( ( m_Info.IciB[0].dU * vtDir2).IsSmall())
nPos2 = IP_START ; // vicino a inizio
nPos2 = ICurve::PP_START ; // vicino a inizio
else if ( (( 1 - m_Info.IciB[0].dU) * vtDir2).IsSmall())
nPos2 = IP_END ; // vicino a fine
nPos2 = ICurve::PP_END ; // vicino a fine
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
nPos2 = IP_MID ; // nell'interno
nPos2 = ICurve::PP_MID ; // nell'interno
// se soluzione non accettata, esco
if ( nPos1 == IP_NULL || nPos2 == IP_NULL)
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return ;
// limito i parametri a stare sui segmenti (0...1)
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ;
@@ -191,12 +189,12 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
m_Info.IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == IP_START || nPos1 == IP_END) &&
( nPos2 == IP_START || nPos2 == IP_END)) {
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == IP_START) {
else if ( nPos1 == ICurve::PP_START) {
if ( dCrossXY > 0)
m_Info.IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
@@ -204,7 +202,7 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
// curva B NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == IP_END) {
else if ( nPos1 == ICurve::PP_END) {
if ( dCrossXY < 0)
m_Info.IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
@@ -212,7 +210,7 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
// curva B NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == IP_START) {
else if ( nPos2 == ICurve::PP_START) {
// curva A NULL + NULL
if ( - dCrossXY > 0)
m_Info.IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
@@ -220,7 +218,7 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
m_Info.IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == IP_END) {
else if ( nPos2 == ICurve::PP_END) {
// curva A NULL + NULL
if ( - dCrossXY < 0)
m_Info.IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
@@ -253,7 +251,6 @@ IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Li
}
// se le linee sono parallele e non coincidenti
//if ( fabs( CrossXY( ( ptS2 - ptS1), vtDir1)) > EPS_SMALL * dLen1XY)
if ( bParallel && bFarEnds)
return ; // non ci sono intersezioni
+26 -5
View File
@@ -327,7 +327,7 @@ PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
//----------------------------------------------------------------------------
bool
PolyLine::NewellPlane( Plane3d& plPlane) const
PolyLine::NewellPlane( Plane3d& plPlane, double& dArea) const
{
// Compute normal as being proportional to projected areas of polygon onto the yz,
// xz, and xy planes. Also compute centroid as representative point on the plane
@@ -356,21 +356,25 @@ PolyLine::NewellPlane( Plane3d& plPlane) const
if ( nNumSide < 3)
return false ;
// Normal must be normalizable (the length of the normal is the double of the area of the polygon)
if ( ! vtN.Normalize())
double dLenN = vtN.Len() ;
if ( dLenN < EPS_SMALL)
return false ;
// Normalize normal and fill in the plane equation fields
vtN /= dLenN ;
// Fill in the plane equation fields
plPlane.vtN = vtN ;
plPlane.dDist = ( ( ptCen - ORIG) * plPlane.vtN) / nNumSide ; // “centroid / n” is the true centroid point
// Set area
dArea = 0.5 * dLenN ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::IsPlanar( Plane3d& plPlane, double dToler) const
PolyLine::IsPlanar( Plane3d& plPlane, double& dArea, double dToler) const
{
// Compute a representative plane for the polygon
if ( ! NewellPlane( plPlane))
if ( ! NewellPlane( plPlane, dArea))
return false ;
// Test each vertex to see if it is farther from plane than allowed max distance
Point3d ptP ;
@@ -383,6 +387,23 @@ PolyLine::IsPlanar( Plane3d& plPlane, double dToler) const
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::GetAreaXY( double& dArea) const
{
// verifico sia chiusa
if ( ! IsClosed())
return false ;
// calcolo l'area considerando solo XY (č la Z di Newell)
dArea = 0 ;
Point3d ptIni, ptFin ;
for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
dArea += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
}
dArea = 0.5 * dArea ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::GetMaxDistanceFromLine( double& dMaxDist, const Point3d& ptAx,
+2 -1
View File
@@ -31,8 +31,9 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
if ( ! PL.IsClosed())
return false ;
// calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
if ( ! PL.IsPlanar( plPlane, 50 * EPS_SMALL))
if ( ! PL.IsPlanar( plPlane, dArea, 50 * EPS_SMALL))
return false ;
bool bCCW ;
if ( fabs( plPlane.vtN.z) >= fabs( plPlane.vtN.x) &&