b709776f5f
- piccole mdofiche poco più che estetiche.
294 lines
10 KiB
C++
294 lines
10 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"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
SelfIntersCurve::SelfIntersCurve( const ICurve& Curve)
|
|
{
|
|
// Le auto-intersezioni sono calcolate nel piano XY locale.
|
|
|
|
// inizializzazioni
|
|
m_bOverlaps = false ;
|
|
m_nIntersCount = 0 ;
|
|
m_pCurve = &Curve ;
|
|
|
|
// verifico che la curva sia definita
|
|
if ( &Curve == nullptr || ! Curve.IsValid())
|
|
return ;
|
|
|
|
// puntatore alla curva usata nei calcoli (originale o temporanea)
|
|
const ICurve* pCalcCrv ;
|
|
// eventuale approssimazione temporanea della curva
|
|
PtrOwner<ICurve> pTmpCrv ;
|
|
// eventuale parametrizzazione della approssimazione temporanea
|
|
DBLVECTOR vTmpPar ;
|
|
|
|
// se curva è arco da approssimare oppure è curva di Bezier
|
|
if ( ( m_pCurve->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve)) ||
|
|
m_pCurve->GetType() == CRV_BEZIER) {
|
|
// approssimo con rette
|
|
PolyLine PL ;
|
|
if ( ! m_pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
|
return ;
|
|
pTmpCrv.Set( CreateBasicCurveComposite()) ;
|
|
if ( IsNull( pTmpCrv))
|
|
return ;
|
|
if ( ! GetBasicCurveComposite( pTmpCrv)->FromPolyLine( PL))
|
|
return ;
|
|
pCalcCrv = pTmpCrv ;
|
|
// salvo la parametrizzazione della approssimazione temporanea
|
|
vTmpPar.reserve( PL.GetPointNbr()) ;
|
|
double dPar ;
|
|
bool bFound = PL.GetFirstU( dPar) ;
|
|
while ( bFound) {
|
|
vTmpPar.push_back( dPar) ;
|
|
bFound = PL.GetNextU( dPar) ;
|
|
}
|
|
}
|
|
// altrimenti uso la curva originale
|
|
else
|
|
pCalcCrv = m_pCurve ;
|
|
|
|
// chiamo calcolatore opportuno
|
|
switch ( pCalcCrv->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( pCalcCrv), *GetCurveComposite( pCalcCrv)) ;
|
|
if ( intCcCc.m_nNumInters > 0) {
|
|
m_bOverlaps = intCcCc.m_bOverlaps ;
|
|
m_nIntersCount = intCcCc.m_nNumInters ;
|
|
for ( int i = 0 ; i < m_nIntersCount ; ++ i)
|
|
m_Info.push_back( intCcCc.m_Info[i]) ;
|
|
}
|
|
}
|
|
break ;
|
|
default :
|
|
break ;
|
|
}
|
|
// per curva approssimata, sistemo...
|
|
AdjustIntersParams( ( pCalcCrv != m_pCurve), pCalcCrv, vTmpPar) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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()) ||
|
|
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SelfIntersCurve::GetCurveParamFromApproxParam( double& dU, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
|
|
{
|
|
int nInd = int( dU) ;
|
|
double dFraz = dU - nInd ;
|
|
if ( nInd >= 0 && nInd < int( vCalcPar.size()) - 1) {
|
|
// parametrizzazione da vettore dei parametri, uniforme in ogni intervallino
|
|
dU = vCalcPar[nInd] + dFraz * ( vCalcPar[nInd+1] - vCalcPar[nInd]) ;
|
|
}
|
|
else {
|
|
// domini parametrici delle due curve
|
|
double dCalcS, dCalcE ;
|
|
pCalcCrv->GetDomain( dCalcS, dCalcE) ;
|
|
double dCrvS, dCrvE ;
|
|
m_pCurve->GetDomain( dCrvS, dCrvE) ;
|
|
// considero una parametrizzazione uniforme sull'intero dominio
|
|
dU = dCrvS + ( dU - dCalcS) * ( dCrvE - dCrvS) / ( dCalcE - dCalcS) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
|
|
{
|
|
// se la curva originale non è stata approssimata o non ci sono auto-intersezioni, non va fatto alcunché
|
|
if ( ! bAdjCrv || m_Info.empty())
|
|
return true ;
|
|
// procedo ad aggiustare
|
|
for ( auto& aInfo : m_Info) {
|
|
// devo ricalcolare i parametri dei punti di intersezione
|
|
GetCurveParamFromApproxParam( aInfo.IciA[0].dU, pCalcCrv, vCalcPar) ;
|
|
ImproveCurveParamAtPoint( aInfo.IciA[0].dU, aInfo.IciA[0].ptI, m_pCurve) ;
|
|
if ( aInfo.bOverlap) {
|
|
GetCurveParamFromApproxParam( aInfo.IciA[1].dU, pCalcCrv, vCalcPar) ;
|
|
ImproveCurveParamAtPoint( aInfo.IciA[1].dU, aInfo.IciA[1].ptI, m_pCurve) ;
|
|
}
|
|
GetCurveParamFromApproxParam( aInfo.IciB[0].dU, pCalcCrv, vCalcPar) ;
|
|
ImproveCurveParamAtPoint( aInfo.IciB[0].dU, aInfo.IciB[0].ptI, m_pCurve) ;
|
|
if ( aInfo.bOverlap) {
|
|
GetCurveParamFromApproxParam( aInfo.IciB[1].dU, pCalcCrv, vCalcPar) ;
|
|
ImproveCurveParamAtPoint( aInfo.IciB[1].dU, aInfo.IciB[1].ptI, m_pCurve) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SelfIntersCurve::GetOverlaps( void)
|
|
{
|
|
return m_bOverlaps ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SelfIntersCurve::GetIntersCount( void)
|
|
{
|
|
return m_nIntersCount ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SelfIntersCurve::GetCrossIntersCount( void)
|
|
{
|
|
int nCrossIntersCount = 0 ;
|
|
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
|
// se con sovrapposizione
|
|
if ( m_Info[i].bOverlap) {
|
|
if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_SPK && m_Info[i].IciA[1].nNextTy != ICCT_SPK &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[1].nNextTy != ICCT_NULL)
|
|
++ nCrossIntersCount ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
|
|
++ nCrossIntersCount ;
|
|
}
|
|
}
|
|
return nCrossIntersCount ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SelfIntersCurve::GetCrossOrOverlapIntersCount( void)
|
|
{
|
|
int nCrossOverIntersCount = 0 ;
|
|
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
|
// se con sovrapposizione
|
|
if ( m_Info[i].bOverlap)
|
|
++ nCrossOverIntersCount ;
|
|
// se altrimenti con attraversamento
|
|
else if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
|
|
++ nCrossOverIntersCount ;
|
|
}
|
|
return nCrossOverIntersCount ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SelfIntersCurve::GetTouchIntersCount( void)
|
|
{
|
|
int nTouchIntersCount = 0 ;
|
|
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
|
// se con sovrapposizione
|
|
if ( m_Info[i].bOverlap) {
|
|
if ( ( m_Info[i].IciA[0].nPrevTy == m_Info[i].IciA[1].nNextTy ||
|
|
m_Info[i].IciA[0].nPrevTy == ICCT_SPK || m_Info[i].IciA[1].nNextTy == ICCT_SPK) &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[1].nNextTy != ICCT_NULL)
|
|
++ nTouchIntersCount ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
if ( m_Info[i].IciA[0].nPrevTy == m_Info[i].IciA[0].nNextTy &&
|
|
m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
|
|
++ nTouchIntersCount ;
|
|
}
|
|
}
|
|
return nTouchIntersCount ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SelfIntersCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
|
|
{
|
|
if ( nInd < 0 || nInd >= m_nIntersCount)
|
|
return false ;
|
|
aInfo = m_Info[nInd] ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SelfIntersCurve::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI)
|
|
{
|
|
if ( m_nIntersCount == 0)
|
|
return false ;
|
|
|
|
// ricerca del punto più vicino tra le intersezioni singole
|
|
bool bFound = false ;
|
|
double dMinSqDist = SQ_INFINITO ;
|
|
for ( int i = 0 ; i < m_nIntersCount ; ++ 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 ;
|
|
}
|