Files
EgtGeomKernel/SelfIntersCurve.cpp
T
Dario Sassi f4b88af3e1 EgtGeomKernel 1.6h2 :
- aggiunte Regioni (SurfFlatRegion) e prime funzionalità relative
- corretti Intervals per Add
- corretta CalcPointParamPosiz per archi che in realtà sono circonferenze.
2015-08-07 10:45:40 +00:00

195 lines
6.4 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : SelfIntersCurve.cpp Data : 06.07.15 Versione : 1.6g2
// Contenuto : Implementazione della classe auto-intersezione di curva.
//
//
//
// Modifiche : 06.07.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "CurveArc.h"
#include "CurveComposite.h"
#include "IntersCrvCompoCrvCompo.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
using namespace std ;
//----------------------------------------------------------------------------
SelfIntersCurve::SelfIntersCurve( const ICurve& Curve)
{
// Le auto-intersezioni sono calcolate nel piano XY locale.
// inizializzazioni
m_bOverlaps = false ;
m_nNumInters = 0 ;
m_pOriCrv = &Curve ;
m_pCurve = nullptr ;
// verifico che la curva sia definita
if ( &Curve == nullptr || ! Curve.IsValid())
return ;
// se curva è arco da approssimare oppure è curva di Bezier
if ( ( m_pOriCrv->GetType() == CRV_ARC && IsArcToApprox( *m_pOriCrv)) ||
m_pOriCrv->GetType() == CRV_BEZ) {
// approssimo con rette
PolyLine PL ;
if ( ! m_pOriCrv->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return ;
m_pTmpCrv.Set( CreateBasicCurveComposite()) ;
if ( IsNull( m_pTmpCrv))
return ;
if ( ! GetBasicCurveComposite( Get( m_pTmpCrv))->FromPolyLine( PL))
return ;
m_pCurve = Get( m_pTmpCrv) ;
}
// altrimenti uso la curva originale
else
m_pCurve = m_pOriCrv ;
// chiamo calcolatore opportuno
switch ( m_pCurve->GetType()) {
case CRV_LINE :
// un segmento non può autointersecarsi (non considero auto-intersezione un segmento perpendicolare a XY)
break ;
case CRV_ARC :
// un arco nel piano XY con angolo al centro non superiore al giro non può autointersecarsi
break ;
case CRV_COMPO : {
IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( &Curve), *GetCurveComposite( &Curve)) ;
if ( intCcCc.m_nNumInters > 0) {
m_bOverlaps = intCcCc.m_bOverlaps ;
m_nNumInters = intCcCc.m_nNumInters ;
for ( int i = 0 ; i < m_nNumInters ; ++ i)
m_Info.push_back( intCcCc.m_Info[i]) ;
}
}
break ;
}
}
//----------------------------------------------------------------------------
bool
SelfIntersCurve::IsArcToApprox( const ICurve& Curve)
{
// recupero l'arco
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
if ( pArc == nullptr)
return false ;
// verifico se non è nel piano XY o ha più di un giro al centro
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
fabs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
}
//----------------------------------------------------------------------------
bool
SelfIntersCurve::GetOverlaps( void)
{
return m_bOverlaps ;
}
//----------------------------------------------------------------------------
int
SelfIntersCurve::GetNumInters( void)
{
return m_nNumInters ;
}
//----------------------------------------------------------------------------
int
SelfIntersCurve::GetNumCrossInters( void)
{
int nNumCrossInters = 0 ;
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se con sovrapposizione
if ( m_Info[i].bOverlap) {
if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy)
++ nNumCrossInters ;
}
// altrimenti
else {
if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy)
++ nNumCrossInters ;
}
}
return nNumCrossInters ;
}
//----------------------------------------------------------------------------
bool
SelfIntersCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
{
if ( nInd < 0 || nInd >= m_nNumInters)
return false ;
aInfo = m_Info[nInd] ;
// se curva originale approssimata, devo ricalcolare i parametri dei punti di intersezione
if ( m_pCurve != m_pOriCrv) {
if ( ! m_pOriCrv->GetParamAtPoint( aInfo.IciA[0].ptI, aInfo.IciA[0].dU, 10 * EPS_SMALL))
return false ;
if ( aInfo.bOverlap && ! m_pOriCrv->GetParamAtPoint( aInfo.IciA[1].ptI, aInfo.IciA[1].dU, 10 * EPS_SMALL))
return false ;
if ( ! m_pOriCrv->GetParamAtPoint( aInfo.IciB[0].ptI, aInfo.IciB[0].dU, 10 * EPS_SMALL))
return false ;
if ( aInfo.bOverlap && ! m_pOriCrv->GetParamAtPoint( aInfo.IciB[1].ptI, aInfo.IciB[1].dU, 10 * EPS_SMALL))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SelfIntersCurve::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI)
{
if ( m_nNumInters == 0)
return false ;
// ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ;
double dMinSqDist = INFINITO * INFINITO ;
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se è un'intersezione singola
if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto
Point3d ptP = m_Info[i].IciA[0].ptI ;
double dSqDist = SqDist( ptNear, ptP) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
ptI = ptP ;
bFound = true ;
}
}
// altrimenti
else {
// recupero il tratto di sovrapposizione
double dUStartTrim, dUEndTrim ;
dUStartTrim = m_Info[i].IciA[0].dU ;
dUEndTrim = m_Info[i].IciA[1].dU ;
PtrOwner<ICurve> pCrv( m_pCurve->CopyParamRange( dUStartTrim, dUEndTrim)) ;
if ( IsNull( pCrv))
continue ;
// cerco il punto
int nFlag ;
Point3d ptP ;
if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) {
// faccio la verifica
double dSqDist = SqDist( ptNear, ptP) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
ptI = ptP ;
bFound = true ;
}
}
}
}
return bFound ;
}