EgtGeomKernel 2.2j2 :
- nella CurveComposite::MergeTwoCurves vengono eliminate le curve molto corte (minori di 10 volte la tolleranza lineare) - nell'offset avanzato migliorata gestione angoli interni per curve molto corte.
This commit is contained in:
+103
-74
@@ -2622,54 +2622,34 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd, bool bNeedSameProp)
|
||||
static int
|
||||
MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAngTol, bool bNeedSameProp)
|
||||
{
|
||||
// se non ci sono almeno 2 curve, esco subito
|
||||
if ( m_CrvSmplS.size() < 2)
|
||||
return true ;
|
||||
// controllo sui limiti di tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
dAngTolDeg = max( dAngTolDeg, EPS_ANG_SMALL) ;
|
||||
// tolleranza lineare corrente
|
||||
double dCurrLinTol = dLinTol ;
|
||||
// devo verificare coppie di curve
|
||||
auto iterP = m_CrvSmplS.begin() ;
|
||||
auto iterC = next( iterP) ;
|
||||
// mentre esiste la coppia
|
||||
while ( iterC != m_CrvSmplS.end()) {
|
||||
// se curve unite
|
||||
if ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dAngTolDeg, bNeedSameProp)) {
|
||||
// cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
iterC = m_CrvSmplS.erase( iterP) ;
|
||||
}
|
||||
// altrimenti ripristino la tolleranza
|
||||
else
|
||||
dCurrLinTol = dLinTol ;
|
||||
// avanzo
|
||||
iterP = iterC ;
|
||||
iterC = next( iterC) ;
|
||||
}
|
||||
// se richiesto e curva chiusa devo confrontare anche ultima e prima curva
|
||||
if ( bStartEnd && IsClosed()) {
|
||||
if ( MergeTwoCurves( *iterP, *(m_CrvSmplS.begin()), dCurrLinTol, dAngTolDeg, bNeedSameProp)) {
|
||||
// cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
iterC = m_CrvSmplS.erase( iterP) ;
|
||||
// se precedente molto corta
|
||||
double dLenP ;
|
||||
if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) {
|
||||
// se abbastanza allineata alla successiva
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptStart ;
|
||||
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
|
||||
}
|
||||
}
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dAngTolDeg, bool bNeedSameProp)
|
||||
{
|
||||
// se corrente molto corta
|
||||
double dLenC ;
|
||||
if ( pCrvC->GetLength( dLenC) && dLenC < dCurrLinTol) {
|
||||
// se abbastanza allineata alla precedente
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptEnd ;
|
||||
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
|
||||
}
|
||||
}
|
||||
// verifico compatibilità delle proprietà
|
||||
int nTprP = pCrvP->GetTempProp() ;
|
||||
int nTprC = pCrvC->GetTempProp() ;
|
||||
if ( bNeedSameProp && nTprP != nTprC)
|
||||
return 0 ;
|
||||
// coefficiente deduzione tolleranza
|
||||
const double COEFF_TOL = 0.7 ;
|
||||
// se entrambe rette
|
||||
@@ -2680,26 +2660,20 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pLineP != nullptr && pLineP->GetStartDir( vtDirP) &&
|
||||
pLineC != nullptr && pLineC->GetStartDir( vtDirC) &&
|
||||
( vtDirP * vtDirC) >= cos( dAngTolDeg * DEGTORAD)) {
|
||||
// recupero le proprietà
|
||||
int nTprP = pLineP->GetTempProp() ;
|
||||
int nTprC = pLineC->GetTempProp() ;
|
||||
( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
// verifico se il punto di giunzione sia eliminabile
|
||||
DistPointLine dPL( pLineP->GetEnd(), pLineP->GetStart(), pLineC->GetEnd()) ;
|
||||
double dSqDist ;
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrLinTol * dCurrLinTol &&
|
||||
( ! bNeedSameProp || nTprP == nTprC)) {
|
||||
// se calcolo nuova linea ok, procedo con l'unione
|
||||
CurveLine NewLine ;
|
||||
if ( NewLine.Set( pLineP->GetStart(), pLineC->GetEnd())) {
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrLinTol * dCurrLinTol) {
|
||||
// se modifica linea corrente ok, procedo con l'unione
|
||||
if ( pLineC->ModifyStart( pLineP->GetStart())) {
|
||||
// diminuisco la tolleranza corrente dell'errore attuale
|
||||
dCurrLinTol -= COEFF_TOL * sqrt( dSqDist) ;
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTprP == nTprC)
|
||||
NewLine.SetTempProp( nTprC) ;
|
||||
// aggiorno la linea corrente e torno flag modifica
|
||||
*pLineC = NewLine ;
|
||||
return true ;
|
||||
// se curve originali con proprietà diversa, la cancello
|
||||
if ( nTprP != nTprC)
|
||||
pLineC->SetTempProp( 0) ;
|
||||
// torno flag modifica
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2714,20 +2688,20 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo
|
||||
Point3d ptC2Ini = pArcC->GetCenter() ;
|
||||
// verifico la coincidenza dei centri
|
||||
if ( ! AreSamePointEpsilon( ptC1Fin, ptC2Ini, dCurrLinTol))
|
||||
return false ;
|
||||
return 0 ;
|
||||
// verifico la coincidenza dei raggi
|
||||
if ( abs( pArcP->GetRadius() - pArcC->GetRadius()) > dCurrLinTol)
|
||||
return false ;
|
||||
return 0 ;
|
||||
// verifico la collinearità delle normali (tenendo conto del raggio)
|
||||
if ( ! (( pArcP->GetNormVersor() - pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall() &&
|
||||
! (( pArcP->GetNormVersor() + pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall())
|
||||
return false ;
|
||||
return 0 ;
|
||||
// verifico la coincidenza del senso di rotazione (verso delle normali e segno angoli al centro)
|
||||
if ( pArcP->GetNormVersor() * pArcC->GetNormVersor() * pArcP->GetAngCenter() * pArcC->GetAngCenter() < 0)
|
||||
return false ;
|
||||
return 0 ;
|
||||
// verifico di non superare l'angolo giro al centro
|
||||
if ( abs( pArcP->GetAngCenter() + pArcC->GetAngCenter()) > ANG_FULL + EPS_ANG_SMALL)
|
||||
return false ;
|
||||
return 0 ;
|
||||
// se archi piatti
|
||||
if ( pArcP->IsPlane() && pArcC->IsPlane()) {
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
@@ -2747,16 +2721,14 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
int nTprP = pArcP->GetTempProp() ;
|
||||
int nTprC = pArcC->GetTempProp() ;
|
||||
if ( nTprP == nTprC)
|
||||
NewArc.SetTempProp( nTprC) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return true ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
return 0 ;
|
||||
}
|
||||
// verifico coincidenza pendenza sulla normale
|
||||
double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ;
|
||||
@@ -2772,24 +2744,81 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) {
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
int nTprP = pArcP->GetTempProp() ;
|
||||
int nTprC = pArcC->GetTempProp() ;
|
||||
if ( nTprP == nTprC)
|
||||
NewArc.SetTempProp( nTprC) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return true ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
// nessuna fusione
|
||||
return false ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd, bool bNeedSameProp)
|
||||
{
|
||||
// se non ci sono almeno 2 curve, esco subito
|
||||
if ( m_CrvSmplS.size() < 2)
|
||||
return true ;
|
||||
// controllo sui limiti di tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
dAngTolDeg = max( dAngTolDeg, EPS_ANG_SMALL) ;
|
||||
double dCosAngTol = cos( dAngTolDeg * DEGTORAD) ;
|
||||
// tolleranza lineare corrente
|
||||
double dCurrLinTol = dLinTol ;
|
||||
// devo verificare coppie di curve
|
||||
auto iterP = m_CrvSmplS.begin() ;
|
||||
auto iterC = next( iterP) ;
|
||||
// mentre esiste la coppia
|
||||
while ( iterC != m_CrvSmplS.end()) {
|
||||
// se curve unite
|
||||
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
iterC = m_CrvSmplS.erase( iterP) ;
|
||||
break ;
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
delete (*iterC) ;
|
||||
iterC = m_CrvSmplS.erase( iterC) ;
|
||||
iterC = prev( iterC) ;
|
||||
break ;
|
||||
default : // ripristino la tolleranza
|
||||
dCurrLinTol = dLinTol ;
|
||||
break ;
|
||||
}
|
||||
// avanzo
|
||||
iterP = iterC ;
|
||||
iterC = next( iterC) ;
|
||||
}
|
||||
// se richiesto e curva chiusa devo confrontare anche ultima e prima curva
|
||||
if ( bStartEnd && m_CrvSmplS.size() >= 2 && IsClosed()) {
|
||||
iterC = m_CrvSmplS.begin() ;
|
||||
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
m_CrvSmplS.erase( iterP) ;
|
||||
break ;
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
delete (*iterC) ;
|
||||
m_CrvSmplS.erase( iterC) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SplitTopBottomArcs( CurveComposite& cCompo)
|
||||
{
|
||||
int i = 0 ;
|
||||
|
||||
@@ -181,7 +181,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
|
||||
bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ;
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
|
||||
bool MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dAngTolDeg, bool bNeedSameProp) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
|
||||
private :
|
||||
|
||||
Binary file not shown.
+48
-14
@@ -1,13 +1,14 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2019
|
||||
// EgalTech 2015-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetCurve.cpp Data : 24.06.19 Versione : 2.1f2
|
||||
// File : OffsetCurve.cpp Data : 10.10.20 Versione : 2.2j2
|
||||
// Contenuto : Classe per offset avanzato di Curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 23.09.15 DS Creazione modulo.
|
||||
// 24.06.19 DS Agg. GetShorterCurve.
|
||||
// 10.10.20 DS Migliorata gestione angoli interni.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -32,8 +33,8 @@ static bool PreviousIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed) ;
|
||||
static bool NextIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool bClosed) ;
|
||||
static bool NextIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed) ;
|
||||
static bool CalcAngle( const ICurve* pCrv1, const ICurve* pCrv2, double& dAngDeg) ;
|
||||
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2) ;
|
||||
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2) ;
|
||||
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes) ;
|
||||
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes) ;
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, double dDist, int nType,
|
||||
CurveComposite& ccAux) ;
|
||||
static double GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) ;
|
||||
@@ -283,8 +284,27 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
ICurve* pCrv = *iIter ;
|
||||
// gestione e verifica di estremi quasi coincidenti ed angoli interni
|
||||
if ( pPrev != nullptr) {
|
||||
if ( ! VerifyAndAdjustSamePoint( pPrev, pCrv))
|
||||
VerifyAndAdjustInternalAngle( pPrev, pCrv) ;
|
||||
int nRes ;
|
||||
if ( VerifyAndAdjustSamePoint( pPrev, pCrv, nRes)) {
|
||||
if ( nRes == 4)
|
||||
VerifyAndAdjustInternalAngle( pPrev, pCrv, nRes) ;
|
||||
// precedente da cancellare
|
||||
if ( ( nRes & 1) != 0) {
|
||||
auto iErase = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ;
|
||||
delete pPrev ;
|
||||
m_CrvLst.erase( iErase) ;
|
||||
auto iPrev = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ;
|
||||
pPrev = *iPrev ;
|
||||
}
|
||||
// corrente da cancellare
|
||||
if ( ( nRes & 2) != 0) {
|
||||
delete pCrv ;
|
||||
iIter = m_CrvLst.erase( iIter) ;
|
||||
}
|
||||
// se eseguita una cancellazione, non devo incrementare
|
||||
if ( ( nRes & 3) != 0)
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
pPrev = pCrv ;
|
||||
@@ -742,7 +762,7 @@ CalcAngle( const ICurve* pCrv1, const ICurve* pCrv2, double& dAngDeg)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2)
|
||||
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
@@ -753,19 +773,28 @@ VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2)
|
||||
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
||||
return false ;
|
||||
// verifica distanza tra estremi
|
||||
if ( ! AreSamePointXYEpsilon( ptP1, ptP2, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
// se coincidono esattamente, va bene così
|
||||
if ( AreSamePointExact( ptP1, ptP2))
|
||||
if ( ! AreSamePointXYEpsilon( ptP1, ptP2, 10 * EPS_SMALL)) {
|
||||
nRes = 4 ;
|
||||
return true ;
|
||||
}
|
||||
// se coincidono esattamente, va bene così
|
||||
if ( AreSamePointExact( ptP1, ptP2)) {
|
||||
nRes = 0 ;
|
||||
return true ;
|
||||
}
|
||||
// sono in tolleranza, ma devo ricongiungere gli estremi
|
||||
nRes = 0 ;
|
||||
Point3d ptMid = 0.5 * ( ptP1 + ptP2) ;
|
||||
return ( pCrv1->ModifyEnd( ptMid) && pCrv2->ModifyStart( ptMid)) ;
|
||||
if ( ! pCrv1->ModifyEnd( ptMid))
|
||||
nRes += 1 ;
|
||||
if ( ! pCrv2->ModifyStart( ptMid))
|
||||
nRes += 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2)
|
||||
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
@@ -785,8 +814,13 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2)
|
||||
! intCC.GetIntersPointNearTo( 1, ptMid, ptNew2))
|
||||
return false ;
|
||||
// modifico le due curve sul punto medio di intersezione
|
||||
nRes = 0 ;
|
||||
Point3d ptNew = 0.5 * ( ptNew1 + ptNew2) ;
|
||||
return ( pCrv1->ModifyEnd( ptNew) && pCrv2->ModifyStart( ptNew)) ;
|
||||
if ( ! pCrv1->ModifyEnd( ptNew))
|
||||
nRes += 1 ;
|
||||
if ( ! pCrv2->ModifyStart( ptNew))
|
||||
nRes += 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user