EgtGeomKernel 1.5g1 :
- alle curve aggiunto il metodo CopyParamRange (per curve chiuse ammatte range che passano dal punto di chiusura) - trasformato il metodo Copy di tutti gli oggetti geometrici in CopyFrom - a TSC aggiunte funzioni CopyCurveByParamRange e SplitCurveByClass - migliorata gestione intersezioni sovrapposte - aggiunta classificazione parti di curva (IN,OUT,ONP,ONM) da intersezioni con altra curva chiusa.
This commit is contained in:
+224
-17
@@ -15,17 +15,20 @@
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurveCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersCurveCurve::IntersCurveCurve( const ICurve& Curve1, const ICurve& Curve2, bool bIsSegment)
|
||||
IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB, bool bAreSegments)
|
||||
{
|
||||
// Le intersezioni sono calcolate nel piano XY locale.
|
||||
// Il flag bIsSegment vale solo per linee.
|
||||
// Il flag bAreSegments vale solo per intersezione tra due linee e riguarda entrambe.
|
||||
|
||||
// reset
|
||||
m_bOverlaps = false ;
|
||||
@@ -34,17 +37,18 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& Curve1, const ICurve& Curve2,
|
||||
m_pCurve[1] = nullptr ;
|
||||
|
||||
// chiamo calcolatore opportuno
|
||||
switch ( Curve1.GetType()) {
|
||||
switch ( CurveA.GetType()) {
|
||||
case CRV_LINE :
|
||||
switch ( Curve2.GetType()) {
|
||||
switch ( CurveB.GetType()) {
|
||||
case CRV_LINE :
|
||||
LineLineCalculate( Curve1, Curve2, bIsSegment) ;
|
||||
LineLineCalculate( CurveA, CurveB, bAreSegments) ;
|
||||
break ;
|
||||
case CRV_ARC :
|
||||
break ;
|
||||
case CRV_BEZ :
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
LineCrvCompoCalculate( CurveA, CurveB) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
@@ -53,30 +57,31 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& Curve1, const ICurve& Curve2,
|
||||
case CRV_BEZ :
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
switch ( Curve2.GetType()) {
|
||||
switch ( CurveB.GetType()) {
|
||||
case CRV_LINE :
|
||||
CrvCompoLineCalculate( CurveA, CurveB) ;
|
||||
break ;
|
||||
case CRV_ARC :
|
||||
break ;
|
||||
case CRV_BEZ :
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
CrvCompoCrvCompoCalculate( Curve1, Curve2) ;
|
||||
CrvCompoCrvCompoCalculate( CurveA, CurveB) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
|
||||
// salvo i puntatori alle curve
|
||||
m_pCurve[0] = &Curve1 ;
|
||||
m_pCurve[1] = &Curve2 ;
|
||||
m_pCurve[0] = &CurveA ;
|
||||
m_pCurve[1] = &CurveB ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
IntersCurveCurve::LineLineCalculate( const ICurve& Curve1, const ICurve& Curve2, bool bIsSegment)
|
||||
IntersCurveCurve::LineLineCalculate( const ICurve& CurveA, const ICurve& CurveB, bool bAreSegments)
|
||||
{
|
||||
IntersLineLine intLnLn( *GetCurveLine( &Curve1), *GetCurveLine( &Curve2), bIsSegment) ;
|
||||
IntersLineLine intLnLn( *GetCurveLine( &CurveA), *GetCurveLine( &CurveB), bAreSegments) ;
|
||||
|
||||
if ( intLnLn.m_nNumInters > 0) {
|
||||
m_bOverlaps = intLnLn.m_bOverlaps ;
|
||||
@@ -88,9 +93,31 @@ IntersCurveCurve::LineLineCalculate( const ICurve& Curve1, const ICurve& Curve2,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& Curve1, const ICurve& Curve2)
|
||||
IntersCurveCurve::LineCrvCompoCalculate( const ICurve& CurveA, const ICurve& CurveB)
|
||||
{
|
||||
IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( &Curve1), *GetCurveComposite( &Curve2)) ;
|
||||
// trasformo la linea 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)
|
||||
{
|
||||
// trasformo la linea 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)
|
||||
{
|
||||
IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( &CurveA), *GetCurveComposite( &CurveB)) ;
|
||||
|
||||
if ( intCcCc.m_nNumInters > 0) {
|
||||
m_bOverlaps = intCcCc.m_bOverlaps ;
|
||||
@@ -160,12 +187,9 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
|
||||
if ( ! m_Info[i].bCBOverEq)
|
||||
swap( dUStartTrim, dUEndTrim) ;
|
||||
}
|
||||
// !!! sistemare per curva chiusa con tratto che attraversa fine/inizio !!!
|
||||
PtrOwner<ICurve> pCrv( m_pCurve[nCrv]->Clone()) ;
|
||||
PtrOwner<ICurve> pCrv( m_pCurve[nCrv]->CopyParamRange( dUStartTrim, dUEndTrim)) ;
|
||||
if ( ! ::IsValid( pCrv))
|
||||
continue ;
|
||||
if ( ! pCrv->TrimStartEndAtParam( dUStartTrim, dUEndTrim))
|
||||
continue ;
|
||||
// cerco il punto
|
||||
int nFlag ;
|
||||
Point3d ptP ;
|
||||
@@ -183,3 +207,186 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
|
||||
|
||||
return bFound ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
|
||||
{
|
||||
// pulisco vettore classificazioni
|
||||
ccClass.clear() ;
|
||||
|
||||
// verifico definizione delle due curve
|
||||
if ( m_pCurve[0] == nullptr || m_pCurve[1] == nullptr)
|
||||
return false ;
|
||||
|
||||
// se richiesta classificazione della curva A
|
||||
if ( nCrv == 0) {
|
||||
// la curva rispetto a cui si classifica deve essere chiusa
|
||||
if ( ! m_pCurve[1]->IsClosed())
|
||||
return false ;
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nNumInters >= 1)
|
||||
return CalcCurveClassification( m_pCurve[0], m_Info, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
|
||||
}
|
||||
// se richiesta classificazione della curva B
|
||||
else if ( nCrv == 1) {
|
||||
// la curva rispetto a cui si classifica deve essere chiusa
|
||||
if ( ! m_pCurve[0]->IsClosed())
|
||||
return false ;
|
||||
// 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) ;
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nNumInters >= 1)
|
||||
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
|
||||
}
|
||||
// altrimenti errore
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, CRVCVECTOR& ccClass)
|
||||
{
|
||||
// numero intersezioni
|
||||
int nNumInters = int( Info.size()) ;
|
||||
if ( nNumInters < 1)
|
||||
return false ;
|
||||
// recupero il dominio parametrico della curva in esame
|
||||
double dStartPar, dEndPar ;
|
||||
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
// recupero la classificazione all'inizio della curva
|
||||
int nLastTy = ICCT_NULL ;
|
||||
double dCurrPar = dStartPar ;
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! Info[nNumInters-1].bOverlap)
|
||||
nLastTy = Info[nNumInters-1].IciA[0].nNextTy ;
|
||||
else {
|
||||
nLastTy = Info[nNumInters-1].IciA[1].nNextTy ;
|
||||
// se attraversa il punto di giunzione (parametro di fine minore di quello di inizio)
|
||||
if ( Info[nNumInters-1].IciA[1].dU < Info[nNumInters-1].IciA[0].dU) {
|
||||
dCurrPar = Info[nNumInters-1].IciA[1].dU ;
|
||||
dEndPar = dCurrPar ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
if ( Info[i].IciA[0].dU > dCurrPar + EPS_PARAM) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
int nPrevTy = Info[i].IciA[0].nPrevTy ;
|
||||
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
|
||||
nPrevTy == ICCT_NULL || nPrevTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = Info[i].IciA[0].dU ;
|
||||
segClass.nClass = (( nPrevTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = Info[i].IciA[0].dU ;
|
||||
nLastTy = Info[i].IciA[0].nNextTy ;
|
||||
}
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( Info[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = Info[i].IciA[1].dU ;
|
||||
segClass.nClass = ( Info[i].bCBOverEq ? CRVC_ON_P : CRVC_ON_M) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = Info[i].IciA[1].dU ;
|
||||
nLastTy = Info[i].IciA[1].nNextTy ;
|
||||
}
|
||||
}
|
||||
// eventuale tratto finale rimasto
|
||||
if ( dCurrPar < dEndPar - EPS_PARAM) {
|
||||
// verifico che la definizione sul tratto sia valida
|
||||
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = (( nLastTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB, CRVCVECTOR& ccClass)
|
||||
{
|
||||
// recupero il dominio parametrico della curva A
|
||||
double dStartPar, dEndPar ;
|
||||
if ( ! pCurveA->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
// se i box delle due curve non interferiscono è sicuramente esterna
|
||||
BBox3d boxCrvA, boxCrvB ;
|
||||
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
|
||||
! pCurveB->GetLocalBBox( boxCrvB))
|
||||
return false ;
|
||||
if ( ! boxCrvA.OverlapsXY( boxCrvB)) {
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
segClass.dParS = dStartPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = CRVC_OUT ;
|
||||
ccClass.push_back( segClass) ;
|
||||
return true ;
|
||||
}
|
||||
// intersezione tra una semiretta parallela a X dal punto iniziale della curva A e la curva B
|
||||
// costruisco la linea
|
||||
Point3d ptStart ;
|
||||
if ( ! pCurveA->GetStartPoint( ptStart))
|
||||
return false ;
|
||||
double dLen = boxCrvB.GetMax().x - boxCrvB.GetMin().x + 1. ;
|
||||
CurveLine clLine ;
|
||||
if ( ! clLine.SetPDL( ptStart, 0, dLen))
|
||||
return false ;
|
||||
// calcolo l'intersezione
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
// dichiaro la curva esterna per default
|
||||
int nClass = CRVC_OUT ;
|
||||
// se c'è almeno una intersezione
|
||||
if ( iCC.GetNumInters() > 0) {
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
IntCrvCrvInfo aInfo ;
|
||||
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
||||
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
nClass = CRVC_IN ;
|
||||
}
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
segClass.dParS = dStartPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = nClass ;
|
||||
ccClass.push_back( segClass) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user