Compare commits
81 Commits
2024/01/09
...
ArcBox
| Author | SHA1 | Date | |
|---|---|---|---|
| 68800a1dfa | |||
| 4f60bd24b6 | |||
| 2f3a6189a7 | |||
| 078f730512 | |||
| 368bd80c69 | |||
| e01941644b | |||
| 0f3bd716a3 | |||
| 0030b684f3 | |||
| 6e6be4e579 | |||
| 3add582efb | |||
| bd80f16812 | |||
| ffc78b03a7 | |||
| 2f6a1f7579 | |||
| e890d5f376 | |||
| 56b49d4c9f | |||
| 7ee0e38cec | |||
| 817bfa788e | |||
| a4bd5a25c2 | |||
| 7c3b3e516a | |||
| 9e3c8b697a | |||
| 775fec489b | |||
| 790a75054c | |||
| b57421e2c9 | |||
| a7dea8b1db | |||
| 2808a95e4a | |||
| e0a350b148 | |||
| 560a447349 | |||
| 700b2ad5ca | |||
| 85d677a41a | |||
| cc200501e9 | |||
| d59cb55139 | |||
| 46052e9d1f | |||
| b36baf0fab | |||
| f2499d08ba | |||
| 651b34781b | |||
| c57a6db4ae | |||
| 78b9234865 | |||
| 6238ea1095 | |||
| de99955e93 | |||
| c45912a2e4 | |||
| 025b4a8b48 | |||
| a5802f0731 | |||
| 4f0a1460fd | |||
| 498e5b37f4 | |||
| fe0a6ad15d | |||
| 13774ba26a | |||
| d1b22114d0 | |||
| 3f2b6b2115 | |||
| bb8c0f766e | |||
| 76e490a583 | |||
| ae91e1c51f | |||
| 4aff949349 | |||
| 3dcceecab7 | |||
| 7b6f1c3e92 | |||
| b107596f84 | |||
| b11de227f3 | |||
| f353e65e61 | |||
| de34cfb7e8 | |||
| cb882b9379 | |||
| f43951a9e2 | |||
| 899e371c52 | |||
| 555e0e4375 | |||
| 8710115634 | |||
| 4056be90d9 | |||
| 77640f3a6f | |||
| 9b11212d07 | |||
| 41d76f0c3f | |||
| d2b77833fd | |||
| 9ac1a56535 | |||
| 9aca1f1e25 | |||
| e3c10e9bd3 | |||
| e84a34917a | |||
| 009328b31b | |||
| ca83aaa249 | |||
| 6cdfdf6db8 | |||
| 6628b1ee24 | |||
| 2d70d27d85 | |||
| 63d62fcc92 | |||
| b4303d0e0d | |||
| 9369447886 | |||
| dca713b240 |
+84
-21
@@ -15,15 +15,30 @@
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "RemoveCurveSpikes.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "AdjustLoops.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------
|
||||
static bool
|
||||
SortCrvCrvInfo( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2)
|
||||
{
|
||||
// confronto i valori del primo punto della curva A
|
||||
double dU1 = aInfo1.IciA[0].dU ;
|
||||
double dU2 = aInfo2.IciA[0].dU ;
|
||||
if ( abs( dU1 - dU2) < EPS_SMALL)
|
||||
// se sono uguali confronto i valori del primo punto della curva B
|
||||
return aInfo1.IciB[0].dU > aInfo2.IciB[0].dU ;
|
||||
else
|
||||
return dU1 < dU2 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
@@ -73,43 +88,75 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
return false ;
|
||||
Intervals inOk( EPS_PARAM) ;
|
||||
inOk.Set( dStart, dEnd) ;
|
||||
|
||||
// Tolgo le parti da eliminare
|
||||
|
||||
// recupero tutte le info delle autointersezioni
|
||||
IntCrvCrvInfo iccInfo ;
|
||||
for ( int i = 0 ; sintC.GetIntCrvCrvInfo( i, iccInfo) ; ++ i) {
|
||||
ICCIVECTOR vIccInfo( sintC.GetIntersCount()) ;
|
||||
for ( int i = 0 ; sintC.GetIntCrvCrvInfo( i, iccInfo) ; ++ i)
|
||||
vIccInfo[i]= iccInfo ;
|
||||
// ordino il vettore
|
||||
sort( vIccInfo.begin(), vIccInfo.end(), SortCrvCrvInfo) ;
|
||||
|
||||
// Tolgo le parti da eliminare
|
||||
int nCross = 0 ;
|
||||
for ( int i = 0 ; i < int( vIccInfo.size()) ; ++ i) {
|
||||
|
||||
if ( i < int( vIccInfo.size()) - 1) {
|
||||
// se anche l'intersezione successiva è overlap che parte dallo stesso punto
|
||||
if ( vIccInfo[i].bOverlap && vIccInfo[i+1].bOverlap &&
|
||||
abs( vIccInfo[i].IciA[0].dU - vIccInfo[i+1].IciA[0].dU) < EPS_SMALL &&
|
||||
abs( vIccInfo[i].IciB[0].dU - vIccInfo[i+1].IciB[0].dU) < EPS_SMALL) {
|
||||
// elimino il tratto
|
||||
inOk.Subtract( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciB[0].dU) ;
|
||||
// salto le intersezioni successive già considerate rimuovendo questo intervallo
|
||||
int j = i + 2 ;
|
||||
while ( j < ( int)vIccInfo.size() && vIccInfo[j].IciA[0].dU > vIccInfo[i].IciA[0].dU - EPS_SMALL &&
|
||||
vIccInfo[j].IciA[1].dU < vIccInfo[i].IciB[0].dU + EPS_SMALL) {
|
||||
j ++ ;
|
||||
}
|
||||
// aggiorno il contatore
|
||||
i = j - 1 ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
|
||||
// se con sovrapposizione
|
||||
if ( iccInfo.bOverlap) {
|
||||
if ( vIccInfo[i].bOverlap) {
|
||||
// se solo touch
|
||||
if ( ( iccInfo.IciA[0].nPrevTy == iccInfo.IciA[1].nNextTy ||
|
||||
iccInfo.IciA[0].nPrevTy == ICCT_SPK || iccInfo.IciA[1].nNextTy == ICCT_SPK) &&
|
||||
iccInfo.IciA[0].nPrevTy != ICCT_NULL && iccInfo.IciA[1].nNextTy != ICCT_NULL) {
|
||||
if ( ( vIccInfo[i].IciA[0].nPrevTy == vIccInfo[i].IciA[1].nNextTy ||
|
||||
vIccInfo[i].IciA[0].nPrevTy == ICCT_SPK || vIccInfo[i].IciA[1].nNextTy == ICCT_SPK) &&
|
||||
vIccInfo[i].IciA[0].nPrevTy != ICCT_NULL && vIccInfo[i].IciA[1].nNextTy != ICCT_NULL) {
|
||||
// obbligatoriamente controversi, elimino entrambi i tratti
|
||||
inOk.Subtract( iccInfo.IciA[0].dU, iccInfo.IciA[1].dU) ;
|
||||
inOk.Subtract( iccInfo.IciB[0].dU, iccInfo.IciB[1].dU) ;
|
||||
inOk.Subtract( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciA[1].dU) ;
|
||||
inOk.Subtract( vIccInfo[i].IciB[0].dU, vIccInfo[i].IciB[1].dU) ;
|
||||
}
|
||||
// altrimenti attraversamento
|
||||
else {
|
||||
// elimino la parte interna
|
||||
if ( iccInfo.bCBOverEq)
|
||||
inOk.Subtract( iccInfo.IciA[0].dU, iccInfo.IciB[0].dU) ;
|
||||
if ( vIccInfo[i].bCBOverEq)
|
||||
inOk.Subtract( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciB[0].dU) ;
|
||||
else
|
||||
inOk.Subtract( min( iccInfo.IciA[0].dU, iccInfo.IciB[1].dU), max( iccInfo.IciB[0].dU, iccInfo.IciA[1].dU)) ;
|
||||
inOk.Subtract( min( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciB[1].dU), max( vIccInfo[i].IciB[0].dU, vIccInfo[i].IciA[1].dU)) ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
// se solo touch
|
||||
if ( iccInfo.IciA[0].nPrevTy == iccInfo.IciA[0].nNextTy &&
|
||||
iccInfo.IciA[0].nPrevTy != ICCT_NULL && iccInfo.IciA[0].nNextTy != ICCT_NULL) {
|
||||
inOk.Subtract( iccInfo.IciA[0].dU, iccInfo.IciA[0].dU) ;
|
||||
inOk.Subtract( iccInfo.IciB[0].dU, iccInfo.IciB[0].dU) ;
|
||||
if ( vIccInfo[i].IciA[0].nPrevTy == vIccInfo[i].IciA[0].nNextTy &&
|
||||
vIccInfo[i].IciA[0].nPrevTy != ICCT_NULL && vIccInfo[i].IciA[0].nNextTy != ICCT_NULL) {
|
||||
inOk.Subtract( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciA[0].dU) ;
|
||||
inOk.Subtract( vIccInfo[i].IciB[0].dU, vIccInfo[i].IciB[0].dU) ;
|
||||
}
|
||||
// altrimenti attraversamento
|
||||
else {
|
||||
inOk.Subtract( iccInfo.IciA[0].dU, iccInfo.IciB[0].dU) ;
|
||||
if ( IsEven( nCross))
|
||||
inOk.Subtract( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciB[0].dU) ;
|
||||
else
|
||||
inOk.Add( vIccInfo[i].IciA[0].dU, vIccInfo[i].IciB[0].dU) ;
|
||||
++ nCross ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copio le parti da conservare
|
||||
double dParS, dParE ;
|
||||
@@ -201,6 +248,22 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
++ iIter ;
|
||||
}
|
||||
|
||||
// elimino le curve troppo piccole
|
||||
for ( auto iIter = CrvLst.begin() ; iIter != CrvLst.end() ;) {
|
||||
CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ;
|
||||
BBox3d b3CrvCo ;
|
||||
double dDiam ;
|
||||
if ( ! pCrvCo->GetLocalBBox( b3CrvCo) || b3CrvCo.IsEmpty() ||
|
||||
! b3CrvCo.GetDiameter( dDiam) || dDiam < 20 * EPS_SMALL) {
|
||||
delete pCrvCo ;
|
||||
pCrvCo = nullptr ;
|
||||
iIter = CrvLst.erase( iIter) ;
|
||||
}
|
||||
else {
|
||||
++ iIter ;
|
||||
}
|
||||
}
|
||||
|
||||
// riporto le curve nel riferimento originale
|
||||
if ( bNeedRef) {
|
||||
for ( auto pCrv : CrvLst)
|
||||
@@ -225,10 +288,10 @@ AdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
// se curva composita
|
||||
CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
|
||||
if ( pCrvCo != nullptr) {
|
||||
// elimino eventuali Spikes e Small Z
|
||||
pCrvCo->RemoveSmallDefects( 2 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ;
|
||||
// unisco eventuali tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
// elimino eventuali spikes
|
||||
RemoveCurveSpikes( pCrvCo) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,3 +63,57 @@ AngleInSpan( double dAngDeg, double dAngRefDeg, double dAngSpanDeg)
|
||||
dAngDiffDeg < dHalfAngSpanDeg + EPS_ANG_SMALL) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AngleInRange( double dAngDeg, double dAngMinDeg, double dAngMaxDeg)
|
||||
{
|
||||
return AngleInSpan( dAngDeg, ( dAngMinDeg + dAngMaxDeg) / 2, dAngMaxDeg - dAngMinDeg) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustAngleInSpan( double& dAngDeg, double dAngRefDeg, double dAngSpanDeg)
|
||||
{
|
||||
// Verifico consistenza intervallo
|
||||
if ( dAngSpanDeg < -EPS_ANG_ZERO)
|
||||
return false ;
|
||||
// Se intervallo vero
|
||||
if ( dAngSpanDeg > EPS_ANG_SMALL) {
|
||||
double dTryDeg = dAngDeg ;
|
||||
// eseguo gli aggiustamenti
|
||||
while ( dTryDeg < dAngRefDeg - dAngSpanDeg)
|
||||
dTryDeg += ANG_FULL ;
|
||||
while ( dTryDeg > dAngRefDeg + dAngSpanDeg)
|
||||
dTryDeg -= ANG_FULL ;
|
||||
// verifico
|
||||
if ( dTryDeg >= dAngRefDeg - dAngSpanDeg && dTryDeg <= dAngRefDeg + dAngSpanDeg) {
|
||||
dAngDeg = dTryDeg ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
// altrimenti un valore
|
||||
else {
|
||||
double dTryDeg = dAngDeg ;
|
||||
// eseguo gli aggiustamenti
|
||||
while ( dTryDeg < dAngRefDeg - EPS_ANG_SMALL)
|
||||
dTryDeg += ANG_FULL ;
|
||||
while ( dTryDeg > dAngRefDeg + EPS_ANG_SMALL)
|
||||
dTryDeg -= ANG_FULL ;
|
||||
// verifico
|
||||
if ( abs( dTryDeg - dAngRefDeg) < EPS_ANG_SMALL) {
|
||||
dAngDeg = dAngRefDeg ;
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustAngleInRange( double& dAngDeg, double dAngMinDeg, double dAngMaxDeg)
|
||||
{
|
||||
return AdjustAngleInSpan( dAngDeg, ( dAngMinDeg + dAngMaxDeg) / 2, dAngMaxDeg - dAngMinDeg) ;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkArcCenTgCurvePnt.h"
|
||||
#include "/EgtDev/Include/EgkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EgkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkArcCenTgCurvePnt.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkArcPntDirTgCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkArcPntDirTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
|
||||
+57
-35
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2015
|
||||
// EgalTech 2014-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ArcSpecial.cpp Data : 15.03.15 Versione : 1.6c2
|
||||
// File : ArcSpecial.cpp Data : 18.08.22 Versione : 2.4h2
|
||||
// Contenuto : Implementazione funzioni per calcoli speciali archi.
|
||||
//
|
||||
//
|
||||
@@ -14,8 +14,8 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "/EgtDev/Include/EgkCurveLine.h"
|
||||
#include "/EgtDev/Include/EgkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -28,15 +28,13 @@ ICurve*
|
||||
GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg)
|
||||
{
|
||||
// creo l'oggetto arco
|
||||
ICurveArc* pArc = CreateCurveArc() ;
|
||||
if ( pArc == nullptr)
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
||||
if ( IsNull( pArc))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con l'arco
|
||||
PtrOwner<ICurve> pCrv( pArc) ;
|
||||
|
||||
// calcolo l'arco, se ok lo restituisco ed esco
|
||||
if ( pArc->Set2PD( ptStart, ptEnd, dDirStartDeg))
|
||||
return Release( pCrv) ;
|
||||
return Release( pArc) ;
|
||||
|
||||
// calcolo arco non riuscito, verifico se retta va bene
|
||||
Vector3d vtDiff = ptEnd - ptStart ;
|
||||
@@ -45,14 +43,12 @@ GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg)
|
||||
// verifico se i punti sono allineati con la direzione e nel giusto verso
|
||||
if ( abs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) {
|
||||
// creo l'oggetto retta
|
||||
ICurveLine* pLine = CreateCurveLine() ;
|
||||
if ( pLine == nullptr)
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con la retta
|
||||
pCrv.Set( pLine) ;
|
||||
// calcolo retta, se ok la restituisco ed esco
|
||||
if ( pLine->Set( ptStart, ptEnd))
|
||||
return Release( pCrv) ;
|
||||
return Release( pLine) ;
|
||||
}
|
||||
|
||||
return nullptr ;
|
||||
@@ -65,29 +61,25 @@ ICurve*
|
||||
GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS, const Vector3d& vtN)
|
||||
{
|
||||
// creo l'oggetto arco
|
||||
ICurveArc* pArc = CreateCurveArc() ;
|
||||
if ( pArc == nullptr)
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
||||
if ( IsNull( pArc))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con l'arco
|
||||
PtrOwner<ICurve> pCrv( pArc) ;
|
||||
|
||||
// calcolo l'arco, se ok lo restituisco ed esco
|
||||
if ( pArc->Set2PVN( ptStart, ptEnd, vtDirS, vtN))
|
||||
return Release( pCrv) ;
|
||||
return Release( pArc) ;
|
||||
|
||||
// calcolo arco non riuscito, verifico se retta va bene
|
||||
Vector3d vtDiff = ptEnd - ptStart ;
|
||||
// verifico se i punti sono allineati con la direzione e nel giusto verso nel piano perpendicolare a vtN
|
||||
if ( abs( ( vtDiff ^ vtDirS) * vtN) < EPS_SMALL && vtDiff * vtDirS > EPS_SMALL) {
|
||||
// creo l'oggetto retta
|
||||
ICurveLine* pLine = CreateCurveLine() ;
|
||||
if ( pLine == nullptr)
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con la retta
|
||||
pCrv.Set( pLine) ;
|
||||
// calcolo retta, se ok la restituisco ed esco
|
||||
if ( pLine->Set( ptStart, ptEnd))
|
||||
return Release( pCrv) ;
|
||||
return Release( pLine) ;
|
||||
}
|
||||
|
||||
return nullptr ;
|
||||
@@ -100,17 +92,15 @@ ICurve*
|
||||
GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, bool bCirc)
|
||||
{
|
||||
// creo l'oggetto arco
|
||||
ICurveArc* pArc = CreateCurveArc() ;
|
||||
if ( pArc == nullptr)
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
||||
if ( IsNull( pArc))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con l'arco
|
||||
PtrOwner<ICurve> pCrv( pArc) ;
|
||||
|
||||
// calcolo l'arco, se ok lo restituisco ed esco
|
||||
if ( pArc->Set3P( ptStart, ptOther, ptEnd, bCirc))
|
||||
return Release( pCrv) ;
|
||||
return Release( pArc) ;
|
||||
|
||||
// se era richiesta una circonferenza, errore
|
||||
// se era richiesta una circonferenza, errore perchè punti allineati
|
||||
if ( bCirc)
|
||||
return nullptr ;
|
||||
|
||||
@@ -118,15 +108,47 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd,
|
||||
// verifico se i punti sono allineati nel giusto verso
|
||||
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) {
|
||||
// creo l'oggetto retta
|
||||
ICurveLine* pLine = CreateCurveLine() ;
|
||||
if ( pLine == nullptr)
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
return nullptr ;
|
||||
// inizializzo il puntatore a curva con la retta
|
||||
pCrv.Set( pLine) ;
|
||||
// calcolo retta, se ok la restituisco ed esco
|
||||
if ( pLine->Set( ptStart, ptEnd))
|
||||
return Release( pCrv) ;
|
||||
return Release( pLine) ;
|
||||
}
|
||||
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Come la CurveArc::SetC2PN, ma garantisce il passaggio per gli estremi e minimizza errore sul centro
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveArc*
|
||||
GetArc2PCN( const Point3d& ptStart, const Point3d& ptEnd, const Point3d& ptNearCen, const Vector3d& vtN)
|
||||
{
|
||||
// creo l'oggetto arco
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
||||
if ( IsNull( pArc))
|
||||
return nullptr ;
|
||||
|
||||
// vettori dal centro a inizio e fine
|
||||
Vector3d vtStart = ptStart - ptNearCen ;
|
||||
Vector3d vtEnd = ptEnd - ptNearCen ;
|
||||
|
||||
// determino il raggio medio
|
||||
double dStartRad = OrthoCompo( vtStart, vtN).Len() ;
|
||||
double dEndRad = OrthoCompo( vtEnd, vtN).Len() ;
|
||||
double dRad = ( dStartRad + dEndRad) / 2 ;
|
||||
if ( dRad < EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// determino un valore approssimato dell'angolo al centro
|
||||
double dAngDeg ; bool bDet ;
|
||||
if ( ! vtStart.GetRotation( vtEnd, vtN, dAngDeg, bDet) || ! bDet || abs( dAngDeg) < EPS_ANG_ZERO)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo l'arco antiorario per i due punti con il raggio medio
|
||||
if ( pArc->Set2PNRS( ptStart, ptEnd, vtN, dRad, ( dAngDeg > 0)))
|
||||
return Release( pArc) ;
|
||||
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
+19
-3
@@ -18,7 +18,7 @@
|
||||
#include "NgeReader.h"
|
||||
#include "GeomDB.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgnStringKeyVal.h"
|
||||
#include "/EgtDev/Include/EGnStringKeyVal.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -212,7 +212,7 @@ bool
|
||||
Attribs::SetName( const string& sName)
|
||||
{
|
||||
// se nome non valido, esco con errore
|
||||
if ( ! IsValidVal( sName))
|
||||
if ( sName.empty() || ! IsValidVal( sName))
|
||||
return false ;
|
||||
|
||||
// può essere solo la prima stringa
|
||||
@@ -282,7 +282,7 @@ bool
|
||||
Attribs::SetInfo( const string& sKey, const string& sVal)
|
||||
{
|
||||
// se chiave o valore non validi, esco con errore
|
||||
if ( ! IsValidKey( sKey) || ! IsValidVal( sVal))
|
||||
if ( ! IsValidKey( sKey) || sVal.empty() || ! IsValidVal( sVal))
|
||||
return false ;
|
||||
|
||||
// se è il nome
|
||||
@@ -356,6 +356,22 @@ Attribs::RemoveInfo( const string& sKey)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Attribs::GetAllInfo( STRVECTOR& vsInfo) const
|
||||
{
|
||||
// riservo spazio opportuno per il vettore delle stringhe
|
||||
vsInfo.clear() ;
|
||||
vsInfo.reserve( m_slInfo.size()) ;
|
||||
// recupero tutte le info tranne il nome (se presente sempre al primo posto)
|
||||
auto iIter = m_slInfo.cbegin() ;
|
||||
if ( FindKey( *iIter, NAME))
|
||||
++ iIter ;
|
||||
for ( ; iIter != m_slInfo.cend() ; ++ iIter)
|
||||
vsInfo.emplace_back( *iIter) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Attribs::CopyAllInfoFrom( const Attribs& attrSou)
|
||||
|
||||
@@ -89,6 +89,7 @@ class Attribs
|
||||
bool GetInfo( const std::string& sKey, std::string& sVal) const ;
|
||||
bool ExistsInfo( const std::string& sKey) const ;
|
||||
bool RemoveInfo( const std::string& sKey) ;
|
||||
bool GetAllInfo( STRVECTOR& vsInfo) const ;
|
||||
bool CopyAllInfoFrom( const Attribs& attrSou) ;
|
||||
|
||||
private :
|
||||
@@ -100,7 +101,7 @@ class Attribs
|
||||
private :
|
||||
unsigned char m_Data[DIM] ;
|
||||
unsigned char m_OldData[DIM] ;
|
||||
int m_Material ;
|
||||
Color m_Color ;
|
||||
STRLIST m_slInfo ;
|
||||
int m_Material ;
|
||||
Color m_Color ;
|
||||
STRLIST m_slInfo ;
|
||||
} ;
|
||||
+29
-2
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
// EgalTech 2014-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : BBox3d.cpp Data : 14.01.14 Versione : 1.5a3
|
||||
// File : BBox3d.cpp Data : 17.08.22 Versione : 2.4h1
|
||||
// Contenuto : Implementazione della classe axis aligned bounding box BBox3d.
|
||||
//
|
||||
//
|
||||
@@ -210,6 +210,33 @@ BBox3d::GetMinDim( Point3d& ptMin, double& dDimX, double& dDimY, double& dDimZ)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
BBox3d::GetDimX( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
return ( m_ptMax.x - m_ptMin.x) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
BBox3d::GetDimY( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
return ( m_ptMax.y - m_ptMin.y) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
BBox3d::GetDimZ( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
return ( m_ptMax.z - m_ptMin.z) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
BBox3d::GetCenterExtent( Point3d& ptCenter, Vector3d& vtExtent) const
|
||||
|
||||
+3
-3
@@ -16,9 +16,9 @@
|
||||
#include "BiArcs.h"
|
||||
#include "CurveArc.h"
|
||||
#include "/EgtDev/Include/EGkAngle.h"
|
||||
#include "/EgtDev/Include/EgkCurveLine.h"
|
||||
#include "/EgtDev/Include/EgkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EgkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EgkBiArcs.h"
|
||||
#include "/EgtDev/Include/EGkBiArcs.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ICurve* GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
|
||||
|
||||
@@ -27,9 +27,10 @@ CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDi
|
||||
BBox3d b3Poly = Stm.GetAllTriaBox() ;
|
||||
// calcolo il BBox del parallelepipedo
|
||||
BBox3d b3Box( ORIG, ORIG + vtDiag) ;
|
||||
b3Box.Expand( dSafeDist) ;
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3Box.Expand( dSafeDist) ;
|
||||
b3Box.ToGlob( frBox) ;
|
||||
// confronto i due Box
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Box.Overlaps( b3Poly))
|
||||
return false ;
|
||||
// recupero i triangoli che interferiscono con il box
|
||||
@@ -46,9 +47,9 @@ CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDi
|
||||
if ( ! Stm.IsClosed())
|
||||
return false ;
|
||||
// Verifico se il box è dentro la superficie tramite calcolo distanza minima.
|
||||
Point3d ptBoxOrig, ptBoxMax ;
|
||||
b3Box.GetMinMax( ptBoxOrig, ptBoxMax) ;
|
||||
DistPointSurfTm DistBoxOrigSurfCalc( ptBoxOrig, Stm) ;
|
||||
Point3d ptBoxCen = ORIG + vtDiag / 2 ;
|
||||
ptBoxCen.ToGlob( frBox) ;
|
||||
DistPointSurfTm DistBoxCenSurfCalc( ptBoxCen, Stm) ;
|
||||
// Se il box è interno c'è collisione
|
||||
return DistBoxOrigSurfCalc.IsPointInside() ;
|
||||
return DistBoxCenSurfCalc.IsPointInside() ;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "CDeBoxTria.h"
|
||||
#include "CDeSpheTria.h"
|
||||
#include "CDeCylTria.h"
|
||||
#include "CDeCapsTria.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -99,9 +100,17 @@ CDeSimpleBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, const Triangle3d
|
||||
Triangle3d trTriaL = trTria ;
|
||||
trTriaL.ToLoc( frBox) ;
|
||||
|
||||
// Calcolo il box locale del triangolo
|
||||
BBox3d b3TriaL ;
|
||||
trTriaL.GetLocalBBox( b3TriaL) ;
|
||||
|
||||
// Calcolo il box come tale
|
||||
BBox3d b3Box( ORIG, ORIG + vtDiag) ;
|
||||
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Box.Overlaps( b3TriaL))
|
||||
return false ;
|
||||
|
||||
// Compute box center and extents
|
||||
Point3d ptCen ;
|
||||
Vector3d vtExt ;
|
||||
@@ -188,6 +197,7 @@ CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, cons
|
||||
if ( CDeSimpleBoxTria( frTmp, vtDiag + 2 * dSafeDist * Z_AX, trTriaL))
|
||||
return true ;
|
||||
|
||||
#if 1
|
||||
// Sfere centrate negli otto vertici
|
||||
if ( CDeSimpleSpheTria( Point3d( 0, 0, 0), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
@@ -243,6 +253,33 @@ CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, cons
|
||||
frTmp.Set( Point3d( 0., vtDiag.y, 0.), Z_AX) ;
|
||||
if ( CDeSimpleCylTria( frTmp, dSafeDist, vtDiag.z, trTriaL))
|
||||
return true ;
|
||||
#else
|
||||
// Capsule centrati sui dodici spigoli
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, 0, 0), Point3d( vtDiag.x, 0, 0), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, vtDiag.y, 0), Point3d( vtDiag.x, vtDiag.y, 0), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, 0, 0), Point3d( 0, vtDiag.y, 0), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( vtDiag.x, 0, 0), Point3d( vtDiag.x, vtDiag.y, 0), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, 0, vtDiag.z), Point3d( vtDiag.x, 0, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, vtDiag.y, vtDiag.z), Point3d( vtDiag.x, vtDiag.y, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, 0, vtDiag.z), Point3d( 0, vtDiag.y, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( vtDiag.x, 0, vtDiag.z), Point3d( vtDiag.x, vtDiag.y, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, 0, 0), Point3d( 0, 0, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( vtDiag.x, 0, 0), Point3d( vtDiag.x, 0, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( vtDiag.x, vtDiag.y, 0), Point3d( vtDiag.x, vtDiag.y, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
if ( CDeSimpleCapsTria( Point3d( 0, vtDiag.y, 0), Point3d( 0, vtDiag.y, vtDiag.z), dSafeDist, trTriaL))
|
||||
return true ;
|
||||
#endif
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2022-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CDeCapsTria.cpp Data : 14.05.22 Versione : 2.4e2
|
||||
// Contenuto : Implementazione della verifica di collisione tra
|
||||
// Capsule (cilindro con estremità semisferiche) e Triangle3d.
|
||||
//
|
||||
//
|
||||
// Modifiche :14.05.22 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CDeCapsTria.h"
|
||||
#include "CDeSpheTria.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSphere.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria)
|
||||
{
|
||||
// vedi Ericson, Real-Time Collision Detection, pag. 226 (Nettle method)
|
||||
|
||||
// Dati della capsule come sfera che si muove
|
||||
Point3d ptC = ptP1 ;
|
||||
Vector3d vtDir = ptP2 - ptP1 ;
|
||||
double dLen = vtDir.Len() ;
|
||||
if ( dLen < EPS_SMALL)
|
||||
return CDeSimpleSpheTria( Media( ptP1, ptP2), dR, trTria) ;
|
||||
vtDir /= dLen ;
|
||||
if ( vtDir * trTria.GetN() > 0) {
|
||||
vtDir.Invert() ;
|
||||
ptC = ptP2 ;
|
||||
}
|
||||
// Determinazione primo possibile punto di contatto della sfera con il piano
|
||||
Point3d ptD = ptC - trTria.GetN() * dR ;
|
||||
// Intersezione della linea di movimento di questo punto con il piano del triangolo
|
||||
Point3d ptP ;
|
||||
int nLpRes = IntersLinePlane( ptD, vtDir, 1, trTria.GetPlane(), ptP, false) ;
|
||||
// Se non c'è intersezione passante
|
||||
if ( nLpRes != ILPT_YES) {
|
||||
// se il centro dista dal piano non meno del raggio, allora non c'è sicuramente collisione
|
||||
double dDist = DistPointPlane( ptP, trTria.GetPlane()) ;
|
||||
if ( abs( dDist) >= dR)
|
||||
return false ;
|
||||
// !!! DA FARE !!!!
|
||||
// si deve intersecare l'asse del capsule con i cilindri centrati sui lati del triangolo
|
||||
// se intersezione inferiore a dLen allora collisione
|
||||
// altrimenti si deve intersecare l'asse del capsule con le sfere centrate sui vertici del triangolo
|
||||
// se intersezione inferiore a dLen allora collisione
|
||||
// per ora salto
|
||||
return false ;
|
||||
}
|
||||
// Determino la posizione dell'intersezione rispetto al triangolo
|
||||
DistPointTriangle dptDist( ptP, trTria) ;
|
||||
// Se l'intersezione sta nel triangolo
|
||||
double dSqDist ;
|
||||
if ( dptDist.GetSqDist( dSqDist) && dSqDist < 4 * SQ_EPS_SMALL) {
|
||||
double dPos = ( ptP - ptD) * vtDir ;
|
||||
return ( dPos > -dR && dPos < dLen) ;
|
||||
}
|
||||
// Altrimenti, recupero il punto del triangolo più vicino all'intersezione
|
||||
Point3d ptQ ;
|
||||
if ( dptDist.GetMinDistPoint( ptQ)) {
|
||||
Point3d ptI1, ptI2 ;
|
||||
int nLsRes = IntersLineSphere( ptQ, -vtDir, ptC, dR, ptI1, ptI2) ;
|
||||
if ( nLsRes != ILST_SEC)
|
||||
return false ;
|
||||
double dPos = ( ptQ - ptI1) * vtDir ;
|
||||
return ( dPos > -dR && dPos < dLen) ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, double dSafeDist, const Triangle3d& trTria)
|
||||
{
|
||||
return CDeSimpleCapsTria( ptP1, ptP2, dR + max( 0., dSafeDist), trTria) ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2022-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : EGkCDeCapsTria.h Data : 14.05.22 Versione : 2.4e2
|
||||
// Contenuto : Dichiarazione funzione verifica collisione tra
|
||||
// Capsule (cilindro con estremità semisferiche) e Triangle3d.
|
||||
//
|
||||
// Modifiche : 14.05.22 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkTriangle3d.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria) ;
|
||||
bool CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, double dSafeDist, const Triangle3d& trTria) ;
|
||||
@@ -20,7 +20,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Il sisitema di riferimento deve avere l'asse di simmetria del cono come asse Z e origine nel centro della base.
|
||||
// Il sistema di riferimento deve avere l'asse di simmetria del cono come asse Z e origine nel centro della base.
|
||||
// La distanza di sicurezza ha effetto solo se maggiore di epsilon, altrimenti è ignorata ed è ininfluente.
|
||||
// Il sistema di riferimento del cono deve essere immerso in quello della superficie.
|
||||
bool
|
||||
@@ -35,10 +35,10 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR
|
||||
// Calcolo il BBox del tronco di cono
|
||||
double dMaxRad = max( dBaseRad, dTopRad) ;
|
||||
BBox3d b3Cone( - dMaxRad, - dMaxRad, 0, dMaxRad, dMaxRad, dHeight) ;
|
||||
b3Cone.Expand( dSafeDist) ;
|
||||
// Porto BBox del cono nel sistema della superficie.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3Cone.Expand( dSafeDist) ;
|
||||
b3Cone.ToGlob( frCone) ;
|
||||
// Se i BBox non interferiscono, ho finito.
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Cone.Overlaps( b3Surf))
|
||||
return false ;
|
||||
// Recupero i triangoli che interferiscono con il box del cono
|
||||
@@ -56,9 +56,9 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR
|
||||
if ( ! Stm.IsClosed())
|
||||
return false ;
|
||||
// Verifico se il tronco di cono è dentro la superficie tramite calcolo distanza minima.
|
||||
Point3d ptConeOrig ;
|
||||
ptConeOrig.ToGlob( frCone) ;
|
||||
DistPointSurfTm DistConeOrigSurfCalc( ptConeOrig, Stm) ;
|
||||
Point3d ptConeCen( 0, 0, dHeight / 2) ;
|
||||
ptConeCen.ToGlob( frCone) ;
|
||||
DistPointSurfTm DistConeCenSurfCalc( ptConeCen, Stm) ;
|
||||
// Se il tronco di cono è interno c'è collisione
|
||||
return DistConeOrigSurfCalc.IsPointInside() ;
|
||||
return DistConeCenSurfCalc.IsPointInside() ;
|
||||
}
|
||||
@@ -33,9 +33,10 @@ CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, double dSafeDist
|
||||
}
|
||||
// calcolo il BBox del cilindro
|
||||
BBox3d b3Cyl( -dR, -dR, 0, dR, dR, dH) ;
|
||||
b3Cyl.Expand( dSafeDist) ;
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3Cyl.Expand( dSafeDist) ;
|
||||
b3Cyl.ToGlob( frC) ;
|
||||
// confronto i due Box
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Cyl.Overlaps( b3Poly))
|
||||
return false ;
|
||||
// recupero i triangoli che interferiscono con il box del Cilindro
|
||||
@@ -52,9 +53,9 @@ CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, double dSafeDist
|
||||
if ( ! Stm.IsClosed())
|
||||
return false ;
|
||||
// Verifico se il cilindro è dentro la superficie tramite calcolo distanza minima.
|
||||
Point3d ptCylOrig( 0., 0., - dSafeDist) ;
|
||||
ptCylOrig.ToGlob( frC) ;
|
||||
DistPointSurfTm DistCylOrigSurfCalc( ptCylOrig, Stm) ;
|
||||
Point3d ptCylCen( 0, 0, dH / 2) ;
|
||||
ptCylCen.ToGlob( frC) ;
|
||||
DistPointSurfTm DistCylCenSurfCalc( ptCylCen, Stm) ;
|
||||
// Se il cilindro è interno c'è collisione
|
||||
return ( DistCylOrigSurfCalc.IsPointInside()) ;
|
||||
return ( DistCylCenSurfCalc.IsPointInside()) ;
|
||||
}
|
||||
|
||||
@@ -38,11 +38,8 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou
|
||||
double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ;
|
||||
double dMaxLenY = max( dLenghtBaseY, dLenghtTopY) ;
|
||||
BBox3d b3Pyr( -dMaxLenX / 2, -dMaxLenY / 2, 0., dMaxLenX / 2, dMaxLenY / 2, dHeight) ;
|
||||
// Se la distanza di sicurezza è maggiore di epsilon aumento le dimensioni del tronco di piramide.
|
||||
if ( dSafeDist > EPS_SMALL) {
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3Pyr.Expand( dSafeDist) ;
|
||||
}
|
||||
// Porto BBox del tronco di piramide nel sistema della superficie.
|
||||
b3Pyr.ToGlob( frPrismoid) ;
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Pyr.Overlaps( b3Surf))
|
||||
@@ -63,8 +60,9 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou
|
||||
if ( ! Stm.IsClosed())
|
||||
return false ;
|
||||
// Verifico se il tronco di piramide è dentro la superficie tramite calcolo distanza minima.
|
||||
Point3d ptPyrOrig = frPrismoid.Orig() ;
|
||||
DistPointSurfTm DistBoxOrigSurfCalc( ptPyrOrig, Stm) ;
|
||||
Point3d ptPyrCen( 0, 0, dHeight / 2) ;
|
||||
ptPyrCen.ToGlob( frPrismoid) ;
|
||||
DistPointSurfTm DistPyrCenSurfCalc( ptPyrCen, Stm) ;
|
||||
// C'è collisione se il tronco di piramide è interno.
|
||||
return ( DistBoxOrigSurfCalc.IsPointInside()) ;
|
||||
return ( DistPyrCenSurfCalc.IsPointInside()) ;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,9 @@ CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, double dSafeDist, const IS
|
||||
BBox3d b3Poly = Stm.GetAllTriaBox() ;
|
||||
// calcolo il BBox della sfera
|
||||
BBox3d b3Sphe( ptCen, dR) ;
|
||||
b3Sphe.Expand( dSafeDist) ;
|
||||
// confronto i due Box
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3Sphe.Expand( dSafeDist) ;
|
||||
// Se i BBox non interferiscono, non c'è collisione
|
||||
if ( ! b3Sphe.Overlaps( b3Poly))
|
||||
return false ;
|
||||
// recupero i triangoli che interferiscono con il box della Sfera
|
||||
|
||||
+5
-5
@@ -109,7 +109,7 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
|
||||
DistLineLine LineLineDistCalc( ptStA, PtEnA, ptStB, PtEnB) ;
|
||||
double dSqSegSegDist ;
|
||||
LineLineDistCalc.GetSqDist( dSqSegSegDist) ;
|
||||
if ( dSqSegSegDist < EPS_SMALL * EPS_SMALL)
|
||||
if ( dSqSegSegDist < SQ_EPS_SMALL)
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
@@ -136,14 +136,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
|
||||
vtSegFirstA /= dSegLenFirstA ;
|
||||
DistLineLine LineLineDistCalcFirstA( ptLineP, vtLineV, 100., trTriaA.GetP( nFirstMaxPosA), vtSegFirstA, dSegLenFirstA, false) ;
|
||||
double dIntParStA, dOtherParFirstA ;
|
||||
LineLineDistCalcFirstA.GetParamsAtMinDistPoints( dIntParStA, dOtherParFirstA) ;
|
||||
LineLineDistCalcFirstA.GetPositionsAtMinDistPoints( dIntParStA, dOtherParFirstA) ;
|
||||
// Limito la retta col secondo segmento trovato di A
|
||||
Vector3d vtSegSecondA = trTriaA.GetP( ( nSecondMaxPosA + 1) % 3) - trTriaA.GetP( nSecondMaxPosA) ;
|
||||
double dSegLenSecondA = vtSegSecondA.Len() ;
|
||||
vtSegSecondA /= dSegLenSecondA ;
|
||||
DistLineLine LineLineDistCalcSecondA( ptLineP, vtLineV, 100., trTriaA.GetP( nSecondMaxPosA), vtSegSecondA, dSegLenSecondA, false) ;
|
||||
double dIntParEnA, dOtherParSecondA ;
|
||||
LineLineDistCalcSecondA.GetParamsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ;
|
||||
LineLineDistCalcSecondA.GetPositionsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ;
|
||||
// Ordino i parametri lungo la retta di intersezione fra i piani
|
||||
if ( dIntParStA > dIntParEnA) {
|
||||
swap( dIntParStA, dIntParEnA) ;
|
||||
@@ -163,14 +163,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB)
|
||||
vtSegFirstB /= dSegLenFirstB ;
|
||||
DistLineLine LineLineDistCalcFirstB( ptLineP, vtLineV, 100., trTriaB.GetP( nFirstMaxPosB), vtSegFirstB, dSegLenFirstB, false) ;
|
||||
double dIntParStB, dOtherParFirstB ;
|
||||
LineLineDistCalcFirstB.GetParamsAtMinDistPoints( dIntParStB, dOtherParFirstB) ;
|
||||
LineLineDistCalcFirstB.GetPositionsAtMinDistPoints( dIntParStB, dOtherParFirstB) ;
|
||||
// Limito la retta col secondo segmento trovato di B
|
||||
Vector3d vtSegSecondB = trTriaB.GetP( ( nSecondMaxPosB + 1) % 3) - trTriaB.GetP( nSecondMaxPosB) ;
|
||||
double dSegLenSecondB = vtSegSecondB.Len() ;
|
||||
vtSegSecondB /= dSegLenSecondB ;
|
||||
DistLineLine LineLineDistCalcSecondB( ptLineP, vtLineV, 100., trTriaB.GetP( nSecondMaxPosA), vtSegSecondB, dSegLenSecondB, false) ;
|
||||
double dIntParEnB, dOtherParSecondB ;
|
||||
LineLineDistCalcSecondB.GetParamsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ;
|
||||
LineLineDistCalcSecondB.GetPositionsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ;
|
||||
// Ordino i parametri lungo la retta di intersezione fra i piani
|
||||
if ( dIntParStB > dIntParEnB) {
|
||||
swap( dIntParStB, dIntParEnB) ;
|
||||
|
||||
+3
-3
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "/EgtDev/Include/EgkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgkGeomDB.h"
|
||||
#include "/EgtDev/Include/EgkCurve.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2022-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : Circle2P.cpp Data : 18.08.22 Versione : 2.4h2
|
||||
// Contenuto : Implementazione funzioni per calcolo circonferenze per 2 punti
|
||||
// diametrali.
|
||||
//
|
||||
//
|
||||
// Modifiche : 18.08.22 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveArc.h"
|
||||
#include "/EgtDev/Include/EGkCircle2P.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveArc*
|
||||
GetCircle2P( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtN)
|
||||
{
|
||||
// Verifico che i due punti siano distinti
|
||||
if ( AreSamePointEpsilon( ptP1, ptP2, EPS_SMALL))
|
||||
return nullptr ;
|
||||
// verifico che la normale non sia allineata con i punti
|
||||
Vector3d vtO = OrthoCompo( vtN, ptP2 - ptP1) ;
|
||||
if ( ! vtO.Normalize())
|
||||
return nullptr ;
|
||||
|
||||
// Creo l'oggetto arco
|
||||
PtrOwner<CurveArc> pCrvArc( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCrvArc))
|
||||
return nullptr ;
|
||||
|
||||
// Eseguo calcoli
|
||||
if ( ! pCrvArc->SetCPAN( Media( ptP1, ptP2), ptP1, ANG_FULL, 0, vtO))
|
||||
return nullptr ;
|
||||
|
||||
return Release( pCrvArc) ;
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EGkAngle.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+127
-51
@@ -699,29 +699,9 @@ CurveArc::Load( NgeReader& ngeIn)
|
||||
bool
|
||||
CurveArc::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// assegno il box in locale
|
||||
b3Loc.Reset() ;
|
||||
double dLinTol = LIN_TOL_APPROX ;
|
||||
double dAngTolDeg = ANG_TOL_APPROX_DEG ;
|
||||
if ( ( nFlag & BBF_EXACT) != 0)
|
||||
dLinTol = LIN_TOL_MIN ;
|
||||
ArcApproxer aAppr( dLinTol, dAngTolDeg, false, *this) ;
|
||||
double dU ;
|
||||
Point3d ptPos ;
|
||||
while ( aAppr.GetPoint( dU, ptPos))
|
||||
b3Loc.Add( ptPos) ;
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
|
||||
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
|
||||
b3Loc.Add( ptMinExtr) ;
|
||||
b3Loc.Add( ptMaxExtr) ;
|
||||
}
|
||||
// richiamo della funzione generale
|
||||
return GetBBox( GLOB_FRM, b3Loc, nFlag) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -736,6 +716,102 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
return false ;
|
||||
// assegno il box nel riferimento
|
||||
b3Ref.Reset() ;
|
||||
|
||||
// ricavo il Frame3D solidale all'arco
|
||||
Frame3d frArc; frArc.Set( m_PtCen, m_dAngCenDeg > 0 ? m_VtN : - m_VtN, m_VtS) ;
|
||||
|
||||
// cordinate nel FrRef dei versori del sistema di riferimento dell'arco
|
||||
Vector3d a = frArc.VersX() ;
|
||||
a.ToGlob( frRef) ;
|
||||
double ax = a.x ;
|
||||
double ay = a.y ;
|
||||
double az = a.z ;
|
||||
|
||||
Vector3d b = frArc.VersY() ;
|
||||
b.ToGlob( frRef) ;
|
||||
double bx = b.x ;
|
||||
double by = b.y ;
|
||||
double bz = b.z ;
|
||||
|
||||
Vector3d c = frArc.VersZ() ;
|
||||
c.ToGlob( frRef) ;
|
||||
double nx = c.x ;
|
||||
double ny = c.y ;
|
||||
double nz = c.z ;
|
||||
|
||||
// vettore degli angoli e dei punti di estremi
|
||||
PNTVECTOR vPoints ;
|
||||
DBLVECTOR vdTheta ;
|
||||
|
||||
// il punto iniziale e finale sono punti candidati per estremanti
|
||||
Point3d ptS, ptE ;
|
||||
GetPointD1D2( 0, FROM_PLUS, ptS) ; if ( ! abs( m_dAngCenDeg - 360) < EPS_SMALL) { GetPointD1D2( 1, FROM_MINUS, ptE) ; }
|
||||
vPoints.push_back( ptS) ; if ( ! abs( m_dAngCenDeg - 360) < EPS_SMALL) { vPoints.push_back( ptE) ; }
|
||||
|
||||
// angolo al centro, raggio e parametro Q
|
||||
double dAngCenRad = m_dAngCenDeg * DEGTORAD ;
|
||||
ptE.ToLoc( frArc) ; ptS.ToLoc( frArc) ;
|
||||
double Q = ( ptE.z - ptS.z) / abs( dAngCenRad) ;
|
||||
double dRad = m_dRad ;
|
||||
|
||||
if ( abs( Q) < EPS_SMALL) {
|
||||
if ( abs( ax) > EPS_SMALL) {
|
||||
vdTheta.push_back( atan( bx / ax)) ;
|
||||
vdTheta.push_back( vdTheta.back() > 0 ? vdTheta.back() + PIGRECO : vdTheta.back() - PIGRECO) ;
|
||||
}
|
||||
if ( abs( ay) > EPS_SMALL) {
|
||||
vdTheta.push_back( atan( by / ay)) ;
|
||||
vdTheta.push_back( vdTheta.back() > 0 ? vdTheta.back() + PIGRECO : vdTheta.back() - PIGRECO) ;
|
||||
}
|
||||
if ( abs( az) > EPS_SMALL) {
|
||||
vdTheta.push_back( atan( bz / az)) ;
|
||||
vdTheta.push_back( vdTheta.back() > 0 ? vdTheta.back() + PIGRECO : vdTheta.back() - PIGRECO) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
vector<double> Va ; Va.push_back( ax) ; Va.push_back( ay) ; Va.push_back( az) ;
|
||||
vector<double> Vb ; Vb.push_back( bx) ; Vb.push_back( by) ; Vb.push_back( bz) ;
|
||||
vector<double> Vn ; Vn.push_back( nx) ; Vn.push_back( ny) ; Vn.push_back( nz) ;
|
||||
|
||||
for ( int i = 0 ; i < 3 ; i++) {
|
||||
double delta = dRad * dRad * Va[i] * Va[i] - Q * Q * Vn[i] * Vn[i] + Vb[i] * Vb[i] * dRad * dRad ;
|
||||
if ( delta > 0) {
|
||||
double t1 = ( dRad * Va[i] + sqrt( delta)) / ( Q * Vn[i] - dRad * Vb[i]) ;
|
||||
if ( abs( 1 - t1 * t1) > EPS_SMALL) {
|
||||
vdTheta.push_back( atan( 2 * t1 / (1 - t1 * t1))) ;
|
||||
vdTheta.push_back(vdTheta.back() > 0 ? vdTheta.back() + PIGRECO : vdTheta.back() - PIGRECO);
|
||||
}
|
||||
double t2 = ( dRad * Va[i] - sqrt( delta)) / ( Q * Vn[i] - dRad * Vb[i]) ;
|
||||
if ( abs( 1 - t2 * t2) > EPS_SMALL){
|
||||
vdTheta.push_back( atan( 2 * t2 / ( 1 - t2 * t2))) ;
|
||||
vdTheta.push_back( vdTheta.back() > 0 ? vdTheta.back() + PIGRECO : vdTheta.back() - PIGRECO) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdTheta.push_back( PIGRECO) ;
|
||||
vdTheta.push_back( PIGRECO / 2) ;
|
||||
vdTheta.push_back( 3 * PIGRECO / 2) ;
|
||||
|
||||
for ( int i = 0 ; i < vdTheta.size() ; i++) {
|
||||
double dTheta = vdTheta[i] > 0 ? vdTheta[i] : 2 * PIGRECO + vdTheta[i] ;
|
||||
if ( dTheta < abs( dAngCenRad)) {
|
||||
Point3d pt ;
|
||||
GetPointD1D2( dTheta / ( abs( dAngCenRad)), FROM_MINUS, pt) ;
|
||||
vPoints.push_back( pt) ;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < vPoints.size(); i++) {
|
||||
vPoints[i].ToGlob( frRef) ;
|
||||
b3Ref.Add( vPoints[i]) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
/*
|
||||
double dLinTol = LIN_TOL_APPROX ;
|
||||
double dAngTolDeg = ANG_TOL_APPROX_DEG ;
|
||||
if ( ( nFlag & BBF_EXACT) != 0)
|
||||
@@ -747,6 +823,9 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
ptPos.ToGlob( frRef) ;
|
||||
b3Ref.Add( ptPos) ;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Vector3d vtFrExtr = m_VtExtr ;
|
||||
@@ -831,7 +910,7 @@ CurveArc::GetEndPoint( Point3d& ptEnd) const
|
||||
double dAng = m_dAngCenDeg * DEGTORAD ;
|
||||
Vector3d vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
|
||||
ptEnd = m_PtCen + m_dRad * vtDir ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
ptEnd += m_dDeltaN * m_VtN ;
|
||||
|
||||
return true ;
|
||||
@@ -849,7 +928,7 @@ CurveArc::GetMidPoint( Point3d& ptMid) const
|
||||
double dAng = 0.5 * m_dAngCenDeg * DEGTORAD ;
|
||||
Vector3d vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
|
||||
ptMid = m_PtCen + m_dRad * vtDir ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
ptMid += ( 0.5 * m_dDeltaN) * m_VtN ;
|
||||
|
||||
return true ;
|
||||
@@ -877,7 +956,7 @@ CurveArc::GetCentroid( Point3d& ptCen) const
|
||||
return false ;
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// calcolo il centro mediante PolygonPlane
|
||||
Point3d ptP ;
|
||||
@@ -909,7 +988,7 @@ CurveArc::GetDir( double dU, Vector3d& vtDir) const
|
||||
Vector3d vtRad = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
|
||||
// calcolo della tangente nel punto finale
|
||||
vtDir = ( m_dRad * m_dAngCenDeg * DEGTORAD) * ( m_VtN ^ vtRad) ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
vtDir += m_dDeltaN * m_VtN ;
|
||||
// normalizzo
|
||||
return vtDir.Normalize( EPS_ZERO) ;
|
||||
@@ -935,13 +1014,13 @@ CurveArc::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, V
|
||||
|
||||
// calcolo del punto
|
||||
ptPos = m_PtCen + m_dRad * vtDir ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
ptPos += ( dU * m_dDeltaN) * m_VtN ;
|
||||
|
||||
// calcolo della derivata prima
|
||||
if ( pvtDer1 != nullptr) {
|
||||
*pvtDer1 = ( m_dRad * m_dAngCenDeg * DEGTORAD) * ( m_VtN ^ vtDir) ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
*pvtDer1 += m_dDeltaN * m_VtN ;
|
||||
}
|
||||
|
||||
@@ -963,7 +1042,7 @@ CurveArc::GetLength( double& dLen) const
|
||||
// lunghezza dell'arco piano
|
||||
dLen = m_dRad * abs( m_dAngCenDeg) * DEGTORAD ;
|
||||
// aggiunta eventuale parte ortogonale
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
dLen = sqrt( dLen * dLen + m_dDeltaN * m_dDeltaN) ;
|
||||
|
||||
return ( dLen > EPS_SMALL) ;
|
||||
@@ -1204,7 +1283,7 @@ CurveArc::Invert( void)
|
||||
return false ;
|
||||
|
||||
// il centro va spostato di DeltaN
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
m_PtCen += m_dDeltaN * m_VtN ;
|
||||
// il versore normale rimane inalterato
|
||||
// il versore iniziale diventa quello finale
|
||||
@@ -1375,13 +1454,11 @@ CurveArc::ModifyEnd( const Point3d& ptNewEnd)
|
||||
bool
|
||||
CurveArc::TrimStartAtParam( double dUTrim)
|
||||
{
|
||||
double dLen ;
|
||||
|
||||
|
||||
// riporto i parametri nel loro range
|
||||
dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ;
|
||||
|
||||
// recupero lunghezza
|
||||
double dLen ;
|
||||
if ( ! GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
@@ -1393,13 +1470,11 @@ CurveArc::TrimStartAtParam( double dUTrim)
|
||||
bool
|
||||
CurveArc::TrimEndAtParam( double dUTrim)
|
||||
{
|
||||
double dLen ;
|
||||
|
||||
|
||||
// riporto i parametri nel loro range
|
||||
dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ;
|
||||
|
||||
// recupero lunghezza
|
||||
double dLen ;
|
||||
if ( ! GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
@@ -1447,7 +1522,7 @@ CurveArc::TrimStartAtLen( double dLenTrim)
|
||||
dAngRot = m_dAngCenDeg * dLenTrim / dLen ;
|
||||
m_VtS.Rotate( m_VtN, dAngRot) ;
|
||||
m_dAngCenDeg -= dAngRot ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL) {
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL) {
|
||||
dMoveN = m_dDeltaN * dLenTrim / dLen ;
|
||||
m_PtCen.Translate( m_VtN * dMoveN) ;
|
||||
m_dDeltaN -= dMoveN ;
|
||||
@@ -1477,7 +1552,7 @@ CurveArc::TrimEndAtLen( double dLenTrim)
|
||||
// eseguo il trim
|
||||
if ( ( dLen - dLenTrim) > EPS_ZERO) {
|
||||
m_dAngCenDeg *= dLenTrim / dLen ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
m_dDeltaN *= dLenTrim / dLen ;
|
||||
}
|
||||
|
||||
@@ -1901,6 +1976,10 @@ CurveArc::ChangeRadius( double dNewRadius)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico validità del raggio
|
||||
if ( ! ( dNewRadius > EPS_SMALL && dNewRadius < MAX_ARC_RAD))
|
||||
return false ;
|
||||
|
||||
// cambio il raggio
|
||||
m_dRad = dNewRadius ;
|
||||
|
||||
@@ -1939,6 +2018,10 @@ CurveArc::ChangeAngCenter( double dNewAngCenDeg)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico accettabilità angolo
|
||||
if ( ! ( abs( m_dAngCenDeg) > EPS_ANG_ZERO))
|
||||
return false ;
|
||||
|
||||
// cambio il parametro
|
||||
m_dAngCenDeg = dNewAngCenDeg ;
|
||||
|
||||
@@ -2031,10 +2114,6 @@ CurveArc::Flip( void)
|
||||
//----------------------------------------------------------------------------
|
||||
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc)
|
||||
{
|
||||
int nStep ;
|
||||
double dAngStepDeg ;
|
||||
|
||||
|
||||
// inizializzazioni
|
||||
m_nTotPnt = 0 ;
|
||||
m_nCurrPnt = - 1 ;
|
||||
@@ -2052,6 +2131,7 @@ ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const
|
||||
dAngTolDeg = min( dAngTolDeg, ANG_TOL_EXT_MAX_DEG) ;
|
||||
|
||||
// determinazione dello step angolare
|
||||
double dAngStepDeg ;
|
||||
double dLinTolRel = dLinTol / arArc.GetRadius() ;
|
||||
if ( bInside)
|
||||
dAngStepDeg = sqrt( 8 * dLinTolRel) * RADTODEG ;
|
||||
@@ -2060,7 +2140,7 @@ ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const
|
||||
dAngStepDeg = min( dAngStepDeg, dAngTolDeg) ;
|
||||
|
||||
// dall'angolo al centro ricavo il numero di passi
|
||||
nStep = (int) ( abs( arArc.GetAngCenter()) / dAngStepDeg + 0.999) ;
|
||||
int nStep = int( abs( arArc.GetAngCenter()) / dAngStepDeg + 0.999) ;
|
||||
nStep = max( nStep, 1) ;
|
||||
|
||||
// sistemo lo step (per il numero intero di passi)
|
||||
@@ -2087,10 +2167,6 @@ ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const
|
||||
bool
|
||||
ArcApproxer::GetPoint( double& dU, Point3d& ptP)
|
||||
{
|
||||
Vector3d vtA1p ;
|
||||
Vector3d vtA2p ;
|
||||
|
||||
|
||||
// incremento indice punto corrente
|
||||
++ m_nCurrPnt ;
|
||||
|
||||
@@ -2109,7 +2185,7 @@ ArcApproxer::GetPoint( double& dU, Point3d& ptP)
|
||||
if ( ! m_bInside && m_nCurrPnt == m_nTotPnt - 1) {
|
||||
dU = 1 ;
|
||||
ptP = m_PtCen + m_vtA1 * m_dRad ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
ptP += ( dU * m_dDeltaN) * m_VtN ;
|
||||
return true ;
|
||||
}
|
||||
@@ -2121,8 +2197,8 @@ ArcApproxer::GetPoint( double& dU, Point3d& ptP)
|
||||
else
|
||||
dU = ( m_nCurrPnt - 0.5) / (double) ( m_nTotPnt - 2) ;
|
||||
// nuovo valore versori
|
||||
vtA1p = m_vtA1 ;
|
||||
vtA2p = m_vtA2 ;
|
||||
Vector3d vtA1p = m_vtA1 ;
|
||||
Vector3d vtA2p = m_vtA2 ;
|
||||
m_vtA1 = m_dCosA * vtA1p + m_dSinA * vtA2p ;
|
||||
m_vtA2 = - m_dSinA * vtA1p + m_dCosA * vtA2p ;
|
||||
// calcolo del punto
|
||||
@@ -2130,7 +2206,7 @@ ArcApproxer::GetPoint( double& dU, Point3d& ptP)
|
||||
ptP = m_PtCen + m_vtA1 * m_dRad ;
|
||||
else
|
||||
ptP = m_PtCen + ( vtA1p + m_vtA1) * ( m_dRad / ( 1 + m_dCosA)) ;
|
||||
if ( abs( m_dDeltaN) > EPS_SMALL)
|
||||
if ( abs( m_dDeltaN) > 0.1 * EPS_SMALL)
|
||||
ptP += ( dU * m_dDeltaN) * m_VtN ;
|
||||
|
||||
return true ;
|
||||
|
||||
+1
-1
@@ -790,7 +790,7 @@ ProjectCurveOnPlane( const ICurve& crCrv, const Plane3d& plPlane)
|
||||
{
|
||||
// determino se curva piana e suo eventuale piano
|
||||
Plane3d plCrv ;
|
||||
if ( crCrv.IsFlat( plCrv)) {
|
||||
if ( crCrv.IsFlat( plCrv, false, EPS_SMALL / 2)) {
|
||||
// se il piano della curva è parallelo a quello di proiezione
|
||||
if ( AreSameOrOppositeVectorExact( plCrv.GetVersN(), plPlane.GetVersN())) {
|
||||
// copio la curva
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EgkCurveAux.h"
|
||||
#include "/EgtDev/Include/EGkCurveAux.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IsClosed( const ICurve& crvC) ;
|
||||
|
||||
+4
-4
@@ -448,7 +448,7 @@ CurveBezier::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
else {
|
||||
// costruisco una approssimazione lineare
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( LIN_TOL_MIN, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! ApproxWithLines( LIN_TOL_MIN, ANG_TOL_APPROX_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// ciclo sui punti della approssimazione
|
||||
Point3d ptTemp ;
|
||||
@@ -491,7 +491,7 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
else {
|
||||
// costruisco una approssimazione lineare
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( LIN_TOL_MIN, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! ApproxWithLines( LIN_TOL_MIN, ANG_TOL_APPROX_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// ciclo sui punti della approssimazione
|
||||
Point3d ptTemp ;
|
||||
@@ -618,7 +618,7 @@ CurveBezier::GetCentroid( Point3d& ptCen) const
|
||||
return false ;
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// calcolo il centro mediante PolygonPlane
|
||||
Point3d ptP ;
|
||||
@@ -1429,7 +1429,7 @@ CurveBezier::ApproxWithArcsXY( double dLinTol, double dAngTolDeg, PolyArc& PA) c
|
||||
|
||||
// costruisco una approssimazione lineare
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, PL))
|
||||
if ( ! ApproxWithLines( dLinTol, dAngTolDeg, APL_STD, PL))
|
||||
return false ;
|
||||
|
||||
// approssimo la curva per approssimazioni successive mediante bisezione
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "CalcDerivate.h"
|
||||
#include "BiArcs.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyArc.h"
|
||||
@@ -65,6 +66,8 @@ CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dL
|
||||
PtrOwner<CurveComposite> pCC( CreateBasicCurveComposite()) ;
|
||||
if ( ! pCC->FromPolyArc( PA))
|
||||
return nullptr ;
|
||||
// elimino eventuali Small Z
|
||||
pCC->RemoveSmallDefects( dLinTol, dAngTolDeg) ;
|
||||
// eventuale fusione di curve compatibili
|
||||
pCC->MergeCurves( dLinTol, dAngTolDeg) ;
|
||||
// restituisco la curva
|
||||
|
||||
+3
-3
@@ -15,9 +15,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "/EgtDev/Include/EGkCurveByInterp.h"
|
||||
#include "/EgtDev/Include/EgkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EgkBiArcs.h"
|
||||
#include "/EgtDev/Include/EgkCurveBezier.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkBiArcs.h"
|
||||
#include "/EgtDev/Include/EGkCurveBezier.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
|
||||
+169
-14
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
// EgalTech 2013-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CurveComposite.cpp Data : 23.11.13 Versione : 1.3a1
|
||||
// File : CurveComposite.cpp Data : 23.01.22 Versione : 2.4a4
|
||||
// Contenuto : Implementazione della classe CCurveComposite.
|
||||
//
|
||||
//
|
||||
@@ -21,15 +21,17 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "GeoConst.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EgkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
@@ -208,8 +210,15 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
if ( ! AreSamePointEpsilon( ptCrvStart, ptEnd, 0.01 * EPS_SMALL)) {
|
||||
// se in tolleranza, modifico l'inizio dell'entità
|
||||
if ( SqDist( ptCrvStart, ptEnd) < ( dLinTol * dLinTol)) {
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyStart( ptEnd))
|
||||
return false ;
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
@@ -254,14 +263,25 @@ CurveComposite::Close( void)
|
||||
// se già chiusa, non faccio alcunché
|
||||
if ( IsClosed())
|
||||
return true ;
|
||||
// aggiungo la linea di chiusura
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
// determino la distanza tra gli estremi
|
||||
Point3d ptStart, ptEnd ;
|
||||
if ( ! GetStartPoint( ptStart) ||
|
||||
! GetEndPoint( ptEnd) ||
|
||||
! pLine->Set( ptEnd, ptStart) ||
|
||||
! AddSimpleCurve( Release( pLine)))
|
||||
! GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
// se molto vicini li modifico
|
||||
if ( SqDist( ptStart, ptEnd) < 100 * SQ_EPS_SMALL) {
|
||||
Point3d ptMid = Media( ptStart, ptEnd) ;
|
||||
if ( ! ModifyStart( ptMid) ||
|
||||
! ModifyEnd( ptMid))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti aggiungo la linea di chiusura
|
||||
else {
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
if ( ! pLine->Set( ptEnd, ptStart) ||
|
||||
! AddSimpleCurve( Release( pLine)))
|
||||
return false ;
|
||||
}
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -967,7 +987,7 @@ CurveComposite::GetCentroid( Point3d& ptCen) const
|
||||
return false ;
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
if ( ! ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, APL_SPECIAL, PL))
|
||||
return false ;
|
||||
// calcolo il centro mediante PolygonPlane
|
||||
Point3d ptP ;
|
||||
@@ -1016,7 +1036,7 @@ CurveComposite::GetMidDir( Vector3d& vtDir) const
|
||||
if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid))
|
||||
return false ;
|
||||
// calcolo la direzione
|
||||
return ::GetTang( *this, 0.5 * m_CrvSmplS.size(), FROM_MINUS, vtDir) ;
|
||||
return ::GetTang( *this, dMid, FROM_MINUS, vtDir) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1321,8 +1341,8 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
|
||||
// se lineare con lato obbligato...
|
||||
if ( nType == APL_LEFT || nType == APL_LEFT_CONVEX ||
|
||||
nType == APL_RIGHT || nType == APL_RIGHT_CONVEX) {
|
||||
// prima approssimazione lineare a 10 * Epsilon
|
||||
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
|
||||
// prima approssimazione lineare alla tolleranza minima del programma
|
||||
if ( ! ApproxWithLines( EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
|
||||
return false ;
|
||||
// eliminazione dei punti in tolleranza andando solo dalla parte ammessa
|
||||
Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
|
||||
@@ -1414,6 +1434,13 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin
|
||||
crvByApprox.Reset() ;
|
||||
crvByApprox.AddPoint( pLine->GetStart()) ;
|
||||
}
|
||||
// aggiungo punti a distanza opportuna
|
||||
const double STEP = 5 ;
|
||||
int nStep = int( dLen / STEP) ;
|
||||
for ( int i = 1 ; i < nStep ; ++ i) {
|
||||
double dCoeff = i / double( nStep) ;
|
||||
crvByApprox.AddPoint( Media( pLine->GetStart(), pLine->GetEnd(), dCoeff)) ;
|
||||
}
|
||||
// aggiungo il punto finale
|
||||
crvByApprox.AddPoint( pLine->GetEnd()) ;
|
||||
}
|
||||
@@ -1457,8 +1484,8 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin
|
||||
// assegno estrusione della curva composita
|
||||
PA.SetExtrusion( m_VtExtr) ;
|
||||
|
||||
// eliminazione dei punti in tolleranza
|
||||
return PA.RemoveAlignedPoints( dLinTol) ;
|
||||
// eliminazione dei punti in tolleranza (opportunamente diminuita)
|
||||
return PA.RemoveAlignedPoints( 0.5 * dLinTol) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1614,6 +1641,40 @@ CurveComposite::AddPoint( const Point3d& ptStart)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::AddLineTg( double dLen, bool bEndOrStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// costruisco la linea
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
return false ;
|
||||
// se da aggiungere alla fine
|
||||
if ( bEndOrStart) {
|
||||
Point3d ptEnd ;
|
||||
Vector3d vtEnd ;
|
||||
if ( ! GetEndPoint( ptEnd) || ! GetEndDir( vtEnd))
|
||||
return false ;
|
||||
Point3d ptNew = ptEnd + vtEnd * dLen ;
|
||||
if ( ! pLine->Set( ptEnd, ptNew))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti da aggiungere all'inizio
|
||||
else {
|
||||
Point3d ptStart ;
|
||||
Vector3d vtStart ;
|
||||
if ( ! GetStartPoint( ptStart) || ! GetStartDir( vtStart))
|
||||
return false ;
|
||||
Point3d ptNew = ptStart - vtStart * dLen ;
|
||||
if ( ! pLine->Set( ptNew, ptStart))
|
||||
return false ;
|
||||
}
|
||||
return AddCurve( Release( pLine), bEndOrStart) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::AddLine( const Point3d& ptNew, bool bEndOrStart)
|
||||
@@ -3015,6 +3076,13 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd,
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::RemoveSmallDefects( double dLinTol, double dAngTolDeg, bool bAlsoSpikes)
|
||||
{
|
||||
return (( ! bAlsoSpikes || RemoveCurveSpikes( this, dLinTol)) && RemoveCurveSmallZs(this, dLinTol)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SplitTopBottomArcs( CurveComposite& cCompo)
|
||||
@@ -3246,6 +3314,93 @@ CurveComposite::IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double
|
||||
return CrvTemp.IsOneCircle( ptCen, vtN, dRad, bCCW) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::IsARectangle( double dLinTol, Point3d& ptP, Vector3d& vtL1, Vector3d& vtL2) const
|
||||
{
|
||||
// deve essere chiusa
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// approssimo con segmenti di retta
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// deve giacere in un piano entro la tolleranza
|
||||
Plane3d plPlane ;
|
||||
if ( ! PL.IsFlat( plPlane, dLinTol))
|
||||
return false ;
|
||||
// deve essere formata da 4 segmenti
|
||||
if ( PL.GetLineNbr() != 4)
|
||||
return false ;
|
||||
// recupero i 4 vertici
|
||||
Point3d ptV1 ; PL.GetFirstPoint( ptV1) ;
|
||||
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
|
||||
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
|
||||
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
|
||||
// verifico che le diagonali si incontrino nel loro punto medio (-> è un parallelogramma)
|
||||
if ( ! AreSamePointEpsilon( Media( ptV1, ptV3), Media( ptV2, ptV4), dLinTol / 2))
|
||||
return false ;
|
||||
// verifico che le diagonali abbiano la stessa lunghezza (-> è un rettangolo)
|
||||
if ( abs( Dist( ptV1, ptV3) - Dist( ptV2, ptV4)) > dLinTol)
|
||||
return false ;
|
||||
// assegno i parametri del rettangolo
|
||||
ptP = ptV1 ;
|
||||
vtL1 = ptV2 - ptV1 ;
|
||||
vtL2 = ptV4 - ptV1 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vector3d& vtL1, Vector3d& vtB2) const
|
||||
{
|
||||
// deve essere chiusa
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// approssimo con segmenti di retta
|
||||
PolyLine PL ;
|
||||
if ( ! ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, APL_STD, PL))
|
||||
return false ;
|
||||
// deve giacere in un piano entro la tolleranza
|
||||
Plane3d plPlane ;
|
||||
if ( ! PL.IsFlat( plPlane, dLinTol))
|
||||
return false ;
|
||||
// deve essere formata da 4 segmenti
|
||||
if ( PL.GetLineNbr() != 4)
|
||||
return false ;
|
||||
// recupero i 4 vertici
|
||||
Point3d ptV1 ; PL.GetFirstPoint( ptV1) ;
|
||||
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
|
||||
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
|
||||
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
|
||||
// verifico se V4->V3 è parallelo a V1->V2
|
||||
double dV3B12, dV4B12 ;
|
||||
if ( ! DistPointLine( ptV3, ptV1, ptV2, false).GetDist( dV3B12) ||
|
||||
! DistPointLine( ptV4, ptV1, ptV2, false).GetDist( dV4B12))
|
||||
return false ;
|
||||
if ( abs( dV3B12 - dV4B12) < EPS_SMALL) {
|
||||
ptP = ptV1 ;
|
||||
vtB1 = ptV2 - ptV1 ;
|
||||
vtL1 = ptV4 - ptV1 ;
|
||||
vtB2 = ptV3 - ptV4 ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se V1->V4 è parallelo a V2->V3
|
||||
double dV1B23, dV4B23 ;
|
||||
if ( ! DistPointLine( ptV1, ptV2, ptV3, false).GetDist( dV1B23) ||
|
||||
! DistPointLine( ptV4, ptV2, ptV3, false).GetDist( dV4B23))
|
||||
return false ;
|
||||
if ( abs( dV1B23 - dV4B23) < EPS_SMALL) {
|
||||
ptP = ptV2 ;
|
||||
vtB1 = ptV3 - ptV2 ;
|
||||
vtL1 = ptV1 - ptV2 ;
|
||||
vtB2 = ptV4 - ptV1 ;
|
||||
return true ;
|
||||
}
|
||||
// non è un trapezio
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum)
|
||||
|
||||
+8
-3
@@ -1,12 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2021
|
||||
// EgalTech 2013-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CurveComposite.h Data : 03.04.21 Versione : 2.3d1
|
||||
// File : CurveComposite.h Data : 24.03.22 Versione : 2.4c2
|
||||
// Contenuto : Dichiarazione della classe Curva composita.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 16.04.13 DS Creazione modulo.
|
||||
// 24.03.22 DS Aggiunto metodo AddLineTg.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -144,8 +145,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool ChangeStartPoint( double dU) override ;
|
||||
bool AddPoint( const Point3d& ptStart) override ;
|
||||
bool AddLine( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddLineTg( double dLen, bool bEndOrStart = true) override ;
|
||||
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddJoint( double dU) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
|
||||
bool RemoveJoint( int nU) override ;
|
||||
@@ -155,10 +157,13 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool ArcsToBezierCurves( void) override ;
|
||||
bool ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDeg) override ;
|
||||
bool MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd = true, bool bNeedSameProp = false) override ;
|
||||
bool RemoveSmallDefects( double dLinTol, double dAngTolDeg, bool bAlsoSpikes = false) override ;
|
||||
bool RemoveUndercutOnY( double dLinTol, double dAngTolDeg) override ;
|
||||
bool IsAPoint( void) const override ;
|
||||
bool IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const override ;
|
||||
bool IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const override ;
|
||||
bool IsARectangle( double dLinTol, Point3d& ptP, Vector3d& vtL1, Vector3d& vtL2) const override ;
|
||||
bool IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vector3d& vtL1, Vector3d& vtB2) const override ;
|
||||
bool SetCurveTempProp( int nCrv, int nProp, int nPropNum = 0) override ;
|
||||
bool GetCurveTempProp( int nCrv, int& nProp, int nPropNum = 0) const override ;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkCurve.h"
|
||||
#include "/EgtDev/Include/EgkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+100
-96
@@ -1,13 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2020
|
||||
// EgalTech 2020-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistLineLine.h Data : 06.11.20 Versione : 2.2k1
|
||||
// File : DistLineLine.h Data : 12.08.22 Versione : 2.4h1
|
||||
// Contenuto : Implementazione della classe distanza fra elementi lineari.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 06.11.20 LM Creazione modulo.
|
||||
//
|
||||
// 12.08.22 DS Correzioni e migliorie varie.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -18,22 +18,26 @@
|
||||
#include "/EgtDev/Include/EGkGeoConst.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistLineLine::DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1,
|
||||
const Point3d& ptSt2, const Point3d& ptEn2,
|
||||
bool bIsSegment1, bool bIsSegment2)
|
||||
{
|
||||
// reset oggetto
|
||||
m_dSqDist = - 1 ;
|
||||
m_dDist = - 1 ;
|
||||
// calcolo direzione segmenti
|
||||
Vector3d vtD1 = ptEn1 - ptSt1 ;
|
||||
double dLen1 = vtD1.Len() ;
|
||||
Vector3d vtD2 = ptEn2 - ptSt2 ;
|
||||
double dLen2 = vtD1.Len() ;
|
||||
if ( dLen1 < EPS_SMALL || dLen2 < EPS_SMALL) {
|
||||
m_dSqDist = - 1 ;
|
||||
m_dDist = - 1 ;
|
||||
double dLen2 = vtD2.Len() ;
|
||||
if ( dLen1 < EPS_SMALL || dLen2 < EPS_SMALL)
|
||||
return ;
|
||||
}
|
||||
vtD1 /= dLen1 ;
|
||||
vtD2 /= dLen2 ;
|
||||
// eseguo
|
||||
Calculate( ptSt1, vtD1, dLen1, ptSt2, vtD2, dLen2, bIsSegment1, bIsSegment2) ;
|
||||
}
|
||||
|
||||
@@ -43,11 +47,13 @@ DistLineLine::DistLineLine( const Point3d& ptSt1, const Vector3d& vtD1, double d
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1, bool bIsSegment2)
|
||||
{
|
||||
if ( dLen1 < EPS_SMALL || dLen2 < EPS_SMALL) {
|
||||
m_dSqDist = - 1 ;
|
||||
m_dDist = - 1 ;
|
||||
// reset oggetto
|
||||
m_dSqDist = - 1 ;
|
||||
m_dDist = - 1 ;
|
||||
// verifico segmenti
|
||||
if ( dLen1 < EPS_SMALL || dLen2 < EPS_SMALL)
|
||||
return ;
|
||||
}
|
||||
// eseguo
|
||||
Calculate( ptSt1, vtD1, dLen1, ptSt2, vtD2, dLen2, bIsSegment1, bIsSegment2) ;
|
||||
}
|
||||
|
||||
@@ -57,6 +63,7 @@ DistLineLine::GetSqDist( double& dSqDist)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
|
||||
dSqDist = m_dSqDist ;
|
||||
return true ;
|
||||
}
|
||||
@@ -67,7 +74,10 @@ DistLineLine::GetDist( double& dDist)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
dDist = sqrt( m_dSqDist) ;
|
||||
|
||||
if ( m_dDist < 0)
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -84,55 +94,48 @@ DistLineLine::GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistLineLine::GetParamsAtMinDistPoints( double& dPar1, double& dPar2)
|
||||
DistLineLine::GetPositionsAtMinDistPoints( double& dPos1, double& dPos2)
|
||||
{
|
||||
if ( m_dSqDist < 0)
|
||||
return false ;
|
||||
dPar1 = m_dPar1 ;
|
||||
dPar2 = m_dPar2 ;
|
||||
dPos1 = m_dPos1 ;
|
||||
dPos2 = m_dPos2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calcola la distanza fra i due elemnti lineari, i punti di minima distanza e
|
||||
// i loro rispettivi parametri.
|
||||
// Se la coppia di punti di minima distanza non è unica ne viene scelta una
|
||||
// in base a comodità di calcolo.
|
||||
// Calcola la distanza fra i due elementi lineari, i punti di minima distanza e le loro posizioni.
|
||||
// Se i due elementi sono paralleli i punti di minimo sono scelti secondo convenienza.
|
||||
void
|
||||
DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1, bool bIsSegment2)
|
||||
{
|
||||
// Caso di elementi lineari paralleli/antiparalleli
|
||||
// Se elementi paralleli o antiparalleli
|
||||
if ( AreSameOrOppositeVectorExact( vtD1, vtD2)) {
|
||||
// Almeno un elemento è una retta
|
||||
if ( ! ( bIsSegment1 && bIsSegment2)) {
|
||||
// Il primo elemento è segmento, quindi deve essere una retta il secondo
|
||||
if ( bIsSegment1) {
|
||||
Vector3d vtStSt = ptSt1 - ptSt2 ;
|
||||
double dLong = vtStSt * vtD2 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD2 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = dLong ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
|
||||
}
|
||||
// Il primo elemento è una retta
|
||||
else {
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dLong = vtStSt * vtD1 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD1 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dPar1 = dLong ;
|
||||
m_dPar2 = 0 ;
|
||||
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 ;
|
||||
}
|
||||
// Se il primo elemento è una retta infinita
|
||||
if ( ! bIsSegment1) {
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dLong = vtStSt * vtD1 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD1 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dPos1 = dLong ;
|
||||
m_dPos2 = 0 ;
|
||||
m_ptMinDist1 = ptSt1 + dLong * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 ;
|
||||
}
|
||||
// se altrimenti il secondo elemento è una retta infinita
|
||||
else if ( ! bIsSegment2) {
|
||||
Vector3d vtStSt = ptSt1 - ptSt2 ;
|
||||
double dLong = vtStSt * vtD2 ;
|
||||
Vector3d vtDist = vtStSt - dLong * vtD2 ;
|
||||
m_dSqDist = vtDist.SqLen() ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = dLong ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + dLong * vtD2 ;
|
||||
}
|
||||
// Entrambi gli elementi sono segmenti
|
||||
// altrimenti entrambi gli elementi sono segmenti
|
||||
else {
|
||||
Point3d ptEn1 = ptSt1 + dLen1 * vtD1 ;
|
||||
Point3d ptEn2 = ptSt2 + dLen2 * vtD2 ;
|
||||
@@ -140,7 +143,7 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
|
||||
Vector3d vtStEn = ptEn2 - ptSt1 ;
|
||||
double dStU = vtStSt * vtD1 ;
|
||||
double dEnU = vtStEn * vtD1 ;
|
||||
// Classifico i punti del segmento segmento in base alla loro
|
||||
// Classifico i punti del secondo segmento in base alla loro
|
||||
// coordinata rispetto all'ordinamento generato dal primo.
|
||||
double dMinPar, dMaxPar ;
|
||||
Point3d ptMinPar, ptMaxPar ;
|
||||
@@ -159,70 +162,71 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen
|
||||
// Possibili posizioni reciproche dei segmenti
|
||||
if ( dMinPar > dLen1) {
|
||||
m_dSqDist = SqDist( ptEn1, ptMinPar) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_ptMinDist1 = ptEn1 ;
|
||||
m_ptMinDist2 = ptMinPar ;
|
||||
m_dPar1 = dLen1 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = dLen1 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else if ( dMinPar > 0) {
|
||||
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_ptMinDist1 = ptSt1 + dMinPar * vtD1 ;
|
||||
m_ptMinDist2 = ptMinPar ;
|
||||
m_dPar1 = dMinPar ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = dMinPar ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else if ( dMaxPar > 0) {
|
||||
m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptSt2 + ( ptSt1 - ptSt2) * vtD2 * vtD2 ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
else {
|
||||
m_dSqDist = SqDist( ptSt1, ptMaxPar) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
m_ptMinDist1 = ptSt1 ;
|
||||
m_ptMinDist2 = ptMaxPar ;
|
||||
m_dPar1 = 0 ;
|
||||
m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
m_dPos1 = 0 ;
|
||||
m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
// Caso generale
|
||||
Vector3d vtDist0 = ptSt2 - ptSt1 ;
|
||||
double dDist01 = vtDist0 * vtD1 ;
|
||||
double dDist02 = vtDist0 * vtD2 ;
|
||||
double dDotD1D2 = vtD1 * vtD2 ;
|
||||
double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dMin1 = - INFINITO ;
|
||||
double dMax1 = INFINITO ;
|
||||
double dMin2 = - INFINITO ;
|
||||
double dMax2 = INFINITO ;
|
||||
double dSt1On2 = ( ptSt1 - ptSt2) * vtD2 ;
|
||||
double dEn1On2 = ( ptSt1 + dLen1 * vtD1 - ptSt2) * vtD2 ;
|
||||
if ( bIsSegment1) {
|
||||
dMin1 = 0 ;
|
||||
dMax1 = dLen1 ;
|
||||
dMin2 = std::min( dSt1On2, dEn1On2) ;
|
||||
dMax2 = std::max( dSt1On2, dEn1On2) ;
|
||||
else {
|
||||
// Posizioni a distanza minima tra rette illimitate
|
||||
Vector3d vtStSt = ptSt2 - ptSt1 ;
|
||||
double dDist01 = vtStSt * vtD1 ;
|
||||
double dDist02 = vtStSt * vtD2 ;
|
||||
double dDotD1D2 = vtD1 * vtD2 ;
|
||||
double dT1 = ( dDist01 - dDotD1D2 * dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
double dT2 = ( dDotD1D2 * dDist01 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ;
|
||||
// Posizioni minime e massime sui segmenti
|
||||
double dMin1 = ( bIsSegment1 ? 0 : -INFINITO) ;
|
||||
double dMax1 = ( bIsSegment1 ? dLen1 : INFINITO) ;
|
||||
double dMin2 = ( bIsSegment2 ? 0 : -INFINITO) ;
|
||||
double dMax2 = ( bIsSegment2 ? dLen2 : INFINITO) ;
|
||||
// Se entrambe le posizioni stanno nei segmenti
|
||||
if ( dT1 >= dMin1 && dT1 <= dMax1 && dT2 >= dMin2 && dT2 <= dMax2) {
|
||||
m_dPos1 = dT1 ;
|
||||
m_dPos2 = dT2 ;
|
||||
}
|
||||
// se altrimenti solo la prima sta nel segmento
|
||||
else if ( dT1 >= dMin1 && dT1 <= dMax1) {
|
||||
m_dPos2 = Clamp( dT2, dMin2, dMax2) ;
|
||||
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
|
||||
}
|
||||
// se altrimenti solo la seconda sta nel segmento
|
||||
else if ( dT2 >= dMin2 && dT2 <= dMax2) {
|
||||
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
|
||||
}
|
||||
// altrimenti nessuna sta nel suo segmento
|
||||
else {
|
||||
m_dPos1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ;
|
||||
m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ;
|
||||
}
|
||||
m_ptMinDist1 = ptSt1 + m_dPos1 * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 + m_dPos2 * vtD2 ;
|
||||
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
|
||||
}
|
||||
if ( bIsSegment2) {
|
||||
double dSt2On1 = ( ptSt2 - ptSt1) * vtD1 ;
|
||||
double dEn2On1 = ( ptSt2 + dLen2 * vtD2 - ptSt1) * vtD1 ;
|
||||
dMin1 = std::max( dMin1, std::min( dSt2On1, dEn2On1)) ;
|
||||
dMax1 = std::min( dMax1, std::max( dSt2On1, dEn2On1)) ;
|
||||
dMin2 = std::max( dMin2, 0.) ;
|
||||
dMax2 = std::min( dMax2, dLen2) ;
|
||||
}
|
||||
m_dPar1 = Clamp( dT1, dMin1, dMax1) ;
|
||||
m_dPar2 = Clamp( dT2, dMin2, dMax2) ;
|
||||
m_ptMinDist1 = ptSt1 + m_dPar1 * vtD1 ;
|
||||
m_ptMinDist2 = ptSt2 + m_dPar2 * vtD2 ;
|
||||
m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ;
|
||||
m_dDist = sqrt( m_dSqDist) ;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -37,17 +37,17 @@ class DistLineLine
|
||||
bool IsSmall( void) { return IsEpsilon( EPS_SMALL) ; }
|
||||
bool IsZero( void) { return IsEpsilon( EPS_ZERO) ; }
|
||||
bool GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) ;
|
||||
bool GetParamsAtMinDistPoints( double& dPar1, double& dPar2) ;
|
||||
bool GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) ;
|
||||
|
||||
private :
|
||||
void Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
|
||||
bool bIsSegment1, bool bIsSegment2) ;
|
||||
private:
|
||||
double m_dSqDist ;
|
||||
double m_dDist ;
|
||||
double m_dPar1 ;
|
||||
double m_dPar2 ;
|
||||
double m_dPos1 ;
|
||||
double m_dPos2 ;
|
||||
Point3d m_ptMinDist1 ;
|
||||
Point3d m_ptMinDist2 ;
|
||||
} ;
|
||||
|
||||
@@ -89,8 +89,18 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
|
||||
}
|
||||
}
|
||||
// altrimenti aggiungo
|
||||
else
|
||||
m_Info.push_back( aInfo) ;
|
||||
else {
|
||||
if ( dCurrDist < m_dDist) {
|
||||
// aggiorno i minimi
|
||||
m_dDist = dCurrDist ;
|
||||
// inserisco in testa
|
||||
m_Info.insert( m_Info.begin(), aInfo) ;
|
||||
}
|
||||
else {
|
||||
// inserisco in coda
|
||||
m_Info.push_back( aInfo) ;
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
++ i ;
|
||||
}
|
||||
|
||||
@@ -20,4 +20,5 @@
|
||||
int GetEGkDebugLev( void) ;
|
||||
ILogger* GetEGkLogger( void) ;
|
||||
const std::string& GetEGkKey( void) ;
|
||||
bool GetEGkNetHwKey( void) ;
|
||||
int ProcessEvents( int nProg, int nPause) ;
|
||||
|
||||
+16
-1
@@ -16,7 +16,7 @@
|
||||
#include "DllMain.h"
|
||||
#include "FontManager.h"
|
||||
#include "\EgtDev\Include\EGkDllMain.h"
|
||||
#include "\EgtDev\Include\EgnGetModuleVer.h"
|
||||
#include "\EgtDev\Include\EGnGetModuleVer.h"
|
||||
#include "\EgtDev\Include\EgtTrace.h"
|
||||
#include "\EgtDev\Include\SELkLockId.h"
|
||||
|
||||
@@ -115,6 +115,7 @@ GetEGkLogger( void)
|
||||
//-----------------------------------------------------------------------------
|
||||
static string s_sKey ;
|
||||
static int s_nKeyType = KEY_LOCK_TYPE_ANY ;
|
||||
static bool s_bNetHwKey = false ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
@@ -130,6 +131,13 @@ SetEGkKeyType( int nType)
|
||||
s_nKeyType = nType ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
SetEGkNetHwKey( bool bNetHwKey)
|
||||
{
|
||||
s_bNetHwKey = bNetHwKey ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const string&
|
||||
GetEGkKey( void)
|
||||
@@ -138,6 +146,13 @@ GetEGkKey( void)
|
||||
return s_sKey ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
GetEGkNetHwKey( void)
|
||||
{
|
||||
return s_bNetHwKey ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
InitFontManager( const string& sNfeFontDir, const string& sDefaultFont)
|
||||
|
||||
Binary file not shown.
+21
-10
@@ -30,7 +30,7 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
<PlatformToolset>v141_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
@@ -46,7 +46,7 @@
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
<PlatformToolset>v141_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
@@ -151,6 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -243,6 +244,8 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
<IntelJCCErratum>true</IntelJCCErratum>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -280,6 +283,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp" />
|
||||
<ClCompile Include="CDeBoxTria.cpp" />
|
||||
<ClCompile Include="CDeCapsTria.cpp" />
|
||||
<ClCompile Include="CDeClosedSurfTmClosedSurfTm.cpp" />
|
||||
<ClCompile Include="CDeConeFrustumClosedSurfTm.cpp" />
|
||||
<ClCompile Include="CDeConeFrustumTria.cpp" />
|
||||
@@ -295,6 +299,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CDeTriaTria.cpp" />
|
||||
<ClCompile Include="CDeUtility.cpp" />
|
||||
<ClCompile Include="ChainCurves.cpp" />
|
||||
<ClCompile Include="Circle2P.cpp" />
|
||||
<ClCompile Include="CircleCenTgCurve.cpp" />
|
||||
<ClCompile Include="Color.cpp" />
|
||||
<ClCompile Include="CreateCurveAux.cpp" />
|
||||
@@ -308,6 +313,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
<ClInclude Include="CDeConeTria.h" />
|
||||
<ClInclude Include="CDeConvexTorusTria.h" />
|
||||
@@ -321,6 +327,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="DistPointSurfTm.cpp" />
|
||||
<ClCompile Include="DistPointTria.cpp" />
|
||||
<ClCompile Include="ExtDimension.cpp" />
|
||||
<ClCompile Include="HashGrids1d.cpp" />
|
||||
<ClCompile Include="IntersLineBox.cpp" />
|
||||
<ClCompile Include="IntersLineSphere.cpp" />
|
||||
<ClCompile Include="IntersLineSurfStd.cpp" />
|
||||
@@ -330,6 +337,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersPlaneTria.cpp" />
|
||||
<ClCompile Include="IntersSurfTmSurfTm.cpp" />
|
||||
<ClCompile Include="IntersTriaTria.cpp" />
|
||||
<ClCompile Include="MedialAxis.cpp" />
|
||||
<ClCompile Include="OffsetCurve.cpp" />
|
||||
<ClCompile Include="DistPointArc.cpp" />
|
||||
<ClCompile Include="DistPointCrvAux.cpp" />
|
||||
@@ -384,7 +392,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="OffsetCurveOnX.cpp" />
|
||||
<ClCompile Include="Polygon3d.cpp" />
|
||||
<ClCompile Include="AdjustLoops.cpp" />
|
||||
<ClCompile Include="RemoveCurveSpikes.cpp" />
|
||||
<ClCompile Include="RemoveCurveDefects.cpp" />
|
||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||
<ClCompile Include="SfrCreate.cpp" />
|
||||
<ClCompile Include="SurfBezier.cpp" />
|
||||
@@ -392,6 +400,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="SurfFlatRegionBooleans.cpp" />
|
||||
<ClCompile Include="SurfFlatRegionOffset.cpp" />
|
||||
<ClCompile Include="SurfTriMeshBooleans.cpp" />
|
||||
<ClCompile Include="SurfTriMeshCuts.cpp" />
|
||||
<ClCompile Include="SurfTriMeshUtilities.cpp" />
|
||||
<ClCompile Include="TextureData.cpp" />
|
||||
<ClCompile Include="Tool.cpp" />
|
||||
@@ -441,14 +450,14 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkChainCurves.h" />
|
||||
<ClInclude Include="..\Include\EGkCircleCenTgCurve.h" />
|
||||
<ClInclude Include="..\Include\EGkColor.h" />
|
||||
<ClInclude Include="..\Include\EgkCurve.h" />
|
||||
<ClInclude Include="..\Include\EgkCurveArc.h" />
|
||||
<ClInclude Include="..\Include\EgkCurveAux.h" />
|
||||
<ClInclude Include="..\Include\EgkCurveBezier.h" />
|
||||
<ClInclude Include="..\Include\EGkCurve.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveArc.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveAux.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveBezier.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveByApprox.h" />
|
||||
<ClInclude Include="..\Include\EgkCurveComposite.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveComposite.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveByInterp.h" />
|
||||
<ClInclude Include="..\Include\EgkCurveLine.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveLine.h" />
|
||||
<ClInclude Include="..\Include\EGkCurveLocal.h" />
|
||||
<ClInclude Include="..\Include\EGkCurvePointDiffGeom.h" />
|
||||
<ClInclude Include="..\Include\EGkDistPointCurve.h" />
|
||||
@@ -558,6 +567,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="DistPointCrvComposite.h" />
|
||||
<ClInclude Include="DistPointLine.h" />
|
||||
<ClInclude Include="DllMain.h" />
|
||||
<ClInclude Include="earcut.hpp" />
|
||||
<ClInclude Include="ExtDimension.h" />
|
||||
<ClInclude Include="ExtText.h" />
|
||||
<ClInclude Include="FontAux.h" />
|
||||
@@ -586,6 +596,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="IntersArcArc.h" />
|
||||
<ClInclude Include="IntersCrvCompoCrvCompo.h" />
|
||||
<ClInclude Include="IntersLineArc.h" />
|
||||
<ClInclude Include="IntersLineBox.h" />
|
||||
<ClInclude Include="IntersLineLine.h" />
|
||||
<ClInclude Include="IntersLineSurfStd.h" />
|
||||
<ClInclude Include="IntersLineTria.h" />
|
||||
@@ -599,7 +610,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="ObjGraphicsMgr.h" />
|
||||
<ClInclude Include="FontOs.h" />
|
||||
<ClInclude Include="AdjustLoops.h" />
|
||||
<ClInclude Include="RemoveCurveSpikes.h" />
|
||||
<ClInclude Include="RemoveCurveDefects.h" />
|
||||
<ClInclude Include="SurfBezier.h" />
|
||||
<ClInclude Include="SurfFlatRegion.h" />
|
||||
<ClInclude Include="TextureData.h" />
|
||||
|
||||
@@ -327,7 +327,7 @@
|
||||
<ClCompile Include="OffsetCurveOnX.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RemoveCurveSpikes.cpp">
|
||||
<ClCompile Include="RemoveCurveDefects.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Polygon3d.cpp">
|
||||
@@ -456,6 +456,21 @@
|
||||
<ClCompile Include="SurfTriMeshUtilities.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshCuts.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HashGrids1d.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCapsTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Circle2P.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MedialAxis.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -626,28 +641,28 @@
|
||||
<ClInclude Include="..\Include\EGkChainCurves.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurveBezier.h">
|
||||
<ClInclude Include="..\Include\EGkCurveBezier.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkColor.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurve.h">
|
||||
<ClInclude Include="..\Include\EGkCurve.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurveArc.h">
|
||||
<ClInclude Include="..\Include\EGkCurveArc.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurveAux.h">
|
||||
<ClInclude Include="..\Include\EGkCurveAux.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkCurveByInterp.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurveComposite.h">
|
||||
<ClInclude Include="..\Include\EGkCurveComposite.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EgkCurveLine.h">
|
||||
<ClInclude Include="..\Include\EGkCurveLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkCurvePointDiffGeom.h">
|
||||
@@ -842,7 +857,7 @@
|
||||
<ClInclude Include="..\Include\EGkIntersLineSurfTm.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RemoveCurveSpikes.h">
|
||||
<ClInclude Include="RemoveCurveDefects.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersPlanePlane.h">
|
||||
@@ -1079,6 +1094,15 @@
|
||||
<ClInclude Include="CDeRectPrismoidTria.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="earcut.hpp">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IntersLineBox.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CDeCapsTria.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+1
-1
@@ -796,7 +796,7 @@ ExtDimension::GetTextHalfDist( const Point3d& ptText) const
|
||||
double dHalfDist = m_dTextHeight / 2 + m_dTextDist ;
|
||||
// recupero il box di ingombro del testo
|
||||
BBox3d b3Text ;
|
||||
if ( GetTextMyBBox( ptText, b3Text)) {
|
||||
if ( GetTextMyBBox( ptText, b3Text) && ! b3Text.IsEmpty()) {
|
||||
double dHalfL = ( b3Text.GetMax().x - b3Text.GetMin().x) / 2 ;
|
||||
double dHalfH = ( b3Text.GetMax().y - b3Text.GetMin().y) / 2 ;
|
||||
dHalfDist = sqrt( dHalfL * dHalfL + dHalfH * dHalfH) ;
|
||||
|
||||
+107
-71
@@ -15,13 +15,90 @@
|
||||
#include "stdafx.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EgkFilletChamfer.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkFilletChamfer.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CalcForFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
const ICurve& cCrv2, const Point3d& ptNear2,
|
||||
const Vector3d& vtNorm, double dRadius,
|
||||
Point3d& ptCen, Point3d& ptTg1, Point3d& ptTg2,
|
||||
int& nSide1, int& nSide2, double& dSinA, double& dTgPar1, double& dTgPar2)
|
||||
{
|
||||
// calcolo un riferimento sul piano perpendicolare alla normale
|
||||
Frame3d frIntr ;
|
||||
if ( ! frIntr.Set( ORIG, vtNorm))
|
||||
return false ;
|
||||
|
||||
// determino il lato di offset della curva 1
|
||||
DistPointCurve dPC1( ptNear2, cCrv1) ;
|
||||
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
|
||||
return false ;
|
||||
double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ;
|
||||
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 1
|
||||
PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ;
|
||||
if ( IsNull( pCopy1))
|
||||
return false ;
|
||||
pCopy1->ToLoc( frIntr) ;
|
||||
pCopy1->SetExtrusion( Z_AX) ;
|
||||
if ( ! pCopy1->SimpleOffset( dOffs1, ICurve::OFF_FILLET))
|
||||
return false ;
|
||||
|
||||
// determino il lato di offset della curva 2
|
||||
DistPointCurve dPC2( ptNear1, cCrv2) ;
|
||||
if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2))
|
||||
return false ;
|
||||
double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ;
|
||||
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 2
|
||||
PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ;
|
||||
if ( IsNull( pCopy2))
|
||||
return false ;
|
||||
pCopy2->ToLoc( frIntr) ;
|
||||
pCopy2->SetExtrusion( Z_AX) ;
|
||||
if ( ! pCopy2->SimpleOffset( dOffs2, ICurve::OFF_FILLET))
|
||||
return false ;
|
||||
|
||||
// calcolo l'intersezione tra le due curve
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Point3d ptNearI = Media( ptNear1, ptNear2) ;
|
||||
ptNearI.ToLoc( frIntr) ;
|
||||
IntersCurveCurve intCC( *pCopy1, *pCopy2) ;
|
||||
if ( ! intCC.GetIntersPointNearTo( 0, ptNearI, ptInt1) ||
|
||||
! intCC.GetIntersPointNearTo( 1, ptNearI, ptInt2))
|
||||
return false ;
|
||||
ptInt1.ToGlob( frIntr) ;
|
||||
ptInt2.ToGlob( frIntr) ;
|
||||
ptCen = Media( ptInt1, ptInt2) ;
|
||||
|
||||
// proiezione del punto di intersezione sulla prima curva
|
||||
DistPointCurve dPCI1( ptInt1, cCrv1) ;
|
||||
int nFlag1 ;
|
||||
if ( ! dPCI1.GetParamAtMinDistPoint( 0, dTgPar1, nFlag1) || nFlag1 != MDPCI_NORMAL)
|
||||
return false ;
|
||||
Vector3d vtTg1 ;
|
||||
if ( ! cCrv1.GetPointTang( dTgPar1, ICurve::FROM_MINUS, ptTg1, vtTg1))
|
||||
return false ;
|
||||
|
||||
// proiezione del punto di intersezione sulla seconda curva
|
||||
DistPointCurve dPCI2( ptInt2, cCrv2) ;
|
||||
int nFlag2 ;
|
||||
if ( ! dPCI2.GetParamAtMinDistPoint( 0, dTgPar2, nFlag2) || nFlag2 != MDPCI_NORMAL)
|
||||
return false ;
|
||||
Vector3d vtTg2 ;
|
||||
if ( ! cCrv2.GetPointTang( dTgPar2, ICurve::FROM_MINUS, ptTg2, vtTg2))
|
||||
return false ;
|
||||
|
||||
// determino rotazione tra le curve
|
||||
dSinA = ( vtTg1 ^ vtTg2) * vtNorm ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveArc*
|
||||
CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
@@ -34,76 +111,26 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo un riferimento sul piano perpendicolare alla normale
|
||||
Frame3d frIntr ;
|
||||
if ( ! frIntr.Set( ORIG, vtNorm))
|
||||
// eseguo calcoli
|
||||
Point3d ptCen, ptTg1, ptTg2 ;
|
||||
int nSide1, nSide2 ;
|
||||
double dSinA, dTgPar1, dTgPar2 ;
|
||||
if ( ! CalcForFillet( cCrv1, ptNear1, cCrv2, ptNear2, vtNorm, dRadius,
|
||||
ptCen, ptTg1, ptTg2, nSide1, nSide2, dSinA, dTgPar1, dTgPar2))
|
||||
return nullptr ;
|
||||
|
||||
// determino il lato di offset della curva 1
|
||||
DistPointCurve dPC1( ptNear2, cCrv1) ;
|
||||
int nSide1 ;
|
||||
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
|
||||
return nullptr ;
|
||||
double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ;
|
||||
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 1
|
||||
PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ;
|
||||
if ( IsNull( pCopy1))
|
||||
return nullptr ;
|
||||
pCopy1->ToLoc( frIntr) ;
|
||||
pCopy1->SetExtrusion( Z_AX) ;
|
||||
if ( ! pCopy1->SimpleOffset( dOffs1, ICurve::OFF_FILLET))
|
||||
return nullptr ;
|
||||
// se tangenti parallele al contatto con fillet, ricalcolo con raggio più piccolo
|
||||
bool bParallel = ( abs( dSinA) < EPS_SMALL) ;
|
||||
if ( bParallel) {
|
||||
Point3d ptQQQ, ptQQ1, ptQQ2 ;
|
||||
double dQQQ1, dQQQ2 ;
|
||||
if ( ! CalcForFillet( cCrv1, ptNear1, cCrv2, ptNear2, vtNorm, dRadius - 10 * EPS_SMALL,
|
||||
ptQQQ, ptQQ1, ptQQ2, nSide1, nSide2, dSinA, dQQQ1, dQQQ2) || abs( dSinA) < EPS_SMALL)
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// determino il lato di offset della curva 2
|
||||
DistPointCurve dPC2( ptNear1, cCrv2) ;
|
||||
int nSide2 ;
|
||||
if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2))
|
||||
return nullptr ;
|
||||
double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ;
|
||||
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 2
|
||||
PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ;
|
||||
if ( IsNull( pCopy2))
|
||||
return nullptr ;
|
||||
pCopy2->ToLoc( frIntr) ;
|
||||
pCopy2->SetExtrusion( Z_AX) ;
|
||||
if ( ! pCopy2->SimpleOffset( dOffs2, ICurve::OFF_FILLET))
|
||||
return nullptr ;
|
||||
|
||||
// calcolo l'intersezione tra le due curve
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Point3d ptNear1I = ptNear1 ;
|
||||
ptNear1I.ToLoc( frIntr) ;
|
||||
IntersCurveCurve intCC( *pCopy1, *pCopy2) ;
|
||||
if ( ! intCC.GetIntersPointNearTo( 0, ptNear1I, ptInt1) ||
|
||||
! intCC.GetIntersPointNearTo( 1, ptNear1I, ptInt2))
|
||||
return nullptr ;
|
||||
ptInt1.ToGlob( frIntr) ;
|
||||
ptInt2.ToGlob( frIntr) ;
|
||||
|
||||
// proiezione del punto di intersezione sulla prima curva
|
||||
DistPointCurve dPCI1( ptInt1, cCrv1) ;
|
||||
double dTgPar1 ;
|
||||
int nFlag1 ;
|
||||
if ( ! dPCI1.GetParamAtMinDistPoint( 0, dTgPar1, nFlag1) || nFlag1 != MDPCI_NORMAL)
|
||||
return nullptr ;
|
||||
Point3d ptTg1 ;
|
||||
Vector3d vtTg1 ;
|
||||
if ( ! cCrv1.GetPointTang( dTgPar1, ICurve::FROM_MINUS, ptTg1, vtTg1))
|
||||
return nullptr ;
|
||||
|
||||
// proiezione del punto di intersezione sulla seconda curva
|
||||
DistPointCurve dPCI2( ptInt2, cCrv2) ;
|
||||
double dTgPar2 ;
|
||||
int nFlag2 ;
|
||||
if ( ! dPCI2.GetParamAtMinDistPoint( 0, dTgPar2, nFlag2) || nFlag2 != MDPCI_NORMAL)
|
||||
return nullptr ;
|
||||
Point3d ptTg2 ;
|
||||
Vector3d vtTg2 ;
|
||||
if ( ! cCrv2.GetPointTang( dTgPar2, ICurve::FROM_MINUS, ptTg2, vtTg2))
|
||||
return nullptr ;
|
||||
|
||||
// determino rotazione tra le curve
|
||||
bool bCCW = (( vtTg1 ^ vtTg2) * vtNorm) > 0 ;
|
||||
// orientamento tra le curve
|
||||
bool bCCW = ( dSinA > 0) ;
|
||||
|
||||
// assegno i valori dei parametri di trim (+ da inizio, - da fine)
|
||||
if ( bCCW) {
|
||||
@@ -118,8 +145,17 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
// creo l'arco di fillet
|
||||
PtrOwner<CurveArc> crvFillet( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( crvFillet) ||
|
||||
! crvFillet->SetC2PN( ptInt1, ptTg1, ptTg2, vtNorm))
|
||||
! crvFillet->SetC2PN( ptCen, ptTg1, ptTg2, vtNorm))
|
||||
return nullptr ;
|
||||
// se direzioni agli estremi praticamente parallele
|
||||
if ( bParallel) {
|
||||
// calcolo il verso dell'arco di fillet
|
||||
bool bFilletCcw = ( ( bCCW && nSide1 == nSide2) || ( ! bCCW && nSide1 != nSide2)) ;
|
||||
// si deve verificare se va usato l'arco esplementare
|
||||
bool bArcCcw = ( crvFillet->GetAngCenter() > 0) ;
|
||||
if ( bFilletCcw != bArcCcw)
|
||||
crvFillet->ToExplementary() ;
|
||||
}
|
||||
return Release(crvFillet) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkVector3d.h"
|
||||
#include "/EgtDev/Include/EGtNumCollection.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double AdjustFontRatio( double dRatio) ;
|
||||
|
||||
+2
-2
@@ -17,9 +17,9 @@
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkGdbIterator.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGnFileUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EgnStringUtils.h"
|
||||
#include "/EgtDev/Include/EgnFileUtils.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
+1
-2
@@ -378,8 +378,7 @@ OsFont::GetRegion( const string& sText, int nInsPos, ISURFFRPLIST& lstSFR) const
|
||||
if ( ! GetCharOutline( vCode[i], dAdvance, lstPC))
|
||||
return false ;
|
||||
// lo trasformo opportunamente
|
||||
ICURVEPLIST::iterator iIter ;
|
||||
for ( iIter = lstPC.begin() ; iIter != lstPC.end() ; ++ iIter) {
|
||||
for ( auto iIter = lstPC.begin() ; iIter != lstPC.end() ; ++ iIter) {
|
||||
// inverto i percorsi per avere gli esterni CCW
|
||||
(*iIter)->Invert() ;
|
||||
// la trasformo per avere solo archi e rette
|
||||
|
||||
+3
-3
@@ -224,10 +224,10 @@ Frame3d::Set( const Point3d& ptOrig, double dAngCDeg, double dAngADeg, double dA
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Frame3d::Reset( void)
|
||||
Frame3d::Reset( bool bGlob)
|
||||
{
|
||||
m_nType = TOP ;
|
||||
m_nZType = TOP ;
|
||||
m_nType = ( bGlob ? TOP : ERR) ;
|
||||
m_nZType = ( bGlob ? TOP : ERR) ;
|
||||
m_ptOrig = ORIG ;
|
||||
m_vtVersX = X_AX ;
|
||||
m_vtVersY = Y_AX ;
|
||||
|
||||
+2
-2
@@ -7921,7 +7921,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
sText += "<br/> " ;
|
||||
sText += " U=" + ToString( aInfo.IciA[j].dU,7) + " P=(" + ToString( aInfo.IciA[j].ptI,4) + ")" ;
|
||||
switch( aInfo.IciA[j].nPrevTy) {
|
||||
case ICCT_NULL : sText += " ??-" ; break ;
|
||||
case ICCT_NULL : sText += " ?" "?-" ; break ;
|
||||
case ICCT_IN : sText += " IN-" ; break ;
|
||||
case ICCT_OUT : sText += " OUT-" ; break ;
|
||||
case ICCT_ON : sText += " ON-" ; break ;
|
||||
@@ -7940,7 +7940,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
sText += string( "<br/>") + ( aInfo.bCBOverEq ? " + " : " - ") ;
|
||||
sText += " U=" + ToString( aInfo.IciB[j].dU,7) + " P=(" + ToString( aInfo.IciB[j].ptI,4) + ")" ;
|
||||
switch( aInfo.IciB[j].nPrevTy) {
|
||||
case ICCT_NULL : sText += " ??-" ; break ;
|
||||
case ICCT_NULL : sText += " ?" "?-" ; break ;
|
||||
case ICCT_IN : sText += " IN-" ; break ;
|
||||
case ICCT_OUT : sText += " OUT-" ; break ;
|
||||
case ICCT_ON : sText += " ON-" ; break ;
|
||||
|
||||
+2
-2
@@ -14,10 +14,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "OutTsc.h"
|
||||
#include "/EgtDev/Include/EgkGdbExecutor.h"
|
||||
#include "/EgtDev/Include/EGkGdbExecutor.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
#include "/EgtDev/Include/EgtExecMgr.h"
|
||||
#include "/EgtDev/Include/EgkGeoCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
#include "Tool.h"
|
||||
|
||||
class PolyLine ;
|
||||
|
||||
@@ -1618,6 +1618,39 @@ GdbIterator::RemoveInfo( const string& sKey)
|
||||
return m_pCurrObj->RemoveInfo( sKey) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbIterator::GetAllInfo( STRVECTOR& vsInfo) const
|
||||
{
|
||||
if ( m_pGDB == nullptr || m_pCurrObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// recupero tutte le Info
|
||||
return m_pCurrObj->GetAllInfo( vsInfo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbIterator::CopyAllInfoFrom( const IGdbIterator& iIter)
|
||||
{
|
||||
if ( m_pGDB == nullptr || m_pCurrObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// recupero l'oggetto sorgente
|
||||
const GdbIterator* pIter = dynamic_cast<const GdbIterator*> (&iIter) ;
|
||||
if ( pIter == nullptr || pIter->m_pGDB != m_pGDB || pIter->m_pCurrObj == nullptr)
|
||||
return false ;
|
||||
const GdbObj* pGdbObjSou = pIter->m_pCurrObj ;
|
||||
|
||||
// copio tutte le Info
|
||||
if ( m_pCurrObj != pGdbObjSou && pGdbObjSou->m_pAttribs != nullptr) {
|
||||
m_pCurrObj->GetSafeAttribs() ;
|
||||
return ( m_pCurrObj->m_pAttribs != nullptr && m_pCurrObj->m_pAttribs->CopyAllInfoFrom( *(pGdbObjSou->m_pAttribs))) ;
|
||||
}
|
||||
else
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// TextureData
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+4
-2
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
// EgalTech 2013-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : GdbIterator.h Data : 04.12.13 Versione : 1.4a3
|
||||
// File : GdbIterator.h Data : 29.01.23 Versione : 2.5a2
|
||||
// Contenuto : Dichiarazione della classe GdbIterator.
|
||||
//
|
||||
//
|
||||
@@ -142,6 +142,8 @@ class GdbIterator : public IGdbIterator
|
||||
bool GetInfo( const std::string& sKey, STRVECTOR& vsInfo) const override ;
|
||||
bool ExistsInfo( const std::string& sKey) const override ;
|
||||
bool RemoveInfo( const std::string& sKey) override ;
|
||||
bool GetAllInfo( STRVECTOR& vsInfo) const override ;
|
||||
bool CopyAllInfoFrom( const IGdbIterator& iIter) override ;
|
||||
// TextureData
|
||||
bool SetTextureName( const std::string& sTxrName) override ;
|
||||
bool SetTextureFrame( const Frame3d& frTxrRef) override ;
|
||||
|
||||
+13
@@ -1024,6 +1024,19 @@ GdbObj::RemoveInfo( const string& sKey)
|
||||
return m_pAttribs->RemoveInfo( sKey) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::GetAllInfo( STRVECTOR& vsInfo) const
|
||||
{
|
||||
// se non ci sono attributi
|
||||
if ( m_pAttribs == nullptr) {
|
||||
vsInfo.clear() ;
|
||||
return true ;
|
||||
}
|
||||
// recupero tutte le Info
|
||||
return m_pAttribs->GetAllInfo( vsInfo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// TextureData
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -119,6 +119,7 @@ class GdbObj
|
||||
bool GetInfo( const std::string& sKey, STRVECTOR& vsInfo) const ;
|
||||
bool ExistsInfo( const std::string& sKey) const ;
|
||||
bool RemoveInfo( const std::string& sKey) ;
|
||||
bool GetAllInfo( STRVECTOR& vsInfo) const ;
|
||||
bool SaveTextureData( NgeWriter& ngeOut) const ;
|
||||
bool LoadTextureData( NgeReader& ngeIn) ;
|
||||
TextureData* GetTextureData( void)
|
||||
|
||||
+6
-2
@@ -50,7 +50,11 @@ const double BEZARC_ANG_CEN_MAX = 90 ;
|
||||
//----------------- Costanti per superfici TriMesh ---------------------------
|
||||
// tolleranza lineare standard
|
||||
const double STM_STD_LIN_TOL = 0.1 ;
|
||||
// angolo limite per definire un edge che è contorno di poligono
|
||||
// angolo limite standard per definire un edge che è contorno di poligono
|
||||
const double STM_STD_BOUNDARY_ANG = 0.1 ;
|
||||
// angolo limite per mediare le normali in un vertice
|
||||
// angolo limite standard per mediare le normali in un vertice
|
||||
const double STM_STD_SMOOTH_ANG = 25.0 ;
|
||||
// distanza limite tra diagonali per quadrilatero con twist
|
||||
const double STM_TWIST_DIAG_DIST = 1.0 ;
|
||||
// angolo limite con twist per mediare le normali in un vertice
|
||||
const double STM_TWIST_SMOOTH_ANG = 35.0 ;
|
||||
|
||||
+68
-42
@@ -37,22 +37,25 @@ IGeomDB*
|
||||
CreateGeomDB( void)
|
||||
{
|
||||
// verifico la chiave e le opzioni
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK && ! EqualNoCase( GetEGkKey(), "EGkBase")) {
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKC/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return nullptr ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_BASE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKC/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return nullptr ;
|
||||
if ( ! GetEGkNetHwKey()) {
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK && ! EqualNoCase( GetEGkKey(), "EGkBase")) {
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKC/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return nullptr ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_BASE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKC/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// creo il GeomDB
|
||||
return static_cast<IGeomDB*> ( new( nothrow) GeomDB) ;
|
||||
}
|
||||
@@ -272,19 +275,21 @@ bool
|
||||
GeomDB::Save( int nId, const string& sFileOut, int nFlag) const
|
||||
{
|
||||
// verifico la chiave e le opzioni
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKS/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
if ( ! GetEGkNetHwKey()) {
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKS/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// assegno Id base
|
||||
@@ -382,19 +387,21 @@ bool
|
||||
GeomDB::Save( const INTVECTOR& vId, const string& sFileOut, int nFlag) const
|
||||
{
|
||||
// verifico la chiave e le opzioni
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKS/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
if ( ! GetEGkNetHwKey()) {
|
||||
unsigned int nOpt1, nOpt2 ;
|
||||
int nOptExpDays ;
|
||||
int nRet = GetKeyOptions( GetEGkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV,
|
||||
nOpt1, nOpt2, nOptExpDays) ;
|
||||
if ( nRet != KEY_OK) {
|
||||
string sErr = "Error on Key (GKS/" + ToString( nRet) + ")" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
if ( (nOpt1 & KEYOPT_EGK_SAVE) == 0 || nOptExpDays < GetCurrDay()) {
|
||||
string sErr = "Error on Key (GKS/OPT)" ;
|
||||
LOG_ERROR( GetEGkLogger(), sErr.c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// assegno Id base (nessuna riduzione degli Id)
|
||||
@@ -513,7 +520,10 @@ GeomDB::SaveHeader( NgeWriter& ngeOut) const
|
||||
|
||||
// LockId del sistema come commento
|
||||
string sLockId ;
|
||||
if ( ! GetLockId( sLockId)) {
|
||||
if ( GetEGkNetHwKey()) {
|
||||
sLockId = "NET-000000" ;
|
||||
}
|
||||
else if ( ! GetLockId( sLockId)) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error on Key (1)")
|
||||
return false ;
|
||||
}
|
||||
@@ -2521,6 +2531,9 @@ GeomDB::GetCalcMaterial( const GdbObj* pGdbObj, Material& mMat) const
|
||||
Color cCol ;
|
||||
if ( pGdbObj->GetCalcMaterial( cCol)) {
|
||||
mMat.Set( cCol) ;
|
||||
Color cDiff = cCol ;
|
||||
cDiff.Intensify( 1.25) ;
|
||||
mMat.SetDiffuse( cDiff) ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
@@ -2874,6 +2887,19 @@ GeomDB::RemoveInfo( int nId, const string& sKey)
|
||||
return pGdbObj->RemoveInfo( sKey) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GeomDB::GetAllInfo( int nId, STRVECTOR& vsInfo) const
|
||||
{
|
||||
// recupero l'oggetto
|
||||
const GdbObj* pGdbObj = GetGdbObj( nId) ;
|
||||
if ( pGdbObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// recupero tutte le Info
|
||||
return pGdbObj->GetAllInfo( vsInfo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GeomDB::CopyAllInfoFrom( int nId, int nSouId)
|
||||
@@ -2883,7 +2909,7 @@ GeomDB::CopyAllInfoFrom( int nId, int nSouId)
|
||||
if ( pGdbObj == nullptr)
|
||||
return false ;
|
||||
// recupero l'oggetto sorgente
|
||||
GdbObj* pGdbObjSou = GetGdbObj( nSouId) ;
|
||||
const GdbObj* pGdbObjSou = GetGdbObj( nSouId) ;
|
||||
if ( pGdbObjSou == nullptr)
|
||||
return false ;
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ class GeomDB : public IGeomDB
|
||||
bool GetInfo( int nId, const std::string& sKey, STRVECTOR& vsInfo) const override ;
|
||||
bool ExistsInfo( int nId, const std::string& sKey) const override ;
|
||||
bool RemoveInfo( int nId, const std::string& sKey) override ;
|
||||
bool GetAllInfo( int nId, STRVECTOR& vsInfo) const override ;
|
||||
bool CopyAllInfoFrom( int nId, int nSouId) override ;
|
||||
// TextureData
|
||||
bool DumpTextureData( int nId, std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ;
|
||||
|
||||
+759
@@ -0,0 +1,759 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2018
|
||||
//----------------------------------------------------------------------------
|
||||
// File : HashGrids1d.cpp Data : 02.05.22 Versione : 2.4e1
|
||||
// Contenuto : Funzioni della classe HashGrids1d.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 04.07.15 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids1d.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const size_t CellCount = 16 ;
|
||||
const size_t cellVectorSize = 16 ;
|
||||
const size_t occupiedCellsVectorSize = 256 ;
|
||||
const size_t minimalGridDensity = 1 ;
|
||||
const size_t gridActivationThreshold = 64 ;
|
||||
const double hierarchyFactor = 2 ;
|
||||
const double MIN_CELL_SIZE = 5.0 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// HashGrid1d
|
||||
//----------------------------------------------------------------------------
|
||||
class HashGrid1d
|
||||
{
|
||||
private :
|
||||
struct Cell
|
||||
{
|
||||
HashGrids1d::PtrObjVector* m_Objs ; // Vettore dei puntatori agli oggetti nella cella, come puntatore
|
||||
int* m_neighborOffset ; // Puntatore ad array con offsets per accedere direttamente ai vicini
|
||||
size_t m_occupiedCellsId ; // Indice della cella nel vettore delle celle occupate
|
||||
Cell( void)
|
||||
: m_Objs( nullptr), m_neighborOffset( nullptr), m_occupiedCellsId( 0) {}
|
||||
} ;
|
||||
|
||||
typedef vector<Cell*> CellVector ;
|
||||
|
||||
public :
|
||||
explicit HashGrid1d( double dCellSpan) ;
|
||||
~HashGrid1d( void) ;
|
||||
double GetCellSpan( void) const
|
||||
{ return m_dCellSpan ; }
|
||||
void Add( HashGrids1d::ObjData& obj) ;
|
||||
void Remove( HashGrids1d::ObjData& obj) ;
|
||||
void Update( HashGrids1d::ObjData& obj) ;
|
||||
void Find( const BBox3d& b3Test, INTVECTOR& vnIds) ;
|
||||
void Clear( void) ;
|
||||
|
||||
private :
|
||||
void InitNeighborOffsets( void) ;
|
||||
size_t Hash( const Point3d& ptP) const ;
|
||||
void Add( HashGrids1d::ObjData& obj, Cell* cell) ;
|
||||
void Remove( HashGrids1d::ObjData& obj, Cell* cell) ;
|
||||
void Enlarge( void) ;
|
||||
static inline bool PowerOfTwo( size_t number) ;
|
||||
|
||||
private :
|
||||
Cell* m_cell ; // Vettore di celle della griglia
|
||||
|
||||
size_t m_CellCount ; // Numero di celle allocate in direzione Z
|
||||
|
||||
size_t m_HashMask ; // Maschera di bit per calcolo hash
|
||||
|
||||
size_t m_enlargementThreshold ; // Soglia corrente per incremetare le dimensioni della griglia
|
||||
|
||||
double m_dCellSpan ; // Dimensione di una cella (cubica) della griglia
|
||||
double m_dInvCellSpan ; // Inverso della dimensione di una cella
|
||||
|
||||
CellVector m_occupiedCells ; // Vettore delle celle occupate in questa griglia
|
||||
|
||||
size_t m_objCount ; // Numero di oggetti presenti in questa griglia
|
||||
|
||||
int m_stdNeighborOffset[3] ; // Array degli offset standard per le adiacenze
|
||||
|
||||
BBox3d m_b3Grid ; // Box totale degli oggetti inseriti in questa griglia
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
HashGrid1d::HashGrid1d( double dCellSpan)
|
||||
{
|
||||
// Initialization of all member variables and ...
|
||||
m_CellCount = PowerOfTwo( CellCount) ? CellCount : 16 ;
|
||||
|
||||
m_HashMask = m_CellCount - 1 ;
|
||||
|
||||
m_enlargementThreshold = m_CellCount / minimalGridDensity ;
|
||||
|
||||
// allocazione dell'array lineare che rappresenta lo hash grid.
|
||||
m_cell = new Cell[ m_CellCount] ;
|
||||
|
||||
// ogni cella è già inizializzata come vuota
|
||||
// imposto gli offset ai vicini
|
||||
InitNeighborOffsets() ;
|
||||
|
||||
m_dCellSpan = max( dCellSpan, 10 * EPS_SMALL) ;
|
||||
m_dInvCellSpan = 1. / dCellSpan ;
|
||||
|
||||
m_occupiedCells.reserve( occupiedCellsVectorSize) ;
|
||||
|
||||
m_objCount = 0 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
HashGrid1d::~HashGrid1d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Add( HashGrids1d::ObjData& obj)
|
||||
{
|
||||
// If adding the body will cause the total number of bodies assigned to this grid to exceed the
|
||||
// enlargement threshold, the size of this hash grid must be increased.
|
||||
if ( m_objCount == m_enlargementThreshold)
|
||||
Enlarge() ;
|
||||
|
||||
// Calculate (and store) the hash value (= the body's cell association) and ...
|
||||
size_t h = Hash( obj.box.GetMin()) ;
|
||||
obj.nHash = h ;
|
||||
|
||||
// ... insert the body into the corresponding cell.
|
||||
Cell* pCell = m_cell + h ;
|
||||
Add( obj, pCell) ;
|
||||
++ m_objCount ;
|
||||
|
||||
// Aggiorno box di griglia
|
||||
m_b3Grid.Add( obj.box) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Remove( HashGrids1d::ObjData& obj)
|
||||
{
|
||||
// The stored hash value (= the body's cell association) is used in order to directly access the
|
||||
// cell from which this body will be removed.
|
||||
Cell* pCell = m_cell + obj.nHash ;
|
||||
Remove( obj, pCell) ;
|
||||
-- m_objCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Update( HashGrids1d::ObjData& obj)
|
||||
{
|
||||
// The hash value is recomputed based on the body's current spatial location.
|
||||
size_t newHash = Hash( obj.box.GetMin()) ;
|
||||
size_t oldHash = obj.nHash ;
|
||||
|
||||
// If this new hash value is identical to the hash value of the previous time step, the body
|
||||
// remains assigned to its current grid cell.
|
||||
if ( newHash == oldHash)
|
||||
return ;
|
||||
|
||||
// Only if the hash value changes, the cell association has to be changed, too - meaning, the
|
||||
// body has to be removed from its currently assigned cell and ...
|
||||
Cell* pCell = m_cell + oldHash ;
|
||||
Remove( obj, pCell) ;
|
||||
|
||||
obj.nHash = newHash ;
|
||||
|
||||
// ... stored in the cell that corresponds to the new hash value.
|
||||
pCell = m_cell + newHash ;
|
||||
Add( obj, pCell) ;
|
||||
|
||||
// Aggiorno box di griglia
|
||||
m_b3Grid.Add( obj.box) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds)
|
||||
{
|
||||
// Limito il box a quello di griglia
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Test.FindIntersection( m_b3Grid, b3Int))
|
||||
return ;
|
||||
|
||||
// Recupero gli estremi del box
|
||||
Point3d ptMin ;
|
||||
double dXDim, dYDim, dZDim ;
|
||||
if ( ! b3Int.GetMinDim( ptMin, dXDim, dYDim, dZDim))
|
||||
return ;
|
||||
// Sposto p.to minimo in meno di una cella (oggetti possono occupare 2 celle) e allargo tutto di EPS_SMALL
|
||||
ptMin -= Vector3d( 0, 0, 1) * ( m_dCellSpan + EPS_SMALL) ;
|
||||
dZDim += m_dCellSpan + 2 * EPS_SMALL ;
|
||||
|
||||
// Numero di celle da esplorare sull'asse Z
|
||||
int nZSpan = min( static_cast<int>( ceil( dZDim * m_dInvCellSpan)), int( m_CellCount)) ;
|
||||
|
||||
//string sOut = "Celle=" + ToString( int( m_CellCount)) + " Occupate=" + ToString( int(m_occupiedCells.size())) + " Span=" + ToString( nZSpan) ;
|
||||
//LOG_INFO( GetEGkLogger(), sOut.c_str()) ;
|
||||
|
||||
// Se conviene verificare queste celle
|
||||
if ( nZSpan < 5 * int( m_occupiedCells.size())) {
|
||||
// cella di base
|
||||
int nZ = static_cast<int>( Hash( ptMin)) ;
|
||||
for ( int i = 0 ; i <= nZSpan ; ++ i) {
|
||||
// inserisco in lista gli oggetti della cella
|
||||
if ( m_cell[nZ].m_Objs != nullptr) {
|
||||
for ( auto pObj : *( m_cell[nZ].m_Objs)) {
|
||||
if ( b3Int.Overlaps( pObj->box))
|
||||
vnIds.push_back( pObj->nId) ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva in Z+
|
||||
nZ += m_cell[nZ].m_neighborOffset[2] ;
|
||||
}
|
||||
}
|
||||
|
||||
// altrimenti verifico direttamente tutte e sole quelle occupate
|
||||
else {
|
||||
// ciclo sulle celle occupate
|
||||
for ( auto cell : m_occupiedCells) {
|
||||
// inserisco in lista gli oggetti della cella
|
||||
if ( cell->m_Objs != nullptr) {
|
||||
for ( auto pObj : *(cell->m_Objs)) {
|
||||
if ( b3Int.Overlaps( pObj->box))
|
||||
vnIds.push_back( pObj->nId) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Clear( void)
|
||||
{
|
||||
for ( auto cell : m_occupiedCells) {
|
||||
delete cell->m_Objs ;
|
||||
cell->m_Objs = nullptr ;
|
||||
}
|
||||
m_occupiedCells.clear() ;
|
||||
m_objCount = 0 ;
|
||||
m_b3Grid.Reset() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::InitNeighborOffsets( void)
|
||||
{
|
||||
int nc = static_cast<int>( m_CellCount) ;
|
||||
|
||||
// Initialization of the grid-global offset array that is valid for all inner cells in the hash grid.
|
||||
m_stdNeighborOffset[0] = -1 ;
|
||||
m_stdNeighborOffset[1] = 0 ;
|
||||
m_stdNeighborOffset[2] = 1 ;
|
||||
|
||||
// Allocation and initialization of the offset arrays of all the border cells. All inner cells
|
||||
// are set to point to the grid-global offset array.
|
||||
Cell* c = m_cell ;
|
||||
for ( int i = 0 ; i < nc ; ++ i, ++ c) {
|
||||
// cella di bordo
|
||||
if ( i == 0) {
|
||||
c->m_neighborOffset = new int[3] ;
|
||||
c->m_neighborOffset[0] = nc - 1 ;
|
||||
c->m_neighborOffset[1] = 0 ;
|
||||
c->m_neighborOffset[2] = 1 ;
|
||||
}
|
||||
else if ( i == nc - 1) {
|
||||
c->m_neighborOffset = new int[3] ;
|
||||
c->m_neighborOffset[0] = -1 ;
|
||||
c->m_neighborOffset[1] = 0 ;
|
||||
c->m_neighborOffset[2] = -nc + 1 ;
|
||||
}
|
||||
// cella interna
|
||||
else {
|
||||
c->m_neighborOffset = m_stdNeighborOffset ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
size_t
|
||||
HashGrid1d::Hash( const Point3d& ptP) const
|
||||
{
|
||||
size_t nHash ;
|
||||
if ( ptP.z < 0) {
|
||||
double i = ( - ptP.z ) * m_dInvCellSpan ;
|
||||
nHash = m_CellCount - 1 - ( static_cast<size_t>( i ) & m_HashMask) ;
|
||||
}
|
||||
else {
|
||||
double i = ptP.z * m_dInvCellSpan ;
|
||||
nHash = static_cast<size_t>( i ) & m_HashMask ;
|
||||
}
|
||||
|
||||
return nHash ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Add( HashGrids1d::ObjData& obj, Cell* cell)
|
||||
{
|
||||
// If this cell is already occupied by other bodies, which means the pointer to the body
|
||||
// container holds a valid address and thus the container itself is properly initialized, then
|
||||
// the body is simply added to this already existing body container. Note that the index position
|
||||
// is memorized (=> "body->setCellId()") in order to ensure constant time removal.
|
||||
if ( cell->m_Objs != nullptr) {
|
||||
obj.nCellId = cell->m_Objs->size() ;
|
||||
cell->m_Objs->push_back( &obj) ;
|
||||
}
|
||||
|
||||
// If, however, the cell is still empty, then the object container, first of all, must be created
|
||||
// (i.e., allocated) and properly initialized (i.e., sufficient initial storage capacity must be
|
||||
// reserved). Furthermore, the cell must be inserted into the grid-global vector 'm_occupiedCells'
|
||||
// in which all cells that are currently occupied by bodies are recorded.
|
||||
else {
|
||||
cell->m_Objs = new HashGrids1d::PtrObjVector ;
|
||||
cell->m_Objs->reserve( cellVectorSize) ;
|
||||
|
||||
obj.nCellId = 0 ;
|
||||
cell->m_Objs->push_back( &obj) ;
|
||||
|
||||
cell->m_occupiedCellsId = m_occupiedCells.size() ;
|
||||
m_occupiedCells.push_back( cell) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Remove( HashGrids1d::ObjData& obj, Cell* cell )
|
||||
{
|
||||
// If the body is the last body that is stored in this cell ...
|
||||
if ( cell->m_Objs->size() == 1) {
|
||||
// ... the cell's body container is destroyed and ...
|
||||
delete cell->m_Objs ;
|
||||
cell->m_Objs = nullptr ;
|
||||
|
||||
// ... the cell is removed from the grid-global vector 'm_occupiedCells' that records all
|
||||
// body-occupied cells. Since the cell memorized its index (=> 'm_occupiedCellsId') in this
|
||||
// vector, it can be removed in constant time, O(1).
|
||||
if ( cell->m_occupiedCellsId == m_occupiedCells.size() - 1) {
|
||||
m_occupiedCells.pop_back() ;
|
||||
}
|
||||
else {
|
||||
Cell* lastCell = m_occupiedCells.back() ;
|
||||
m_occupiedCells.pop_back() ;
|
||||
lastCell->m_occupiedCellsId = cell->m_occupiedCellsId ;
|
||||
m_occupiedCells[ cell->m_occupiedCellsId ] = lastCell ;
|
||||
}
|
||||
}
|
||||
// If the body is *not* the last body that is stored in this cell ...
|
||||
else {
|
||||
size_t cellId = obj.nCellId ;
|
||||
|
||||
// ... the body is removed from the cell's body container. Since the body memorized its
|
||||
// index (=> 'cellId') in this container, it can be removed in constant time, O(1).
|
||||
if ( cellId == cell->m_Objs->size() - 1) {
|
||||
cell->m_Objs->pop_back() ;
|
||||
}
|
||||
else {
|
||||
HashGrids1d::ObjData* lastElement = cell->m_Objs->back() ;
|
||||
cell->m_Objs->pop_back() ;
|
||||
lastElement->nCellId = cellId ;
|
||||
(*cell->m_Objs)[ cellId] = lastElement ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrid1d::Enlarge( void)
|
||||
{
|
||||
HashGrids1d::PtrObjVector PObjVecTemp ;
|
||||
PObjVecTemp.reserve( m_objCount) ;
|
||||
|
||||
// All objs that are assigned to this grid are temporarily removed, ...
|
||||
for ( auto cell = m_occupiedCells.begin() ; cell < m_occupiedCells.end() ; ++ cell) {
|
||||
HashGrids1d::PtrObjVector* cellBodies = (*cell)->m_Objs ;
|
||||
for ( auto e = cellBodies->begin() ; e < cellBodies->end() ; ++ e) {
|
||||
PObjVecTemp.push_back( *e) ;
|
||||
}
|
||||
}
|
||||
|
||||
// ... the grid's current data structures are deleted, ...
|
||||
Clear() ;
|
||||
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_CellCount *= 2 ;
|
||||
m_HashMask = m_CellCount - 1 ;
|
||||
|
||||
// ... a new threshold for enlarging this hash grid is set, ...
|
||||
m_enlargementThreshold = m_CellCount / minimalGridDensity ;
|
||||
|
||||
// ... a new linear array of cells representing this enlarged hash grid is allocated and ...
|
||||
m_cell = new Cell[ m_CellCount] ;
|
||||
|
||||
// ... initialized, and finally ...
|
||||
InitNeighborOffsets() ;
|
||||
|
||||
// ... all previously removed objs are reinserted.
|
||||
for ( auto p = PObjVecTemp.begin() ; p < PObjVecTemp.end() ; ++ p) {
|
||||
Add( **p) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrid1d::PowerOfTwo( size_t number)
|
||||
{
|
||||
return ( ( number > 0) && ( ( number & ( number - 1)) == 0)) ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// HashGrids1d
|
||||
//----------------------------------------------------------------------------
|
||||
HashGrids1d::HashGrids1d( void)
|
||||
{
|
||||
try {
|
||||
// Finchè il numero di oggetti non supera la soglia non si usano le griglie
|
||||
m_nonGridObjs.reserve( gridActivationThreshold) ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
}
|
||||
catch(...) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in HashGrids1d constructor") ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
HashGrids1d::~HashGrids1d( void)
|
||||
{
|
||||
// Delete all grids that are stored in the grid hierarchy (=> m_GridList).
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::SetActivationGrid( bool bActivate)
|
||||
{
|
||||
m_bActivate = bActivate ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrids1d::Add( int nObjId, const BBox3d& box)
|
||||
{
|
||||
try {
|
||||
// The body is marked as being added to 'm_objsToAdd' by setting the grid pointer to nullptr and
|
||||
// setting the cell-ID to '0'. Additionally, the hash value is used to memorize the body's
|
||||
// index position in the 'm_objsToAdd' vector.
|
||||
m_ObjsList.emplace_back( nObjId, box, nullptr, m_objsToAdd.size(), 0) ;
|
||||
|
||||
// inserisco nel Map
|
||||
m_ObjsMap.emplace( nObjId, &(m_ObjsList.back())) ;
|
||||
|
||||
// Temporarily add the body to 'm_objsToAdd'. As soon as "findContacts()" is called, all
|
||||
// bodies stored in 'm_objsToAdd' are finally inserted into the data structure.
|
||||
m_objsToAdd.push_back( &(m_ObjsList.back())) ;
|
||||
|
||||
// Aggiorno il box complessivo
|
||||
m_b3Objs.Add( box) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
catch(...) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in HashGrids1d::Add") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrids1d::Modify( int nObjId, const BBox3d& box)
|
||||
{
|
||||
// Cerco l'oggetto con l'Id voluto
|
||||
auto iIter = m_ObjsMap.find( nObjId) ;
|
||||
if ( iIter == m_ObjsMap.end())
|
||||
return false ;
|
||||
ObjData* pObj = iIter->second ;
|
||||
if ( pObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// Modifico il suo box
|
||||
pObj->box = box ;
|
||||
|
||||
// Aggiorno il box complessivo
|
||||
m_b3Objs.Add( box) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrids1d::Remove( int nObjId)
|
||||
{
|
||||
// Cerco l'oggetto con l'Id voluto
|
||||
auto iIter = m_ObjsMap.find( nObjId) ;
|
||||
if ( iIter == m_ObjsMap.end())
|
||||
return false ;
|
||||
ObjData* pObj = iIter->second ;
|
||||
if ( pObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// Recupero la griglia di appartenenza
|
||||
HashGrid1d* pGrid = pObj->pHGrid ;
|
||||
|
||||
// The body is stored in a hash grid from which it must be removed.
|
||||
if ( pGrid != nullptr) {
|
||||
pGrid->Remove( *pObj) ;
|
||||
}
|
||||
// The body's grid pointer is equal to nullptr.
|
||||
// => The body is either stored in 'm_objsToAdd' (-> cell-ID = 0) or 'm_nonGridObjs' (-> cell-ID = 1).
|
||||
else {
|
||||
if ( pObj->nCellId == 0) {
|
||||
// the body's hash value => index of this body in 'm_objsToAdd'
|
||||
if ( pObj->nHash == m_objsToAdd.size() - 1) {
|
||||
m_objsToAdd.pop_back() ;
|
||||
}
|
||||
else if ( pObj->nHash < m_objsToAdd.size()) {
|
||||
ObjData* pLastObj = m_objsToAdd.back() ;
|
||||
m_objsToAdd.pop_back() ;
|
||||
pLastObj->nHash = pObj->nHash ;
|
||||
m_objsToAdd[ pObj->nHash] = pLastObj ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else {
|
||||
// the body's hash value => index of this body in 'm_nonGridObjs'
|
||||
if ( pObj->nHash == m_nonGridObjs.size() - 1) {
|
||||
m_nonGridObjs.pop_back();
|
||||
}
|
||||
else if ( pObj->nHash < m_nonGridObjs.size()) {
|
||||
ObjData* pLastObj = m_nonGridObjs.back() ;
|
||||
m_nonGridObjs.pop_back() ;
|
||||
pLastObj->nHash = pObj->nHash ;
|
||||
m_nonGridObjs[ pObj->nHash] = pLastObj ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrids1d::Update( void)
|
||||
{
|
||||
try {
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
else
|
||||
addList( *pObj) ;
|
||||
}
|
||||
m_objsToAdd.clear() ;
|
||||
}
|
||||
// Aggiorniamo per eventuali modifiche agli oggetti già precedentemente presenti nelle griglie
|
||||
if ( bGridActivePrev) {
|
||||
for ( auto& Obj : m_ObjsList) {
|
||||
HashGrid1d* pGrid = Obj.pHGrid ;
|
||||
if ( pGrid != nullptr) {
|
||||
double dSize = 0 ;
|
||||
Obj.box.GetDiameter( dSize) ;
|
||||
double dCellSpan = pGrid->GetCellSpan() ;
|
||||
|
||||
if ( dSize >= dCellSpan || dSize < ( dCellSpan / hierarchyFactor)) {
|
||||
pGrid->Remove( Obj) ;
|
||||
addGrid( Obj) ;
|
||||
}
|
||||
else {
|
||||
pGrid->Update( Obj) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
catch(...) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in HashGrids1d::Update") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
HashGrids1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
{
|
||||
// pulisco il risultato
|
||||
vnIds.clear() ;
|
||||
vnIds.reserve( 128) ;
|
||||
|
||||
// limito con box globale
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Test.FindIntersection( m_b3Objs, b3Int))
|
||||
return false ;
|
||||
|
||||
// ricerca nelle griglie
|
||||
if ( m_bGridActive) {
|
||||
for ( auto pGrid : m_GridList)
|
||||
pGrid->Find( b3Int, vnIds) ;
|
||||
}
|
||||
|
||||
// ricerca negli oggetti fuori griglia
|
||||
for ( auto pObj : m_nonGridObjs) {
|
||||
if ( b3Int.Overlaps( pObj->box))
|
||||
vnIds.push_back( pObj->nId) ;
|
||||
}
|
||||
|
||||
// ordino il risultato ed elimino gli indici ripetuti
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::addGrid( ObjData& obj)
|
||||
{
|
||||
double size = - 1 ;
|
||||
obj.box.GetDiameter( size) ;
|
||||
|
||||
// If the body is finite in size, it must be assigned to a grid with suitably sized cells.
|
||||
if ( size > - EPS_ZERO) {
|
||||
|
||||
size = max( size, MIN_CELL_SIZE) ;
|
||||
|
||||
HashGrid1d* pGrid = nullptr ;
|
||||
|
||||
if ( m_GridList.empty()) {
|
||||
// If no hash grid yet exists in the hierarchy, an initial hash grid is created
|
||||
// based on the body's size.
|
||||
|
||||
pGrid = new HashGrid1d( size * sqrt( hierarchyFactor)) ;
|
||||
}
|
||||
else {
|
||||
// Check the hierarchy for a hash grid with suitably sized cells - if such a grid does not
|
||||
// yet exist, it will be created.
|
||||
|
||||
double cellSpan = 0;
|
||||
for ( auto g = m_GridList.begin(); g != m_GridList.end(); ++ g) {
|
||||
pGrid = *g;
|
||||
cellSpan = pGrid->GetCellSpan();
|
||||
|
||||
if ( size < cellSpan) {
|
||||
cellSpan /= hierarchyFactor ;
|
||||
if ( size < cellSpan ) {
|
||||
while ( size < cellSpan)
|
||||
cellSpan /= hierarchyFactor ;
|
||||
pGrid = new HashGrid1d( cellSpan * hierarchyFactor) ;
|
||||
m_GridList.insert( g, pGrid) ;
|
||||
}
|
||||
|
||||
pGrid->Add( obj) ;
|
||||
obj.pHGrid = pGrid ;
|
||||
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
while ( size >= cellSpan)
|
||||
cellSpan *= hierarchyFactor ;
|
||||
pGrid = new HashGrid1d( cellSpan) ;
|
||||
}
|
||||
|
||||
pGrid->Add( obj) ;
|
||||
obj.pHGrid = pGrid ;
|
||||
|
||||
m_GridList.push_back( pGrid) ;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// The body - which is infinite in size - is marked as being added to 'm_nonGridObjs' by setting
|
||||
// the grid pointer to nullptr and setting the cell-ID to '1'. Additionally, the hash value is used
|
||||
// to memorize the body's index position in the 'm_nonGridObjs' vector.
|
||||
|
||||
obj.pHGrid = nullptr ;
|
||||
obj.nHash = m_nonGridObjs.size() ;
|
||||
obj.nCellId = 1 ;
|
||||
|
||||
m_nonGridObjs.push_back( &obj) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::addList( ObjData& obj)
|
||||
{
|
||||
// Se abilitato e superata la soglia ...
|
||||
if ( m_bActivate && m_nonGridObjs.size() == gridActivationThreshold) {
|
||||
if ( gridActivationThreshold > 0) {
|
||||
|
||||
// all objs stored in 'm_nonGridObjs' are inserted in grids
|
||||
for ( size_t i = 0; i < gridActivationThreshold; ++i ) {
|
||||
addGrid( *m_nonGridObjs[i] );
|
||||
}
|
||||
|
||||
// ... the 'm_nonGridObjs' vector is cleared ...
|
||||
m_nonGridObjs.clear() ;
|
||||
}
|
||||
|
||||
addGrid( obj) ;
|
||||
|
||||
// ... and the usage of the hierarchical hash grids is activated irrevocably.
|
||||
m_bGridActive = true ;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// The body is marked as being added to 'm_nonGridObjs' by setting the grid pointer to nullptr and
|
||||
// setting the cell-ID to '1'. Additionally, the hash value is used to memorize the body's index
|
||||
// position in the 'm_nonGridObjs' vector.
|
||||
obj.pHGrid = nullptr ;
|
||||
obj.nHash = m_nonGridObjs.size() ;
|
||||
obj.nCellId = 1 ;
|
||||
m_nonGridObjs.push_back( &obj) ;
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids2d.h"
|
||||
#include "/EgtDev/Include/EgnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+1
-2
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
||||
#include "/EgtDev/Include/EgnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -684,7 +684,6 @@ HashGrids3d::Update( void)
|
||||
double dSize = 0 ;
|
||||
Obj.box.GetDiameter( dSize) ;
|
||||
double dCellSpan = pGrid->GetCellSpan() ;
|
||||
|
||||
if ( dSize >= dCellSpan || dSize < ( dCellSpan / hierarchyFactor)) {
|
||||
pGrid->Remove( Obj) ;
|
||||
addGrid( Obj) ;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include "CurveAux.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkAngle.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids2d.h"
|
||||
#include <algorithm>
|
||||
@@ -541,7 +541,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// se il tipo di accostamento per la curva A non è definito
|
||||
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
|
||||
if ( i > 0 || bCrvAClosed) {
|
||||
if ( i > 0 || ( bCrvAClosed && ! bAutoInters)) {
|
||||
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
|
||||
m_Info[i].IciA[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciA[1].nNextTy : m_Info[j].IciA[0].nNextTy) ;
|
||||
}
|
||||
@@ -549,7 +549,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// se il tipo di allontanamento per la curva A non è definito
|
||||
int ki = ( m_Info[i].bOverlap ? 1 : 0) ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
if ( i < m_nNumInters - 1 || bCrvAClosed) {
|
||||
if ( i < m_nNumInters - 1 || ( bCrvAClosed && ! bAutoInters)) {
|
||||
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
|
||||
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[0].nPrevTy ;
|
||||
}
|
||||
@@ -561,14 +561,14 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
|
||||
// se il tipo di accostamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
|
||||
if ( i > 0 || bCrvBClosed) {
|
||||
if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
|
||||
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
|
||||
}
|
||||
}
|
||||
// se il tipo di allontanamento per la curva B non è definito
|
||||
if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) {
|
||||
if ( i < m_nNumInters - 1 || bCrvBClosed) {
|
||||
if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) {
|
||||
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
|
||||
m_Info[i].IciB[0].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
|
||||
}
|
||||
@@ -702,9 +702,9 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// assegno sottoindici (considero solo intersezioni overlap)
|
||||
int ki = 0 ;
|
||||
int kj = 1 ;
|
||||
// verifico se entrambe overlap, la precedente termina con ON e la successiva inizia con ON
|
||||
// verifico se entrambe overlap con lo stesso verso, la precedente termina con ON e la successiva inizia con ON
|
||||
// sia sulla curva A sia sulla curva B (tenendo conto del senso equiverso/controverso)
|
||||
if ( m_Info[j].bOverlap && m_Info[i].bOverlap &&
|
||||
if ( m_Info[j].bOverlap && m_Info[i].bOverlap && m_Info[j].bCBOverEq == m_Info[i].bCBOverEq &&
|
||||
m_Info[j].IciA[kj].nNextTy == ICCT_ON && m_Info[i].IciA[ki].nPrevTy == ICCT_ON &&
|
||||
GetCrvBDirANext( m_Info[j]) == ICCT_ON && GetCrvBDirAPrev( m_Info[i]) == ICCT_ON) {
|
||||
// CurvaA : riporto il secondo punto del successivo sul secondo punto del precedente
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+127
-108
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2020
|
||||
// EgalTech 2020-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
|
||||
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
|
||||
// Contenuto : Implementazione della intersezione linea/box.
|
||||
//
|
||||
//
|
||||
@@ -13,13 +13,77 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptMin, const Point3d& ptMax,
|
||||
double& dU1, double& dU2)
|
||||
{
|
||||
// Verifico il versore
|
||||
if ( vtL.IsSmall())
|
||||
return false ;
|
||||
|
||||
// Verifico gli estremi del box
|
||||
if ( ptMin.x > ptMax.x + EPS_SMALL ||
|
||||
ptMin.y > ptMax.y + EPS_SMALL ||
|
||||
ptMin.z > ptMax.z + EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Casi di intersezione impossibile
|
||||
if ( abs( vtL.x) < EPS_ZERO && ( ptL.x < ptMin.x - EPS_SMALL || ptL.x > ptMax.x + EPS_SMALL))
|
||||
return false ;
|
||||
if ( abs( vtL.y) < EPS_ZERO && ( ptL.y < ptMin.y - EPS_SMALL || ptL.y > ptMax.y + EPS_SMALL))
|
||||
return false ;
|
||||
if ( abs( vtL.z) < EPS_ZERO && ( ptL.z < ptMin.z - EPS_SMALL || ptL.z > ptMax.z + EPS_SMALL))
|
||||
return false ;
|
||||
|
||||
// Parametri degli estremi della retta
|
||||
dU1 = -INFINITO ;
|
||||
dU2 = INFINITO ;
|
||||
|
||||
// Confronto con piani YZ (perpendicolari ad asse X)
|
||||
if ( vtL.x > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.x - ptL.x) / vtL.x) ;
|
||||
dU2 = min( dU2, ( ptMax.x - ptL.x) / vtL.x) ;
|
||||
}
|
||||
else if ( vtL.x < -EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMax.x - ptL.x) / vtL.x) ;
|
||||
dU2 = min( dU2, ( ptMin.x - ptL.x) / vtL.x) ;
|
||||
}
|
||||
|
||||
// Confronto con piani ZX (perpendicolari ad asse Y)
|
||||
if ( vtL.y > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.y - ptL.y) / vtL.y) ;
|
||||
dU2 = min( dU2, ( ptMax.y - ptL.y) / vtL.y) ;
|
||||
}
|
||||
else if ( vtL.y < -EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMax.y - ptL.y) / vtL.y) ;
|
||||
dU2 = min( dU2, ( ptMin.y - ptL.y) / vtL.y) ;
|
||||
}
|
||||
|
||||
// Confronto con piani XY (perpendicolari ad asse Z)
|
||||
if ( vtL.z > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.z - ptL.z) / vtL.z) ;
|
||||
dU2 = min( dU2, ( ptMax.z - ptL.z) / vtL.z) ;
|
||||
}
|
||||
else if ( vtL.z < -EPS_ZERO){
|
||||
dU1 = max( dU1, ( ptMax.z - ptL.z) / vtL.z) ;
|
||||
dU2 = min( dU2, ( ptMin.z - ptL.z) / vtL.z) ;
|
||||
}
|
||||
|
||||
return ( dU2 >= dU1) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL1, const Point3d& ptL2, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
|
||||
@@ -38,114 +102,69 @@ bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
|
||||
{
|
||||
// Recupero i dati del Box
|
||||
Point3d ptMin ;
|
||||
double dDimX, dDimY, dDimZ ;
|
||||
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
|
||||
Point3d ptMin, ptMax ;
|
||||
if ( ! b3Box.GetMinMax( ptMin, ptMax))
|
||||
return false ;
|
||||
// Contorno di base
|
||||
PolyLine PL ;
|
||||
PL.AddUPoint( 0, ptMin) ;
|
||||
PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0, 0)) ;
|
||||
PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY, 0)) ;
|
||||
PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY, 0)) ;
|
||||
PL.Close() ;
|
||||
// Vettore altezza
|
||||
Vector3d vtExtr( 0, 0, dDimZ) ;
|
||||
// Creo la superficie trimesh equivalente
|
||||
SurfTriMesh Stm ;
|
||||
if ( ! Stm.CreateByExtrusion( PL, vtExtr))
|
||||
return false ;
|
||||
SurfTriMesh StmBot ;
|
||||
if ( ! StmBot.CreateByFlatContour( PL))
|
||||
return false ;
|
||||
StmBot.Invert() ;
|
||||
SurfTriMesh StmTop ;
|
||||
if ( ! StmTop.CreateByFlatContour( PL))
|
||||
return false ;
|
||||
StmTop.Translate( vtExtr) ;
|
||||
if ( ! Stm.DoSewing( StmBot) || ! Stm.DoSewing( StmTop))
|
||||
return false ;
|
||||
// Calcolo l'intersezione
|
||||
ILSIVECTOR vInfo ;
|
||||
if ( ! IntersLineSurfTm( ptL, vtL, dLen, Stm, vInfo, bFinite))
|
||||
return false ;
|
||||
// ciclo sulle intersezioni
|
||||
double dUcurr = -INFINITO ;
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = ILBT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = ILBT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = ILBT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
dUcurr = Info.dU ;
|
||||
|
||||
// Pulisco vettore intersezioni
|
||||
vInters.clear() ;
|
||||
|
||||
// Eseguo intersezione della linea completa
|
||||
double dU1, dU2 ;
|
||||
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
|
||||
|
||||
// Se non c'è intersezione
|
||||
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
|
||||
return true ;
|
||||
|
||||
// Se le due intersezioni coincidono
|
||||
if ( ( dU2 - dU1) < EPS_SMALL) {
|
||||
double dU = ( dU1 + dU2) / 2 ;
|
||||
if ( ! bFinite) {
|
||||
vInters.emplace_back( ILBT_TOUCH, dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
if ( Info.dU > dUcurr - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( ILBT_TG_FIN, Info.dU2) ;
|
||||
dUcurr = Info.dU2 ;
|
||||
else {
|
||||
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se sono dello stesso tipo, elimino una delle due
|
||||
if ( vInters[i].first == vInters[j].first) {
|
||||
// se entranti elimino la prima
|
||||
if ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_TG_INI)
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
// altrimenti la seconda
|
||||
else
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
if ( i > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
// se hanno lo stesso parametro
|
||||
else if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
if ( ( vInters[i].first == ILBT_IN && vInters[j].first == ILBT_OUT) ||
|
||||
( vInters[i].first == ILBT_OUT && vInters[j].first == ILBT_IN)) {
|
||||
vInters[i].first = ILBT_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
if ( i > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
// se prima puntuale e l'altra inizio o fine di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_OUT || vInters[i].first == ILBT_TOUCH) &&
|
||||
( vInters[j].first == ILBT_TG_INI || vInters[j].first == ILBT_TG_FIN)) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
if ( i > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
// se prima inizio o fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( ( vInters[i].first == ILBT_TG_INI || vInters[i].first == ILBT_TG_FIN) &&
|
||||
( vInters[j].first == ILBT_IN || vInters[j].first == ILBT_OUT || vInters[j].first == ILBT_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
if ( i > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( ( vInters[i].first == ILBT_TG_FIN && vInters[j].first == ILBT_TG_INI) ||
|
||||
( vInters[i].first == ILBT_TG_INI && vInters[j].first == ILBT_TG_FIN)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
if ( i > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Se sono due intersezioni con la linea giacente su una faccia del box
|
||||
if ( ( abs( vtL.x) < EPS_ZERO && ( abs( ptL.x - ptMin.x) < EPS_SMALL || abs( ptL.x - ptMax.x) < EPS_SMALL)) ||
|
||||
( abs( vtL.y) < EPS_ZERO && ( abs( ptL.y - ptMin.y) < EPS_SMALL || abs( ptL.y - ptMax.y) < EPS_SMALL)) ||
|
||||
( abs( vtL.z) < EPS_ZERO && ( abs( ptL.z - ptMin.z) < EPS_SMALL || abs( ptL.z - ptMax.z) < EPS_SMALL))) {
|
||||
if ( ! bFinite) {
|
||||
vInters.emplace_back( ILBT_TG_INI, dU1) ;
|
||||
vInters.emplace_back( ILBT_TG_FIN, dU2) ;
|
||||
}
|
||||
else {
|
||||
if ( dU1 > dLen - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_IN, dLen) ;
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Altrimenti sono due intersezioni con attraversamento
|
||||
if ( ! bFinite) {
|
||||
vInters.emplace_back( ILBT_IN, dU1) ;
|
||||
vInters.emplace_back( ILBT_OUT, dU2) ;
|
||||
}
|
||||
else {
|
||||
if ( dU1 > dLen - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_IN, dLen) ;
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2022-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineBox.h Data : 08.01.22 Versione : 2.4a3
|
||||
// Contenuto : Dichiarazione delle funzioni base per intersezione linea/box.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 08.01.22 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato agli assi sono nel medesimo riferimento.
|
||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptMin, const Point3d& ptMax,
|
||||
double& dU1, double& dU2) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
TestIntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptMin, const Point3d& ptMax)
|
||||
{
|
||||
double dU1, dU2 ;
|
||||
return IntersLineBox( ptL, vtL, ptMin, ptMax, dU1, dU2) ;
|
||||
}
|
||||
+3
-56
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2017-2018
|
||||
// EgalTech 2017-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineSurfStd.cpp Data : 03.12.18 Versione : 1.9l1
|
||||
// File : IntersLineSurfStd.cpp Data : 08.01.22 Versione : 2.4a3
|
||||
// Contenuto : Implementazione delle funzioni di intersezione
|
||||
// componente lineare e superficie standard.
|
||||
//
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineSurfStd.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
@@ -21,60 +22,6 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Punti e vettore devono essere espressi nel medesimo sistema di riferimento.
|
||||
// Il box è allineato con gli assi di questo sistema di riferimento.
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
|
||||
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2)
|
||||
{
|
||||
// Casi di intersezione impossibile
|
||||
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL))
|
||||
return false ;
|
||||
if ( abs( vtV.y) < EPS_ZERO && ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL))
|
||||
return false ;
|
||||
if ( abs( vtV.z) < EPS_ZERO && ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL))
|
||||
return false ;
|
||||
|
||||
// Inizializzo parametri intersezioni
|
||||
dU1 = -INFINITO ;
|
||||
dU2 = INFINITO ;
|
||||
|
||||
// Confronto con piani YZ (perpendicolari ad asse X)
|
||||
if ( vtV.x > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ;
|
||||
dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ;
|
||||
}
|
||||
else if ( vtV.x < -EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ;
|
||||
dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ;
|
||||
}
|
||||
|
||||
// Confronto con piani ZX (perpendicolari ad asse Y)
|
||||
if ( vtV.y > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ;
|
||||
dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ;
|
||||
}
|
||||
else if ( vtV.y < -EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ;
|
||||
dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ;
|
||||
}
|
||||
|
||||
// Confronto con piani XY (perpendicolari ad asse Z)
|
||||
if ( vtV.z > EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ;
|
||||
dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ;
|
||||
}
|
||||
else if ( vtV.z < -EPS_ZERO) {
|
||||
dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ;
|
||||
dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ;
|
||||
}
|
||||
|
||||
return ( dU2 >= dU1) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
LineDisc( const Point3d& ptPLine, const Vector3d& vtVLine,
|
||||
|
||||
@@ -34,11 +34,6 @@
|
||||
// Costanti tipologia di componente lineare
|
||||
enum LinType { Line = 0, Ray = 1, Segment = 2} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
|
||||
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) ;
|
||||
|
||||
|
||||
// Costanti tipologia di intersezioni fra un componente lineare e un disco
|
||||
enum LinCompDiscIntersType { D_ERROR_INT = -1, D_NO_INTERS = 0, D_BOUNDARY_INT_LINE_NOT_IN_PLANE = 1,
|
||||
D_INNER_INT_LINE_NOT_IN_PLANE = 2, D_ONE_INT_LINE_ON_PLANE = 3,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2019
|
||||
// EgalTech 2015-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineSurfTm.cpp Data : 09.03.15 Versione : 2.1b6
|
||||
// File : IntersLineSurfTm.cpp Data : 08.01.22 Versione : 2.4a3
|
||||
// Contenuto : Implementazione della intersezione linea/superficie trimesh.
|
||||
//
|
||||
//
|
||||
@@ -14,8 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "IntersLineSurfStd.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
|
||||
|
||||
+34
-6
@@ -1,8 +1,8 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
|
||||
// Contenuto : Implementazione della intersezione linea/box.
|
||||
// File : IntersPlaneBox.cpp Data : 07.05.20 Versione : 2.2e1
|
||||
// Contenuto : Implementazione della intersezione piano/box.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -20,19 +20,47 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
|
||||
bool
|
||||
IntersPlaneBox( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box,
|
||||
TestIntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box)
|
||||
{
|
||||
// Verifica del piano
|
||||
if ( ! plPlane.IsValid())
|
||||
return false ;
|
||||
// Centro e estensione del box
|
||||
Point3d ptCen ;
|
||||
Vector3d vtExt ;
|
||||
if ( ! b3Box.GetCenterExtent( ptCen, vtExt))
|
||||
return false ;
|
||||
// Distanza del centro dal piano
|
||||
double dDist = DistPointPlane( ptCen, plPlane) ;
|
||||
// Proiezione dell'estensione sulla normale al piano
|
||||
Vector3d vtN = plPlane.GetVersN() ;
|
||||
double dProjExt = vtExt.x * abs( vtN.x) + vtExt.y * abs( vtN.y) + vtExt.z * abs( vtN.z) ;
|
||||
// Confronto distanza del centro con estensione proiettata
|
||||
return ( abs( dDist) < dProjExt + EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box,
|
||||
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
|
||||
{
|
||||
// Creo il piano
|
||||
Plane3d plPlane ;
|
||||
if ( ! plPlane.Set( ptOn, vtN))
|
||||
// Verifico il piano
|
||||
if ( ! plPlane.IsValid())
|
||||
return false ;
|
||||
// Recupero i dati del Box
|
||||
Point3d ptMin ;
|
||||
double dDimX, dDimY, dDimZ ;
|
||||
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
|
||||
return false ;
|
||||
// Pulisco vettori intersezioni
|
||||
vPnt.clear() ;
|
||||
vBpt.clear() ;
|
||||
vTria.clear() ;
|
||||
// Verifico se può esistere intersezione
|
||||
if ( ! TestIntersPlaneBox( plPlane, b3Box))
|
||||
return true ;
|
||||
// Contorno di base
|
||||
PolyLine PL ;
|
||||
PL.AddUPoint( 0, ptMin) ;
|
||||
|
||||
+223
-97
@@ -27,102 +27,39 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di un piano con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
|
||||
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
|
||||
{
|
||||
// verifico piano
|
||||
if ( &plPlane == nullptr || plPlane.GetVersN().IsSmall())
|
||||
return false ;
|
||||
// verifico superficie
|
||||
if ( &Stm == nullptr || ! Stm.IsValid())
|
||||
return false ;
|
||||
// verifico parametri di ritorno
|
||||
if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr)
|
||||
return false ;
|
||||
vPnt.clear() ;
|
||||
vBpt.clear() ;
|
||||
vTria.clear() ;
|
||||
|
||||
// per ricerca veloce di punti ripetuti
|
||||
PointGrid3d PtGrid ;
|
||||
PtGrid.Init( 100) ;
|
||||
|
||||
// per ricerca veloce di linee ripetute
|
||||
HashGrids3d LnGrid ;
|
||||
LnGrid.SetActivationGrid( true) ;
|
||||
|
||||
// per ricerca veloce di triangoli ripetuti
|
||||
HashGrids3d TrGrid ;
|
||||
TrGrid.SetActivationGrid( true) ;
|
||||
|
||||
// cerco i triangoli intersecati dal piano
|
||||
Triangle3d Tria ;
|
||||
int nT = Stm.GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// intersezione tra il piano e il triangolo
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersPlaneTria( plPlane, Tria, ptInt, ptInt2) ;
|
||||
// se vertice
|
||||
if ( nRes == IPTT_VERT) {
|
||||
// verifico se punto già inserito
|
||||
int nId ;
|
||||
if ( ! PtGrid.Find( ptInt, 10 * EPS_SMALL, nId)) {
|
||||
vPnt.emplace_back( ptInt) ;
|
||||
PtGrid.InsertPoint( ptInt, int( vPnt.size()) - 1) ;
|
||||
}
|
||||
static void
|
||||
UpdateIntersPlaneSurfTm( const Plane3d& plPlane, const Triangle3d& Tria, PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria,
|
||||
PointGrid3d& PtGrid, HashGrids3d& LnGrid, HashGrids3d& TrGrid)
|
||||
{
|
||||
// intersezione tra il piano e il triangolo
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersPlaneTria( plPlane, Tria, ptInt, ptInt2) ;
|
||||
// se vertice
|
||||
if ( nRes == IPTT_VERT) {
|
||||
// verifico se punto già inserito
|
||||
int nId ;
|
||||
if ( ! PtGrid.Find( ptInt, 10 * EPS_SMALL, nId)) {
|
||||
vPnt.emplace_back( ptInt) ;
|
||||
PtGrid.InsertPoint( ptInt, int( vPnt.size()) - 1) ;
|
||||
}
|
||||
// se altrimenti segmento
|
||||
else if ( nRes == IPTT_EDGE || nRes == IPTT_YES) {
|
||||
// se abbastanza lungo
|
||||
if ( ! AreSamePointApprox( ptInt, ptInt2)) {
|
||||
// verifico se già inserito
|
||||
bool bFound = false ;
|
||||
BBox3d b3Line( ptInt, ptInt2) ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( LnGrid.Find( b3Line, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nA = vnIds[i] ;
|
||||
const Point3d& ptOth = vBpt[nA].first ;
|
||||
const Point3d& ptOth2 = vBpt[nA].second ;
|
||||
if ( ( AreSamePointEpsilon( ptInt, ptOth, 10 * EPS_SMALL) &&
|
||||
AreSamePointEpsilon( ptInt2, ptOth2, 10 * EPS_SMALL)) ||
|
||||
( AreSamePointEpsilon( ptInt, ptOth2, 10 * EPS_SMALL) &&
|
||||
AreSamePointEpsilon( ptInt2, ptOth, 10 * EPS_SMALL))) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se non inserito, procedo
|
||||
if ( ! bFound) {
|
||||
vBpt.emplace_back( ptInt, ptInt2) ;
|
||||
LnGrid.Add( int( vBpt.size()) - 1, b3Line) ;
|
||||
LnGrid.Update() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se altrimenti l'intero triangolo
|
||||
else if ( nRes == IPTT_OVERLAPS) {
|
||||
// verifico se triangolo già inserito
|
||||
}
|
||||
// se altrimenti segmento
|
||||
else if ( nRes == IPTT_EDGE || nRes == IPTT_YES) {
|
||||
// se abbastanza lungo
|
||||
if ( ! AreSamePointApprox( ptInt, ptInt2)) {
|
||||
// verifico se già inserito
|
||||
bool bFound = false ;
|
||||
BBox3d b3Tria( Tria.GetP( 0), Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
BBox3d b3Line( ptInt, ptInt2) ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( TrGrid.Find( b3Tria, vnIds)) {
|
||||
if ( LnGrid.Find( b3Line, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nA = vnIds[i] ;
|
||||
const Triangle3d& trOth = vTria[nA] ;
|
||||
array< bool, 3> bOth = { false, false, false} ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
for ( int k = 0 ; k < 3 ; ++ k) {
|
||||
if ( ! bOth[k])
|
||||
bOth[k] = AreSamePointEpsilon( Tria.GetP( j), trOth.GetP( k), 10 * EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
if ( bOth[0] && bOth[1] && bOth[2]) {
|
||||
const Point3d& ptOth = vBpt[nA].first ;
|
||||
const Point3d& ptOth2 = vBpt[nA].second ;
|
||||
if ( ( AreSamePointEpsilon( ptInt, ptOth, 10 * EPS_SMALL) &&
|
||||
AreSamePointEpsilon( ptInt2, ptOth2, 10 * EPS_SMALL)) ||
|
||||
( AreSamePointEpsilon( ptInt, ptOth2, 10 * EPS_SMALL) &&
|
||||
AreSamePointEpsilon( ptInt2, ptOth, 10 * EPS_SMALL))) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -130,15 +67,52 @@ IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
|
||||
}
|
||||
// se non inserito, procedo
|
||||
if ( ! bFound) {
|
||||
vTria.emplace_back( Tria) ;
|
||||
TrGrid.Add( int( vTria.size()) - 1, b3Tria) ;
|
||||
TrGrid.Update() ;
|
||||
vBpt.emplace_back( ptInt, ptInt2) ;
|
||||
LnGrid.Add( int( vBpt.size()) - 1, b3Line) ;
|
||||
LnGrid.Update() ;
|
||||
}
|
||||
}
|
||||
// passo al prossimo triangolo
|
||||
nT = Stm.GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
// se altrimenti l'intero triangolo
|
||||
else if ( nRes == IPTT_OVERLAPS) {
|
||||
// verifico se triangolo già inserito
|
||||
bool bFound = false ;
|
||||
BBox3d b3Tria( Tria.GetP( 0), Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( TrGrid.Find( b3Tria, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nA = vnIds[i] ;
|
||||
const Triangle3d& trOth = vTria[nA] ;
|
||||
array< bool, 3> bOth = { false, false, false} ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
for ( int k = 0 ; k < 3 ; ++ k) {
|
||||
if ( ! bOth[k])
|
||||
bOth[k] = AreSamePointEpsilon( Tria.GetP( j), trOth.GetP( k), 10 * EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
if ( bOth[0] && bOth[1] && bOth[2]) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se non inserito, procedo
|
||||
if ( ! bFound) {
|
||||
vTria.emplace_back( Tria) ;
|
||||
TrGrid.Add( int( vTria.size()) - 1, b3Tria) ;
|
||||
TrGrid.Update() ;
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
AdjustIntersPlaneSurfTm( PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria,
|
||||
const Plane3d& plPlane, const HashGrids3d& LnGrid, const HashGrids3d& TrGrid)
|
||||
{
|
||||
// rimuovo i punti che stanno sui segmenti
|
||||
for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) {
|
||||
bool bFound = false ;
|
||||
@@ -190,7 +164,7 @@ IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
|
||||
int nA = vnIds[j] ;
|
||||
const Triangle3d& trOth = vTria[nA] ;
|
||||
if ( DistPointTriangle( ptStart, trOth).IsEpsilon( 10 * EPS_SMALL) &&
|
||||
DistPointTriangle( ptEnd, trOth).IsEpsilon( 10 * EPS_SMALL)) {
|
||||
DistPointTriangle( ptEnd, trOth).IsEpsilon( 10 * EPS_SMALL)) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -200,5 +174,157 @@ IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
|
||||
vBpt.erase( vBpt.begin() + i) ;
|
||||
}
|
||||
|
||||
// porto i punti esattamente nel piano
|
||||
for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
|
||||
vPnt[i] = ProjectPointOnPlane( vPnt[i], plPlane) ;
|
||||
}
|
||||
|
||||
// porto i segmenti esattamente nel piano
|
||||
for ( int i = 0 ; i < int( vBpt.size()) ; ++ i) {
|
||||
vBpt[i].first = ProjectPointOnPlane( vBpt[i].first, plPlane) ;
|
||||
vBpt[i].second = ProjectPointOnPlane( vBpt[i].second, plPlane) ;
|
||||
}
|
||||
|
||||
// porto i triangoli esattamente nel piano
|
||||
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) {
|
||||
Triangle3d& trTria = vTria[i] ;
|
||||
trTria.SetP( 0, ProjectPointOnPlane( trTria.GetP( 0), plPlane)) ;
|
||||
trTria.SetP( 1, ProjectPointOnPlane( trTria.GetP( 1), plPlane)) ;
|
||||
trTria.SetP( 2, ProjectPointOnPlane( trTria.GetP( 2), plPlane)) ;
|
||||
trTria.Validate( true) ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di un piano con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneSurfTm( const Plane3d& plPlane, const ISurfTriMesh& Stm,
|
||||
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
|
||||
{
|
||||
// verifico piano
|
||||
if ( &plPlane == nullptr || plPlane.GetVersN().IsSmall())
|
||||
return false ;
|
||||
// verifico superficie
|
||||
if ( &Stm == nullptr || ! Stm.IsValid())
|
||||
return false ;
|
||||
// verifico parametri di ritorno
|
||||
if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr)
|
||||
return false ;
|
||||
vPnt.clear() ;
|
||||
vBpt.clear() ;
|
||||
vTria.clear() ;
|
||||
|
||||
// per ricerca veloce di punti ripetuti
|
||||
PointGrid3d PtGrid ;
|
||||
PtGrid.Init( 100) ;
|
||||
|
||||
// per ricerca veloce di linee ripetute
|
||||
HashGrids3d LnGrid ;
|
||||
LnGrid.SetActivationGrid( true) ;
|
||||
|
||||
// per ricerca veloce di triangoli ripetuti
|
||||
HashGrids3d TrGrid ;
|
||||
TrGrid.SetActivationGrid( true) ;
|
||||
|
||||
// cerco i triangoli intersecati dal piano
|
||||
Triangle3d Tria ;
|
||||
int nT = Stm.GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
UpdateIntersPlaneSurfTm( plPlane, Tria, vPnt, vBpt, vTria, PtGrid, LnGrid, TrGrid) ;
|
||||
nT = Stm.GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
|
||||
AdjustIntersPlaneSurfTm( vPnt, vBpt, vTria, plPlane, LnGrid, TrGrid) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di molti piani paralleli con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
IntersParPlanesSurfTm::IntersParPlanesSurfTm( const Frame3d& frPlanes, const ISurfTriMesh& Stm)
|
||||
: m_bOk( false), m_frPlanes( frPlanes), m_pSTm( &Stm)
|
||||
{
|
||||
// verifico esistenza superficie
|
||||
if ( m_pSTm == nullptr || ! m_pSTm->IsValid())
|
||||
return ;
|
||||
|
||||
// creo HashGrid 1d
|
||||
const int LIM_HG_TRIA = 127 ;
|
||||
m_HGrids.SetActivationGrid( m_pSTm->GetTriangleCount() > LIM_HG_TRIA) ;
|
||||
|
||||
// riempio HashGrid
|
||||
Triangle3d Tria ;
|
||||
int nT = Stm.GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// calcolo il BBox del triangolo nel riferimento dei piani
|
||||
Tria.ToLoc( m_frPlanes) ;
|
||||
BBox3d b3Tria ;
|
||||
b3Tria.Add( Tria.GetP( 0)) ;
|
||||
b3Tria.Add( Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
// inserisco nella griglia
|
||||
if ( ! m_HGrids.Add( nT, b3Tria))
|
||||
return ;
|
||||
// passo al prossimo triangolo
|
||||
nT = Stm.GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
// aggiorno
|
||||
m_bOk = m_HGrids.Update() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersParPlanesSurfTm::GetInters( double dDist, PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria) const
|
||||
{
|
||||
// verifico validità
|
||||
if ( ! m_bOk)
|
||||
return false ;
|
||||
|
||||
// verifico parametri di ritorno
|
||||
if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr)
|
||||
return false ;
|
||||
vPnt.clear() ;
|
||||
vBpt.clear() ;
|
||||
vTria.clear() ;
|
||||
|
||||
// per ricerca veloce di punti ripetuti
|
||||
PointGrid3d PtGrid ;
|
||||
PtGrid.Init( 100) ;
|
||||
|
||||
// per ricerca veloce di linee ripetute
|
||||
HashGrids3d LnGrid ;
|
||||
LnGrid.SetActivationGrid( true) ;
|
||||
|
||||
// per ricerca veloce di triangoli ripetuti
|
||||
HashGrids3d TrGrid ;
|
||||
TrGrid.SetActivationGrid( true) ;
|
||||
|
||||
// calcolo il piano ( in globale)
|
||||
Point3d ptPl = m_frPlanes.Orig() + dDist * m_frPlanes.VersZ() ;
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptPl, m_frPlanes.VersZ()) ;
|
||||
|
||||
// calcolo box del piano ( nel riferimento)
|
||||
BBox3d b3Plane ;
|
||||
b3Plane.Add( Point3d( 0, 0, dDist)) ;
|
||||
b3Plane.Expand( INFINITO - 1 , INFINITO - 1, 0) ;
|
||||
|
||||
// recupero indici triangoli che intersecano box
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Plane, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nT = vnIds[i] ;
|
||||
Triangle3d Tria ;
|
||||
m_pSTm->GetTriangle( nT, Tria) ;
|
||||
UpdateIntersPlaneSurfTm( plPlane, Tria, vPnt, vBpt, vTria, PtGrid, LnGrid, TrGrid) ;
|
||||
}
|
||||
}
|
||||
|
||||
AdjustIntersPlaneSurfTm( vPnt, vBpt, vTria, plPlane, LnGrid, TrGrid) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EgnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <array>
|
||||
|
||||
using namespace std ;
|
||||
@@ -116,7 +116,7 @@ IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2,
|
||||
}
|
||||
}
|
||||
// se altrimenti sovrapposizione
|
||||
else if ( nRes == ITTT_OVERLAPS) {
|
||||
else if ( nRes == ITTT_OVERLAPS || nRes == ITTT_COUNTER_OVERLAPS) {
|
||||
for ( const auto& Tria : vIttTria) {
|
||||
// verifico se triangolo già inserito
|
||||
bool bFound = false ;
|
||||
|
||||
+34
-5
@@ -83,8 +83,37 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
|
||||
// se i triangoli sono complanari
|
||||
if ( nResPP == IPPT_OVERLAPS ||
|
||||
((( nVertPos1 == 0 && nVertNeg1 == 0) || ( nVertPos2 == 0 && nVertNeg2 == 0)) &&
|
||||
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL))
|
||||
return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ;
|
||||
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL)) {
|
||||
// verifica per triangoli con normali controverse
|
||||
bool bCounter = false ;
|
||||
Triangle3d trMyTria2 = trTria2 ;
|
||||
if ( trTria1.GetN() * trTria2.GetN() < 0) {
|
||||
Point3d ptV0 = trMyTria2.GetP( 0) ;
|
||||
trMyTria2.SetP( 0, trMyTria2.GetP( 1)) ;
|
||||
trMyTria2.SetP( 1, ptV0) ;
|
||||
trMyTria2.Validate() ;
|
||||
bCounter = true ;
|
||||
}
|
||||
// verifica per triangoli coincidenti
|
||||
bool bAreSameTria = ( ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 0)) &&
|
||||
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 1)) &&
|
||||
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 2))) ||
|
||||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 1)) &&
|
||||
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 2)) &&
|
||||
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 0))) ||
|
||||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 2)) &&
|
||||
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 0)) &&
|
||||
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 1)))) &&
|
||||
( AreSameVectorExact( trTria1.GetN(), trMyTria2.GetN())) ;
|
||||
if ( bAreSameTria) {
|
||||
vTria.emplace_back( trTria1) ;
|
||||
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
|
||||
}
|
||||
if ( ITTT_OVERLAPS == IntersCoplanarTriaTria( trTria1, trMyTria2, vTria)) {
|
||||
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
|
||||
}
|
||||
return ITTT_NO ;
|
||||
}
|
||||
|
||||
// limito la linea di intersezione con il primo triangolo
|
||||
Point3d ptSt1, ptEn1 ;
|
||||
@@ -112,7 +141,7 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
|
||||
int
|
||||
IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TRIA3DVECTOR& vTria)
|
||||
{
|
||||
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c'è intersezione
|
||||
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c'� intersezione
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
Vector3d vtSide = trTria1.GetP( ( i + 1) % 3) - trTria1.GetP( i) ;
|
||||
Vector3d vtSN = vtSide ^ trTria1.GetN() ;
|
||||
@@ -122,7 +151,7 @@ IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TR
|
||||
( trTria2.GetP( 2) - trTria1.GetP( i)) * vtSN > - EPS_TRIA_H)
|
||||
return ITTT_NO ;
|
||||
}
|
||||
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c'è intersezione
|
||||
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c'� intersezione
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
Vector3d vtSide = trTria2.GetP( ( i + 1) % 3) - trTria2.GetP( i) ;
|
||||
Vector3d vtSN = vtSide ^ trTria2.GetN() ;
|
||||
@@ -205,7 +234,7 @@ int
|
||||
FindTriaTriaIntersType( const Triangle3d& trTria1, const Triangle3d& trTria2, const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
double dStU1, double dEnU1, double dStU2, double dEnU2, int nRes1, int nRes2, double& dIntStU, double& dIntEnU)
|
||||
{
|
||||
// Controllo su validità input
|
||||
// Controllo su validit� input
|
||||
if ( ! ( trTria1.IsValid() && trTria2.IsValid() && vtLineDir.IsNormalized()))
|
||||
return ITTT_NO ;
|
||||
// Casi
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "/EgtDev/Include/EgkLinePerpTwoCurves.h"
|
||||
#include "/EgtDev/Include/EgkLinePntPerpCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePerpTwoCurves.h"
|
||||
#include "/EgtDev/Include/EGkLinePntPerpCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EgkLinePntMinDistCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntMinDistCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkLinePntPerpCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntPerpCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EgkLineTgCurvePerpCurve.h"
|
||||
#include "/EgtDev/Include/EgkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkLineTgCurvePerpCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EgkLineTgTwoCurves.h"
|
||||
#include "/EgtDev/Include/EGkLineTgTwoCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2022-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : MedialAxis.cpp Data : 22.08.22 Versione : 2.4h2
|
||||
// Contenuto : Funzione calcolo approssimato MedialAxis principale.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 22.08.22 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkBBox3d.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkMedialAxis.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProcessCircleCurve( const Point3d& ptCen, double dDiam, const CurveComposite& crvCompo,
|
||||
PNTVECTOR& vPnt, DBLVECTOR& vDiam)
|
||||
{
|
||||
|
||||
// pulizia risultati
|
||||
vPnt.clear() ;
|
||||
vDiam.clear() ;
|
||||
// creazione circonferenza
|
||||
CurveArc crvCirc ;
|
||||
crvCirc.Set( ptCen, Z_AX, dDiam / 2) ;
|
||||
// classificazioni parti di circonferenza rispetto alla curva
|
||||
IntersCurveCurve LnCmpInt( crvCirc, crvCompo) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! LnCmpInt.GetCurveClassification( 0, 10 * EPS_SMALL, ccClass))
|
||||
return false ;
|
||||
int nCount = int( ccClass.size()) ;
|
||||
|
||||
// ... per evitare percorsi di ritorno
|
||||
int nInparts = 0 ;
|
||||
|
||||
for ( int i = 0 ; i < nCount ; ++ i) {
|
||||
if ( ccClass[i].nClass == CRVC_IN) {
|
||||
nInparts ++ ;
|
||||
// gestione unione intervallo a cavallo del parametro 0==1
|
||||
if ( i == nCount - 1 && ccClass[0].nClass == CRVC_IN && ccClass[0].dParS < EPS_ZERO && ccClass[i].dParE > 1 - EPS_ZERO) {
|
||||
double dPar = ( ccClass[i].dParS + 1 + ccClass[0].dParE) / 2 ;
|
||||
if ( dPar > 1)
|
||||
dPar -= 1 ;
|
||||
Point3d ptP ;
|
||||
crvCirc.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP) ;
|
||||
vPnt[0] = ptP ;
|
||||
double dDelta = ccClass[i].dParE - ccClass[i].dParS + ccClass[0].dParE - ccClass[0].dParS ;
|
||||
vDiam[0] = PIGRECO * dDiam * dDelta ;
|
||||
nInparts-- ;
|
||||
}
|
||||
// altrimenti caso standard
|
||||
else {
|
||||
double dPar = ( ccClass[i].dParS + ccClass[i].dParE) / 2 ;
|
||||
Point3d ptP ;
|
||||
crvCirc.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP) ;
|
||||
vPnt.emplace_back( ptP) ;
|
||||
double dDelta = ccClass[i].dParE - ccClass[i].dParS ;
|
||||
vDiam.emplace_back( PIGRECO * dDiam * dDelta) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( nInparts == 1)
|
||||
vPnt.clear() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveSimpleMedialAxis( const ICurve* pCrv, PolyLine& PL)
|
||||
{
|
||||
// pulizia della polilinea
|
||||
PL.Clear() ;
|
||||
// verifico che la curva esista
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// verifico che la curva sia chiusa
|
||||
if ( ! pCrv->IsClosed())
|
||||
return false ;
|
||||
// verifico che la curva sia piana
|
||||
Plane3d plPlane ;
|
||||
if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
// eventuali trasformazioni in composita
|
||||
CurveComposite crvCompo ;
|
||||
if ( pCrv->GetType() == CRV_ARC) {
|
||||
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
crvCompo.AddCurve( *pArc) ;
|
||||
}
|
||||
else if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const CurveBezier* pBez = GetBasicCurveBezier( pCrv) ;
|
||||
PolyArc PA ;
|
||||
if ( ! pBez->ApproxWithArcs( 10 * EPS_SMALL, ANG_TOL_STD_DEG, PA) || ! crvCompo.FromPolyArc( PA))
|
||||
return false ;
|
||||
}
|
||||
else if ( pCrv->GetType() == CRV_COMPO) {
|
||||
crvCompo.AddCurve( *pCrv) ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
// se è una circonferenza
|
||||
Point3d ptCen ; Vector3d vtN ; double dRad ; bool bCCW ;
|
||||
if ( crvCompo.IsACircle( 10 * EPS_SMALL, ptCen, vtN, dRad, bCCW)) {
|
||||
PL.AddUPoint( 0, ptCen) ;
|
||||
return true ;
|
||||
}
|
||||
// la porto nel riferimento del piano
|
||||
Frame3d frLoc ;
|
||||
frLoc.Set( ORIG, plPlane.GetVersN()) ;
|
||||
crvCompo.ToLoc( frLoc) ;
|
||||
// lo oriento in senso antiorario
|
||||
double dArea ;
|
||||
if ( ! crvCompo.GetAreaXY( dArea))
|
||||
return false ;
|
||||
if ( dArea < 0)
|
||||
crvCompo.Invert() ;
|
||||
// ne calcolo il box
|
||||
BBox3d b3Compo ;
|
||||
if ( ! crvCompo.GetLocalBBox( b3Compo, BBF_STANDARD))
|
||||
return false ;
|
||||
|
||||
// ricerca di un punto di partenza
|
||||
CurveLine crvLine ;
|
||||
if ( b3Compo.GetDimX() > b3Compo.GetDimY()) {
|
||||
Point3d ptP1 = Media( b3Compo.GetMin(), b3Compo.GetMax()) - 0.6 * b3Compo.GetDimY() * Y_AX ;
|
||||
Point3d ptP2 = ptP1 + 1.2 * b3Compo.GetDimY() * Y_AX ;
|
||||
crvLine.Set( ptP1, ptP2) ;
|
||||
}
|
||||
else {
|
||||
Point3d ptP1 = Media( b3Compo.GetMin(), b3Compo.GetMax()) - 0.6 * b3Compo.GetDimX() * X_AX ;
|
||||
Point3d ptP2 = ptP1 + 1.2 * b3Compo.GetDimX() * X_AX ;
|
||||
crvLine.Set( ptP1, ptP2) ;
|
||||
}
|
||||
|
||||
IntersCurveCurve LnCmpInt( crvLine, crvCompo) ;
|
||||
if ( LnCmpInt.GetCrossIntersCount() < 2)
|
||||
return false ;
|
||||
IntCrvCrvInfo aInfo[2] ;
|
||||
LnCmpInt.GetIntCrvCrvInfo( 0, aInfo[0]) ;
|
||||
LnCmpInt.GetIntCrvCrvInfo( 1, aInfo[1]) ;
|
||||
Point3d ptOrig = Media( aInfo[0].IciA->ptI, aInfo[1].IciA->ptI) ;
|
||||
double dDiamOrig = 1.2 * DistXY( aInfo[0].IciA->ptI, aInfo[1].IciA->ptI) ;
|
||||
Vector3d vtTg0 ; Point3d ptP0 ; crvCompo.GetPointTang( aInfo[0].IciB->dU, ICurve::FROM_MINUS, ptP0, vtTg0) ;
|
||||
Vector3d vtTg1 ; Point3d ptP1 ; crvCompo.GetPointTang( aInfo[1].IciB->dU, ICurve::FROM_MINUS, ptP1, vtTg1) ;
|
||||
Vector3d vtDirOrig = Media( vtTg0, -vtTg1) ; vtDirOrig.Normalize() ;
|
||||
|
||||
// movimento lungo un ramo
|
||||
Point3d ptStart = ptOrig ;
|
||||
double dDiam = dDiamOrig ;
|
||||
Vector3d vtDir = vtDirOrig ;
|
||||
int i = 0 ;
|
||||
|
||||
while ( i < 1000) {
|
||||
PNTVECTOR vPnt ;
|
||||
DBLVECTOR vDiam ;
|
||||
if ( ! ProcessCircleCurve( ptStart, dDiam, crvCompo, vPnt, vDiam))
|
||||
return false ;
|
||||
if ( vPnt.empty())
|
||||
break ;
|
||||
int nInd = -1 ;
|
||||
double dCosMax = -0.5 ;
|
||||
for ( int j = 0 ; j < int( vPnt.size()) ; ++ j) {
|
||||
Vector3d vtNewDir = vPnt[j] - ptStart ;
|
||||
if ( vtNewDir.Normalize()) {
|
||||
double dCosA = vtDir * vtNewDir ;
|
||||
if ( dCosA > dCosMax) {
|
||||
nInd = j ;
|
||||
dCosMax = dCosA ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nInd < 0)
|
||||
break ;
|
||||
vtDir = vPnt[nInd] - ptStart ;
|
||||
vtDir.Normalize() ;
|
||||
ptStart = vPnt[nInd] ;
|
||||
dDiam = 1.2 * vDiam[nInd] ;
|
||||
PL.AddUPoint( 0, GetToGlob( ptStart, frLoc)) ;
|
||||
++ i ;
|
||||
}
|
||||
|
||||
// movimento lungo l'altro ramo
|
||||
ptStart = ptOrig ;
|
||||
dDiam = dDiamOrig ;
|
||||
vtDir = -vtDirOrig ;
|
||||
i = 0 ;
|
||||
while ( i < 1000) {
|
||||
PNTVECTOR vPnt ;
|
||||
DBLVECTOR vDiam ;
|
||||
if ( ! ProcessCircleCurve( ptStart, dDiam, crvCompo, vPnt, vDiam))
|
||||
return false ;
|
||||
if ( vPnt.empty())
|
||||
break ;
|
||||
int nInd = -1 ;
|
||||
double dCosMax = -0.5 ;
|
||||
for ( int j = 0 ; j < int( vPnt.size()) ; ++ j) {
|
||||
Vector3d vtNewDir = vPnt[j] - ptStart ;
|
||||
if ( vtNewDir.Normalize()) {
|
||||
double dCosA = vtDir * vtNewDir ;
|
||||
if ( dCosA > dCosMax) {
|
||||
nInd = j ;
|
||||
dCosMax = dCosA ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nInd < 0)
|
||||
break ;
|
||||
vtDir = vPnt[nInd] - ptStart ;
|
||||
vtDir.Normalize() ;
|
||||
ptStart = vPnt[nInd] ;
|
||||
dDiam = 1.2 * vDiam[nInd] ;
|
||||
PL.AddUPoint( 0, GetToGlob( ptStart, frLoc), false) ;
|
||||
++ i ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
#include "/EgtDev/Include/EGkGdbConst.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtStringConverter.h"
|
||||
#include "/EgtDev/Extern/Zlib/Include/zlib.h"
|
||||
#include "/EgtDev/Extern/zlib/Include/zlib.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
+64
-15
@@ -17,6 +17,7 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
@@ -68,6 +69,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
{
|
||||
// pulisco tutto
|
||||
Reset() ;
|
||||
// verifico che la curva esista
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// verifico se la curva è un segmento di retta
|
||||
bool bIsLine = false ;
|
||||
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
|
||||
@@ -79,9 +83,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
|
||||
bIsLine = true ;
|
||||
}
|
||||
// verifico che la curva esista e sia piana
|
||||
// verifico che la curva sia piana
|
||||
Plane3d plPlane ;
|
||||
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL))
|
||||
if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
// recupero o assegno estrusione
|
||||
Vector3d vtExtr ;
|
||||
@@ -156,6 +160,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// verifico se curva chiusa e non forzata aperta
|
||||
bool bClosed = ccCopy.IsClosed() && ( nType & ICurve::OFF_FORCE_OPEN) == 0 ;
|
||||
|
||||
// elimino eventuali piccole Z
|
||||
RemoveCurveSmallZs( &ccCopy, 10 * EPS_SMALL) ;
|
||||
|
||||
// unisco parti allineate (tranne gli estremi)
|
||||
ccCopy.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
|
||||
|
||||
@@ -270,6 +277,17 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
}
|
||||
}
|
||||
|
||||
// aggiorno lunghezza segmenti di retta (possono essere stati allungati)
|
||||
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) {
|
||||
const ICurve* pCrv = *iIter ;
|
||||
if ( pCrv->GetType() == CRV_LINE) {
|
||||
double dLen ; pCrv->GetLength( dLen) ;
|
||||
int nInd = abs( pCrv->GetTempProp()) - 1 ;
|
||||
if ( nInd >= 0 && nInd < int( vLens.size()))
|
||||
vLens[nInd] = dLen ;
|
||||
}
|
||||
}
|
||||
|
||||
// secondo passo : eliminazione archi invertiti e rette impossibili
|
||||
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) {
|
||||
ICurve* pCrv = *iIter ;
|
||||
@@ -277,6 +295,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( pCrv->GetTempProp() < 0 ||
|
||||
( pCrv->GetType() == CRV_ARC && GetBasicCurveArc(pCrv)->GetRadius() < EPS_SMALL)) {
|
||||
delete pCrv ;
|
||||
pCrv = nullptr ;
|
||||
iIter = m_CrvLst.erase( iIter) ;
|
||||
continue ;
|
||||
}
|
||||
@@ -331,13 +350,17 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( ( nRes & 1) != 0) {
|
||||
auto iErase = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ;
|
||||
delete pPrev ;
|
||||
pPrev = nullptr ;
|
||||
m_CrvLst.erase( iErase) ;
|
||||
if ( m_CrvLst.empty())
|
||||
break ;
|
||||
auto iPrev = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ;
|
||||
pPrev = *iPrev ;
|
||||
}
|
||||
// corrente da cancellare
|
||||
if ( ( nRes & 2) != 0) {
|
||||
delete pCrv ;
|
||||
pCrv = nullptr ;
|
||||
iIter = m_CrvLst.erase( iIter) ;
|
||||
}
|
||||
// se eseguita una cancellazione, non devo incrementare
|
||||
@@ -358,6 +381,13 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( ! m_CrvLst.empty())
|
||||
m_CrvLst.front()->GetStartPoint( ptPrec) ;
|
||||
for ( auto& pCrv : m_CrvLst) {
|
||||
// se curva troppo piccola la salto
|
||||
double dCrvLen ;
|
||||
if ( ! pCrv->GetLength( dCrvLen)) {
|
||||
delete( pCrv) ;
|
||||
pCrv = nullptr ;
|
||||
continue ;
|
||||
}
|
||||
// se punto iniziale diverso da precedente, inserisco segmento di collegamento
|
||||
Point3d ptStart ;
|
||||
pCrv->GetStartPoint( ptStart) ;
|
||||
@@ -438,7 +468,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
dLenPrev = vLen[i] ;
|
||||
}
|
||||
// se fatta almeno una suddivisione, trimmo l'ultima parte
|
||||
if ( dUPrev > EPS_PARAM) {}
|
||||
if ( dUPrev > EPS_PARAM)
|
||||
pCompo1->TrimStartAtParam( dUPrev) ;
|
||||
|
||||
// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
|
||||
@@ -578,16 +608,18 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
pCrvCo2->GetEndPoint( ptEnd2) ;
|
||||
// verifiche di concatenamento
|
||||
if ( AreSamePointEpsilon( ptEnd, ptStart2, 10 * EPS_SMALL)) {
|
||||
pCrvCo->AddCurve( pCrvCo2, true, 10 * EPS_SMALL) ;
|
||||
m_CrvLst.erase( iIter2) ;
|
||||
ptEnd = ptEnd2 ;
|
||||
iIter2 = next( iIter) ;
|
||||
if ( pCrvCo->AddCurve( pCrvCo2, true, 10 * EPS_SMALL)) {
|
||||
m_CrvLst.erase( iIter2) ;
|
||||
ptEnd = ptEnd2 ;
|
||||
iIter2 = next( iIter) ;
|
||||
}
|
||||
}
|
||||
else if ( AreSamePointEpsilon( ptEnd2, ptStart, 10 * EPS_SMALL)) {
|
||||
pCrvCo->AddCurve( pCrvCo2, false, 10 * EPS_SMALL) ;
|
||||
m_CrvLst.erase( iIter2) ;
|
||||
ptStart = ptStart2 ;
|
||||
iIter2 = next( iIter) ;
|
||||
if ( pCrvCo->AddCurve( pCrvCo2, false, 10 * EPS_SMALL)) {
|
||||
m_CrvLst.erase( iIter2) ;
|
||||
ptStart = ptStart2 ;
|
||||
iIter2 = next( iIter) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
++ iIter2 ;
|
||||
@@ -661,6 +693,17 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
|
||||
}
|
||||
|
||||
// elimino eventuali curve non uniche molto corte e aperte
|
||||
while ( ( m_CrvLst.size() > 1)) {
|
||||
ICurve* pCrv = m_CrvLst.back() ;
|
||||
if ( ! pCrv->IsClosed() && pCrv->GetTempProp() < 1000 * 50 * EPS_SMALL) {
|
||||
delete( pCrv) ;
|
||||
m_CrvLst.pop_back() ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -828,11 +871,14 @@ VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
return true ;
|
||||
}
|
||||
// sono in tolleranza, ma devo ricongiungere gli estremi
|
||||
Point3d ptS1, ptE2 ;
|
||||
if ( ! pCrv1->GetStartPoint( ptS1) || ! pCrv2->GetEndPoint( ptE2))
|
||||
return false ;
|
||||
nRes = 0 ;
|
||||
Point3d ptMid = 0.5 * ( ptP1 + ptP2) ;
|
||||
if ( ! pCrv1->ModifyEnd( ptMid))
|
||||
if ( AreSamePointApprox( ptS1, ptMid) || ! pCrv1->ModifyEnd( ptMid))
|
||||
nRes += 1 ;
|
||||
if ( ! pCrv2->ModifyStart( ptMid))
|
||||
if ( AreSamePointApprox( ptMid, ptE2) || ! pCrv2->ModifyStart( ptMid))
|
||||
nRes += 2 ;
|
||||
return true ;
|
||||
}
|
||||
@@ -859,11 +905,14 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
! intCC.GetIntersPointNearTo( 1, ptMid, ptNew2))
|
||||
return false ;
|
||||
// modifico le due curve sul punto medio di intersezione
|
||||
Point3d ptS1, ptE2 ;
|
||||
if ( ! pCrv1->GetStartPoint( ptS1) || ! pCrv2->GetEndPoint( ptE2))
|
||||
return false ;
|
||||
nRes = 0 ;
|
||||
Point3d ptNew = 0.5 * ( ptNew1 + ptNew2) ;
|
||||
if ( ! pCrv1->ModifyEnd( ptNew))
|
||||
if ( AreSamePointApprox( ptS1, ptNew) || ! pCrv1->ModifyEnd( ptNew))
|
||||
nRes += 1 ;
|
||||
if ( ! pCrv2->ModifyStart( ptNew))
|
||||
if ( AreSamePointApprox( ptNew, ptE2) || ! pCrv2->ModifyStart( ptNew))
|
||||
nRes += 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+136
-11
@@ -515,8 +515,11 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
|
||||
// cerco le componenti principali (tramite PCA)
|
||||
Point3d ptP1, ptP2 ;
|
||||
PointsPCA ptsPCA ;
|
||||
for ( bool bFound = GetFirstLine( ptP1, ptP2) ; bFound ; bFound = GetNextLine( ptP1, ptP2))
|
||||
ptsPCA.AddPoint( Media( ptP1, ptP2), Dist( ptP1, ptP2)) ;
|
||||
for ( bool bFound = GetFirstLine( ptP1, ptP2) ; bFound ; bFound = GetNextLine( ptP1, ptP2)) {
|
||||
double dLen = Dist( ptP1, ptP2) ;
|
||||
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.25), dLen / 2) ;
|
||||
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.75), dLen / 2) ;
|
||||
}
|
||||
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
|
||||
nRank = ptsPCA.GetRank() ;
|
||||
// se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti
|
||||
@@ -599,8 +602,10 @@ PolyLine::IsClosedAndFlat( Plane3d& plPlane, double& dArea, double dToler) const
|
||||
PolygonPlane PolyPlane ;
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
|
||||
PolyPlane.AddPoint( ptP) ;
|
||||
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea))
|
||||
return false ;
|
||||
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea)) {
|
||||
dArea = 0 ;
|
||||
return IsFlat( plPlane, dToler) ;
|
||||
}
|
||||
// Test each vertex to see if it is farther from plane than allowed max distance
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
|
||||
double dDist = ( ( ptP - ORIG) * plPlane.GetVersN()) - plPlane.GetDist() ;
|
||||
@@ -1301,21 +1306,34 @@ PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dDist)
|
||||
{
|
||||
double dDummy ;
|
||||
return DistPointPolyLine( ptP, plPoly, dDist, dDummy) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dDist, double& dMinDistPar)
|
||||
{
|
||||
// La polilinea deve contenere almeno due punti
|
||||
if ( plPoly.GetPointNbr() < 2)
|
||||
return false ;
|
||||
// Ciclo sui punti della polilinea
|
||||
dDist = INFINITO ;
|
||||
int nSeg = -1 ;
|
||||
Point3d ptStart, ptEnd ;
|
||||
plPoly.GetFirstPoint( ptStart) ;
|
||||
while ( plPoly.GetNextPoint( ptEnd)) {
|
||||
++ nSeg ;
|
||||
// distanza del punto dal segmento della polilinea
|
||||
DistPointLine PointLineDistCalc( ptP, ptStart, ptEnd) ;
|
||||
double dPlDist ;
|
||||
PointLineDistCalc.GetDist( dPlDist) ;
|
||||
if ( dPlDist < dDist)
|
||||
if ( dPlDist < dDist) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += nSeg ;
|
||||
}
|
||||
// assegno nuovo inizio
|
||||
ptStart = ptEnd ;
|
||||
}
|
||||
@@ -1331,9 +1349,6 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
double dArea ;
|
||||
if ( ! plPoly.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
// Impongo l'orientamento CCW
|
||||
if ( dArea < 0)
|
||||
plPlane.Invert() ;
|
||||
// Il punto deve giacere nel piano della polilinea
|
||||
if ( ! PointInPlaneEpsilon( ptP, plPlane, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
@@ -1367,7 +1382,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
if ( prev( itMinDistEnd) != List.begin())
|
||||
vtPrevTg = prev( itMinDistEnd)->first - prev( itMinDistEnd, 2)->first ;
|
||||
else
|
||||
vtPrevTg = prev( itMinDistEnd)->first - prev( List.rbegin())->first ;
|
||||
vtPrevTg = prev( itMinDistEnd)->first - next( List.rbegin())->first ;
|
||||
vtPrevTg.Normalize() ;
|
||||
// tangente media
|
||||
vtTang = vtPrevTg + vtCurrTg ;
|
||||
@@ -1410,7 +1425,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol
|
||||
// Ciclo sui punti della polilinea
|
||||
int nSeg = -1 ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
double dMinPar = -1 ;
|
||||
dPar = -1 ;
|
||||
Point3d ptStart, ptEnd ;
|
||||
plPoly.GetFirstPoint( ptStart) ;
|
||||
while ( plPoly.GetNextPoint( ptEnd)) {
|
||||
@@ -1423,7 +1438,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol
|
||||
dMinSqDist = dSqDist ;
|
||||
double dSegPar ;
|
||||
dDistCalc.GetParamAtMinDistPoint( dSegPar) ;
|
||||
dMinPar = nSeg + dSegPar ;
|
||||
dPar = nSeg + dSegPar ;
|
||||
}
|
||||
// assegno nuovo inizio
|
||||
ptStart = ptEnd ;
|
||||
@@ -1514,3 +1529,113 @@ SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler,
|
||||
plPoly2.AddUPoint( 0, ptP, false) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIVECTOR& vPnt1, PNTIVECTOR& vPnt2, bool& bCommonInternalPoints)
|
||||
{
|
||||
// controllo che le polyline abbiano almeno un punto
|
||||
int nPnt1 = PL1.GetPointNbr() ;
|
||||
int nPnt2 = PL2.GetPointNbr() ;
|
||||
if ( nPnt1 == 0 || nPnt2 == 0)
|
||||
return false ;
|
||||
|
||||
bCommonInternalPoints = false ; // indica la presenza di punti interni in comune tra le due polylines
|
||||
|
||||
vPnt1.reserve( PL1.GetPointNbr()) ;
|
||||
Point3d ptP1 ;
|
||||
bool bF1 = PL1.GetFirstPoint( ptP1) ;
|
||||
while ( bF1) {
|
||||
vPnt1.emplace_back( ptP1, -1) ;
|
||||
bF1 = PL1.GetNextPoint( ptP1) ;
|
||||
}
|
||||
int nTotP1 = int( vPnt1.size()) ;
|
||||
|
||||
vPnt2.reserve( PL2.GetPointNbr()) ;
|
||||
Point3d ptP2 ;
|
||||
bool bF2 = PL2.GetFirstPoint( ptP2) ;
|
||||
while ( bF2) {
|
||||
vPnt2.emplace_back( ptP2, -1) ;
|
||||
bF2 = PL2.GetNextPoint( ptP2) ;
|
||||
}
|
||||
int nTotP2 = int( vPnt2.size()) ;
|
||||
|
||||
// calcoli per prima curva
|
||||
int nLastJ = 0 ;
|
||||
vPnt1[0].second = 0 ;
|
||||
|
||||
double dFirstDist, dFirstParMinDist ;
|
||||
DistPointPolyLine( vPnt1[0].first, PL2, dFirstDist, dFirstParMinDist) ;
|
||||
int nFirstMinJ = ( int)( dFirstParMinDist + 0.5) ;
|
||||
|
||||
for ( int i = 1 ; i < nTotP1 ; ++ i) {
|
||||
|
||||
double dDist = INFINITO ;
|
||||
double dMinDistPar = nLastJ ;
|
||||
for ( int j = max( nLastJ, 1) ; j < nTotP2 ; ++ j) {
|
||||
// distanza del punto dal segmento della polilinea
|
||||
DistPointLine PointLineDistCalc( vPnt1[i].first, vPnt2[j-1].first, vPnt2[j].first) ;
|
||||
double dPlDist ;
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += j - 1 ;
|
||||
}
|
||||
}
|
||||
int nMinJ = ( int)( dMinDistPar + 0.5) ;
|
||||
|
||||
// eventuale correzione per i primi punti ( da forzare nel vertice 0)
|
||||
if ( nLastJ == 0 && nFirstMinJ > 0.5 * nTotP2 && nMinJ >= nFirstMinJ)
|
||||
nMinJ = 0 ;
|
||||
|
||||
if ( nMinJ < nLastJ)
|
||||
nMinJ = nLastJ ;
|
||||
|
||||
// verifica se è un punto interno in comune con l'altra polyline
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt1[i].second = nMinJ ;
|
||||
nLastJ = nMinJ ;
|
||||
}
|
||||
|
||||
// calcoli per seconda curva
|
||||
int nLastI = 0 ;
|
||||
vPnt2[0].second = 0 ;
|
||||
|
||||
DistPointPolyLine( vPnt2[0].first, PL1, dFirstDist, dFirstParMinDist) ;
|
||||
int nFirstMinI = ( int)( dFirstParMinDist + 0.5) ;
|
||||
|
||||
for ( int j = 1 ; j < nTotP2 ; ++ j) {
|
||||
|
||||
double dDist = INFINITO ;
|
||||
double dMinDistPar = nLastI ;
|
||||
for ( int i = max( nLastI, 1) ; i < nTotP1 ; ++ i) {
|
||||
// distanza del punto dal segmento della polilinea
|
||||
DistPointLine PointLineDistCalc( vPnt2[j].first, vPnt1[i-1].first, vPnt1[i].first) ;
|
||||
double dPlDist ;
|
||||
PointLineDistCalc.GetDist( dPlDist) ;
|
||||
if ( dPlDist < dDist) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += i - 1 ;
|
||||
}
|
||||
}
|
||||
int nMinI = ( int)( dMinDistPar + 0.5) ;
|
||||
|
||||
// eventuale correzione per primi punti
|
||||
if ( nLastI == 0 && nFirstMinI > 0.5 * nTotP1 && nMinI >= nFirstMinI)
|
||||
nMinI = 0 ;
|
||||
|
||||
if ( nMinI < nLastI)
|
||||
nMinI = nLastI ;
|
||||
|
||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt2[j].second = nMinI ;
|
||||
nLastI = nMinI ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+2
-2
@@ -17,7 +17,7 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkPolygon3d.h"
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -187,7 +187,7 @@ Polygon3d::Trim( const Plane3d& plPlane, bool bInVsOut, bool bOnEq, bool bOnCt)
|
||||
DBLVECTOR vDist ;
|
||||
vDist.reserve( m_vVert.capacity()) ;
|
||||
for ( auto& ptP : m_vVert) {
|
||||
double dDist = ( ptP - ORIG) * plPlane.GetVersN() - plPlane.GetDist() ;
|
||||
double dDist = DistPointPlane( ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
++ nNbrOn ;
|
||||
else if ( dDist < 0)
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2017-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RemoveCurveDefects.cpp Data : 28.11.22 Versione : 2.4k6
|
||||
// Contenuto : Implementazione rimozione spikes di curva.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 02.10.17 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RemoveCurveSpikes( ICurveComposite* pCurve, double dLinTol)
|
||||
{
|
||||
// verifico validità curva
|
||||
if ( pCurve == nullptr)
|
||||
return false ;
|
||||
// verifico e sistemo tolleranza lineare
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
// recupero il numero di curve semplici componenti la composta
|
||||
int nCrvCount = pCurve->GetCurveCount() ;
|
||||
if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed()))
|
||||
return true ;
|
||||
// ciclo sulle curve elementari della composita
|
||||
int nStart = pCurve->IsClosed() ? 0 : 1 ;
|
||||
for ( int i = nStart ; i < nCrvCount ; ++ i) {
|
||||
// recupero due curve consecutive
|
||||
const ICurve* pPrevCrv = pCurve->GetCurve( ( i > 0 ? i - 1 : nCrvCount - 1)) ;
|
||||
const ICurve* pNextCrv = pCurve->GetCurve( i) ;
|
||||
// se sono entrambe rette
|
||||
if ( pPrevCrv->GetType() == CRV_LINE && pNextCrv->GetType() == CRV_LINE) {
|
||||
// recupero i punti estremi
|
||||
Point3d ptStart ; pPrevCrv->GetStartPoint( ptStart) ;
|
||||
Point3d ptMid ; pPrevCrv->GetEndPoint( ptMid) ;
|
||||
Point3d ptEnd ; pNextCrv->GetEndPoint( ptEnd) ;
|
||||
// recupero le direzioni negli estremi
|
||||
Vector3d vtPrev ; pPrevCrv->GetStartDir( vtPrev) ;
|
||||
Vector3d vtNext ; pNextCrv->GetStartDir( vtNext) ;
|
||||
// verifico se spike
|
||||
double dPrevDist, dNextDist ;
|
||||
if ( vtPrev * vtNext < cos( 175 * DEGTORAD) &&
|
||||
(( DistPointLine( ptStart, ptMid, ptEnd).GetDist( dPrevDist) && dPrevDist < dLinTol) ||
|
||||
( DistPointLine( ptEnd, ptStart, ptMid).GetDist( dNextDist) && dNextDist < dLinTol))) {
|
||||
// se spike ha base abbastanza larga, basta togliere uno dei due lati
|
||||
if ( SqDist( ptStart, ptEnd) > SQ_EPS_SMALL) {
|
||||
pCurve->RemoveJoint( i) ;
|
||||
-- nCrvCount ;
|
||||
-- i ;
|
||||
}
|
||||
// altrimenti bisogna togliere entrambi
|
||||
else {
|
||||
pCurve->RemoveJoint( i - 1) ;
|
||||
pCurve->RemoveJoint( i) ;
|
||||
nCrvCount -= 2 ;
|
||||
i = max( i - 2, nStart - 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// !!! Aggiungere la gestione degli altri tipi di curve !!!
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RemoveCurveSmallZs( ICurveComposite* pCurve, double dLinTol)
|
||||
{
|
||||
// verifico validità curva
|
||||
if ( pCurve == nullptr)
|
||||
return false ;
|
||||
// verifico e sistemo tolleranza lineare
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
// recupero il numero di curve semplici componenti la composta
|
||||
int nCrvCount = pCurve->GetCurveCount() ;
|
||||
if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed()))
|
||||
return true ;
|
||||
// ciclo sulle curve elementari della composita
|
||||
int nStart = pCurve->IsClosed() ? 0 : 1 ;
|
||||
int nEnd = pCurve->IsClosed() ? nCrvCount : nCrvCount - 1 ;
|
||||
for ( int i = nStart ; i < nEnd ; ++ i) {
|
||||
// recupero tre curve consecutive
|
||||
const ICurve* pPrevCrv = pCurve->GetCurve( ( i > 0 ? i - 1 : nCrvCount - 1)) ;
|
||||
const ICurve* pCurrCrv = pCurve->GetCurve( i) ;
|
||||
const ICurve* pNextCrv = pCurve->GetCurve( ( i < nCrvCount - 1 ? i + 1 : 0)) ;
|
||||
// se la curva corrente è una retta
|
||||
if ( pCurrCrv->GetType() == CRV_LINE) {
|
||||
// recupero tre punti notevoli della curva
|
||||
Point3d ptStart ; pCurrCrv->GetStartPoint( ptStart) ;
|
||||
Point3d ptMid ; pCurrCrv->GetMidPoint( ptMid) ;
|
||||
Point3d ptEnd ; pCurrCrv->GetEndPoint( ptEnd) ;
|
||||
// recupero le direzioni negli estremi
|
||||
Vector3d vtPrev ; pPrevCrv->GetEndDir( vtPrev) ;
|
||||
Vector3d vtNext ; pNextCrv->GetStartDir( vtNext) ;
|
||||
// verifico se Small Z
|
||||
double dDistS, dDistM1, dDistM2, dDistE ;
|
||||
if ( vtPrev * vtNext > cos( 30 * DEGTORAD) &&
|
||||
(( DistPointCurve( ptStart, *pNextCrv).GetDist( dDistS) && dDistS < dLinTol) &&
|
||||
( DistPointCurve( ptMid, *pNextCrv).GetDist( dDistM1) && dDistM1 < dLinTol) &&
|
||||
( DistPointCurve( ptMid, *pPrevCrv).GetDist( dDistM2) && dDistM2 < dLinTol) &&
|
||||
( DistPointCurve( ptEnd, *pPrevCrv).GetDist( dDistE) && dDistE < dLinTol))) {
|
||||
// rimuovo il segmento
|
||||
if ( pCurve->RemoveJoint( i)) {
|
||||
-- nCrvCount ;
|
||||
-- nEnd ;
|
||||
-- i ;
|
||||
// porto il nuovo estremo sul punto medio
|
||||
pCurve->ModifyJoint( i + 1, ptMid) ;
|
||||
}
|
||||
// altrimenti devo rimuovere anche il successivo
|
||||
else if ( pCurve->RemoveJoint( i + 1) && pCurve->RemoveJoint( i)) {
|
||||
nCrvCount -= 2 ;
|
||||
nEnd -= 2 ;
|
||||
-- i ;
|
||||
// porto il nuovo estremo sul punto medio
|
||||
pCurve->ModifyJoint( i + 1, ptMid) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2017-2017
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RemoveCurveSpikes.h Data : 02.10.17 Versione : 1.8j1
|
||||
// Contenuto : Dichiarazione funzione rimozione spikes curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 02.10.17 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool RemoveCurveSpikes( ICurveComposite* pCurve) ;
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2017-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RemoveCurveDefects.h Data : 13.11.22 Versione : 2.4k2
|
||||
// Contenuto : Dichiarazione funzioni rimozione difetti curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 02.10.17 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool RemoveCurveSpikes( ICurveComposite* pCurve, double dLinTol = EPS_SMALL) ;
|
||||
bool RemoveCurveSmallZs( ICurveComposite* pCurve, double dLinTol = EPS_SMALL) ;
|
||||
@@ -1,74 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2017-2017
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RemoveCurveSpikes.cpp Data : 02.10.17 Versione : 1.8j1
|
||||
// Contenuto : Implementazione rimozione spikes di curva.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 02.10.17 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveSpikes.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RemoveCurveSpikes( ICurveComposite* pCurve)
|
||||
{
|
||||
// verifico validità curva
|
||||
if ( pCurve == nullptr)
|
||||
return false ;
|
||||
// recupero il numero di curve semplici componenti la composta
|
||||
int nCrvCount = pCurve->GetCurveCount() ;
|
||||
if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed()))
|
||||
return true ;
|
||||
// ciclo sulle curve elementari della composita
|
||||
int nStart = pCurve->IsClosed() ? 0 : 1 ;
|
||||
for ( int i = nStart ; i < nCrvCount ; ++ i) {
|
||||
// recupero due curve consecutive
|
||||
const ICurve* pPrevCrv = pCurve->GetCurve( ( i > 0 ? i - 1 : nCrvCount - 1)) ;
|
||||
const ICurve* pNextCrv = pCurve->GetCurve( i) ;
|
||||
// se sono entrambe rette
|
||||
if ( pPrevCrv->GetType() == CRV_LINE && pNextCrv->GetType() == CRV_LINE) {
|
||||
// recupero i punti estremi
|
||||
Point3d ptStart ; pPrevCrv->GetStartPoint( ptStart) ;
|
||||
Point3d ptMid ; pPrevCrv->GetEndPoint( ptMid) ;
|
||||
Point3d ptEnd ; pNextCrv->GetEndPoint( ptEnd) ;
|
||||
// recupero le direzioni negli estremi
|
||||
Vector3d vtPrev ; pPrevCrv->GetStartDir( vtPrev) ;
|
||||
Vector3d vtNext ; pNextCrv->GetStartDir( vtNext) ;
|
||||
// verifico se spike
|
||||
double dPrevDist, dNextDist ;
|
||||
if ( vtPrev * vtNext < cos( 175 * DEGTORAD) &&
|
||||
(( DistPointLine( ptStart, ptMid, ptEnd).GetDist( dPrevDist) && dPrevDist < EPS_SMALL) ||
|
||||
( DistPointLine( ptEnd, ptStart, ptMid).GetDist( dNextDist) && dNextDist < EPS_SMALL))) {
|
||||
// se spike ha base abbastanza larga, basta togliere uno dei due lati
|
||||
if ( SqDist( ptStart, ptEnd) > SQ_EPS_SMALL) {
|
||||
pCurve->RemoveJoint( i) ;
|
||||
-- nCrvCount ;
|
||||
-- i ;
|
||||
}
|
||||
// altrimenti bisogna togliere entrambi
|
||||
else {
|
||||
pCurve->RemoveJoint( i - 1) ;
|
||||
pCurve->RemoveJoint( i) ;
|
||||
nCrvCount -= 2 ;
|
||||
i = max( i - 2, nStart - 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// !!! Aggiungere la gestione degli altri tipi di curve !!!
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+65
-23
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2016
|
||||
// EgalTech 2015-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : StmFromCurves.cpp Data : 11.08.16 Versione : 1.6t2
|
||||
// File : StmFromCurves.cpp Data : 08.12.22 Versione : 2.4l2
|
||||
// Contenuto : Implementazione di funzioni per creazione di superfici Stm
|
||||
// a partire da curve, con diversi metodi.
|
||||
//
|
||||
@@ -19,9 +19,9 @@
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "AdjustLoops.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgkPolyLine.h"
|
||||
#include "/EgtDev/Include/EgkBiArcs.h"
|
||||
#include "/EgtDev/Include/EgkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkBiArcs.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
@@ -136,14 +136,33 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
pCompo1->GetEndPoint( ptEnd) ;
|
||||
pCompo1->GetEndDir( vtEnd) ;
|
||||
pCompo1->GetMidPoint( ptMid) ;
|
||||
if ( Dist( ptStart, ptEnd) <= 2 * dRadius && Dist( ptStart, ptMid) > 2 * dRadius && Dist( ptEnd, ptMid) > 2 * dRadius) {
|
||||
double dAngEnd ; vtEnd.ToSpherical( nullptr, nullptr, &dAngEnd) ;
|
||||
double dAngStart ; vtStart.ToSpherical( nullptr, nullptr, &dAngStart) ;
|
||||
PtrOwner<ICurve> pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ;
|
||||
if ( ! IsNull( pClose))
|
||||
pCompo1->AddCurve( Release( pClose)) ;
|
||||
else
|
||||
pCompo1->Close() ;
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, 2 * dRadius) && Dist( ptStart, ptMid) > 2 * dRadius && Dist( ptEnd, ptMid) > 2 * dRadius) {
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, max( 0.1 * dRadius, 10 * EPS_SMALL))) {
|
||||
Point3d ptNew = Media( ptStart, ptEnd) ;
|
||||
pCompo1->ModifyStart( ptNew) ;
|
||||
pCompo1->ModifyEnd( ptNew) ;
|
||||
}
|
||||
else {
|
||||
// piano della curva
|
||||
Frame3d frLoc ;
|
||||
if ( ! AreSameVectorApprox( vtExtr, Z_AX))
|
||||
frLoc.Set( ptStart, vtExtr) ;
|
||||
// costruisco il biarco nel piano della curva
|
||||
ptStart.ToLoc( frLoc) ;
|
||||
ptEnd.ToLoc( frLoc) ;
|
||||
Vector3d vtELoc( vtEnd) ; vtELoc.ToLoc( frLoc) ;
|
||||
Vector3d vtSLoc( vtStart) ; vtSLoc.ToLoc( frLoc) ;
|
||||
double dAngEnd ; vtELoc.ToSpherical( nullptr, nullptr, &dAngEnd) ;
|
||||
double dAngStart ; vtSLoc.ToSpherical( nullptr, nullptr, &dAngStart) ;
|
||||
PtrOwner<ICurve> pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ;
|
||||
// porto il biarco in globale
|
||||
pClose->ToGlob( frLoc) ;
|
||||
// aggiungo il biarco
|
||||
if ( ! IsNull( pClose))
|
||||
pCompo1->AddCurve( Release( pClose)) ;
|
||||
else
|
||||
pCompo1->Close() ;
|
||||
}
|
||||
}
|
||||
// tipo di offset
|
||||
int nOffsType = ( bSquareMids ? ICurve::OFF_EXTEND : ICurve::OFF_FILLET) ;
|
||||
@@ -162,15 +181,21 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType))
|
||||
return nullptr ;
|
||||
ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ;
|
||||
if ( pOffs1 != nullptr)
|
||||
while ( pOffs1 != nullptr) {
|
||||
SfrCntr.AddCurve( pOffs1) ;
|
||||
pOffs1 = OffsCrv1.GetLongerCurve() ;
|
||||
}
|
||||
|
||||
// offset della seconda curva a destra del raggio (è invertita rispetto alla precedente)
|
||||
OffsetCurve OffsCrv2 ;
|
||||
if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType))
|
||||
return nullptr ;
|
||||
ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ;
|
||||
if ( pOffs2 != nullptr)
|
||||
while ( pOffs2 != nullptr) {
|
||||
SfrCntr.AddCurve( pOffs2) ;
|
||||
pOffs2 = OffsCrv2.GetLongerCurve() ;
|
||||
}
|
||||
|
||||
// creo la regione
|
||||
return SfrCntr.GetSurf() ;
|
||||
}
|
||||
@@ -187,24 +212,42 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
PtrOwner<CurveComposite> pCompo2( pCompo1->Clone()) ;
|
||||
if ( IsNull( pCompo2) || ! pCompo2->Invert())
|
||||
return nullptr ;
|
||||
|
||||
// creo la regione
|
||||
SurfFlatRegionByContours SfrCntr( false, false) ;
|
||||
|
||||
// offset della prima curva a destra del raggio
|
||||
OffsetCurve OffsCrv1 ;
|
||||
if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType))
|
||||
return nullptr ;
|
||||
ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ;
|
||||
if ( pOffs1 != nullptr) {
|
||||
pCompo1->Clear() ;
|
||||
pCompo1->AddCurve( pOffs1) ;
|
||||
if ( pOffs1 == nullptr)
|
||||
return nullptr ;
|
||||
pCompo1->Clear() ;
|
||||
while ( pOffs1 != nullptr) {
|
||||
if ( pOffs1->IsClosed())
|
||||
SfrCntr.AddCurve( pOffs1) ;
|
||||
else
|
||||
pCompo1->AddCurve( pOffs1) ;
|
||||
pOffs1 = OffsCrv1.GetLongerCurve() ;
|
||||
}
|
||||
|
||||
// offset della seconda curva a destra del raggio
|
||||
OffsetCurve OffsCrv2 ;
|
||||
if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType))
|
||||
return nullptr ;
|
||||
ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ;
|
||||
if ( pOffs2 != nullptr) {
|
||||
pCompo2->Clear() ;
|
||||
pCompo2->AddCurve( pOffs2) ;
|
||||
if ( pOffs2 == nullptr)
|
||||
return nullptr ;
|
||||
pCompo2->Clear() ;
|
||||
while ( pOffs2 != nullptr) {
|
||||
if ( pOffs2->IsClosed())
|
||||
SfrCntr.AddCurve( pOffs2) ;
|
||||
else
|
||||
pCompo2->AddCurve( pOffs2) ;
|
||||
pOffs2 = OffsCrv2.GetLongerCurve() ;
|
||||
}
|
||||
|
||||
// se estremi squadrati
|
||||
if ( bSquareEnds) {
|
||||
// aggiungo alla prima curva una linea che la unisca alla seconda
|
||||
@@ -270,8 +313,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
if ( ! pCompo1->AddCurve( Release( pCompo2)))
|
||||
return nullptr ;
|
||||
}
|
||||
// creo la regione
|
||||
SurfFlatRegionByContours SfrCntr( false, false) ;
|
||||
|
||||
SfrCntr.AddCurve( Release( pCompo1)) ;
|
||||
return SfrCntr.GetSurf() ;
|
||||
}
|
||||
|
||||
+309
-2
@@ -17,7 +17,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "/EgtDev/Include/EgkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
@@ -321,6 +321,313 @@ GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vecto
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static ISurfTriMesh*
|
||||
GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, int nCapType, double dLinTol)
|
||||
{
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// curve di offset
|
||||
OffsetCurve OffsCrvR ;
|
||||
if ( ! OffsCrvR.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvR( OffsCrvR.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvR))
|
||||
return nullptr ;
|
||||
OffsetCurve OffsCrvL ;
|
||||
if ( ! OffsCrvL.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvL( OffsCrvL.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvL))
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvRb ;
|
||||
PtrOwner<ICurve> pCrvLb ;
|
||||
// costruisco le parti di superficie
|
||||
PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSrfTop))
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
|
||||
if ( IsNull( pSrfBot))
|
||||
return nullptr ;
|
||||
pSrfBot->Translate( -dDimV * vtNorm) ;
|
||||
pSrfBot->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ;
|
||||
if ( IsNull( pSrfRgt))
|
||||
return nullptr ;
|
||||
pSrfRgt->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvL, -dDimV * vtNorm, false, dLinTol)) ;
|
||||
if ( IsNull( pSrfLft))
|
||||
return nullptr ;
|
||||
// unisco le parti
|
||||
PtrOwner<ISurfTriMesh> pSTM( Release( pSrfTop)) ;
|
||||
pSTM->DoSewing( *pSrfRgt) ;
|
||||
pSTM->DoSewing( *pSrfLft) ;
|
||||
pSTM->DoSewing( *pSrfBot) ;
|
||||
// salvo tolleranza lineare usata e imposto angolo per smooth
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
pSTM->SetSmoothAngle( 20) ;
|
||||
// se guida aperta e tappi piatti
|
||||
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
Plane3d plEnds ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// aggiungo il cap sull'inizio
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
// se altrimenti guida aperta e tappi arrotondati
|
||||
if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
//POLYLINEVECTOR vPL ;
|
||||
//if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
// return nullptr ;
|
||||
//Plane3d plEnds ; double dArea ;
|
||||
//if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
//if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// step di rotazione per rispettare la tolleranza
|
||||
double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
|
||||
// aggiungo il cap sull'inizio
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
vtStart.Rotate( vtNorm, 0, 1) ;
|
||||
PolyLine PLStart ;
|
||||
PLStart.AddUPoint( 0, ptStart) ;
|
||||
PLStart.AddUPoint( 1, ptStart + dDimH / 2 * vtStart) ;
|
||||
PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dDimV * vtNorm) ;
|
||||
PLStart.AddUPoint( 3, ptStart - dDimV * vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtEnd ;
|
||||
pGuide->GetEndDir( vtEnd) ;
|
||||
vtEnd.Rotate( vtNorm, 0, -1) ;
|
||||
PolyLine PLEnd ;
|
||||
PLEnd.AddUPoint( 0, ptEnd) ;
|
||||
PLEnd.AddUPoint( 1, ptEnd + dDimH / 2 * vtEnd) ;
|
||||
PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dDimV * vtNorm) ;
|
||||
PLEnd.AddUPoint( 3, ptEnd - dDimV * vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
// elimino eventuali fessure
|
||||
//pSTM->Repair() ;
|
||||
}
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static ISurfTriMesh*
|
||||
GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol)
|
||||
{
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// assegno la normale del piano
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
// determino il punto centrale della sezione
|
||||
Point3d ptCen ;
|
||||
pGuide->GetStartPoint( ptCen) ;
|
||||
ptCen -= dDimV / 2 * vtNorm ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// curve di offset
|
||||
OffsetCurve OffsCrvR ;
|
||||
if ( ! OffsCrvR.Make( pGuide, dDimH / 2 - dBevelH, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvR( OffsCrvR.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvR))
|
||||
return nullptr ;
|
||||
OffsetCurve OffsCrvL ;
|
||||
if ( ! OffsCrvL.Make( pGuide, -dDimH / 2 + dBevelH, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvL( OffsCrvL.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvL))
|
||||
return nullptr ;
|
||||
OffsetCurve OffsCrvRb ;
|
||||
if ( ! OffsCrvRb.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvRb.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvRb( OffsCrvRb.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvRb))
|
||||
return nullptr ;
|
||||
pCrvRb->Translate( - dBevelV * vtNorm) ;
|
||||
OffsetCurve OffsCrvLb ;
|
||||
if ( ! OffsCrvLb.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvLb.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCrvLb( OffsCrvLb.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvLb))
|
||||
return nullptr ;
|
||||
pCrvLb->Translate( - dBevelV * vtNorm) ;
|
||||
// costruisco le parti di superficie
|
||||
PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSrfTop))
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
|
||||
if ( IsNull( pSrfBot))
|
||||
return nullptr ;
|
||||
pSrfBot->Translate( -dDimV * vtNorm) ;
|
||||
pSrfBot->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pSrfTopR( GetSurfTriMeshRuled( pCrvRb, pCrvR, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSrfTopR))
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pSrfBotR( pSrfTopR->Clone()) ;
|
||||
if ( IsNull( pSrfBotR))
|
||||
return nullptr ;
|
||||
pSrfBotR->Mirror( ptCen, vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSrfTopL( GetSurfTriMeshRuled( pCrvL, pCrvLb, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSrfTopL))
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pSrfBotL( pSrfTopL->Clone()) ;
|
||||
if ( IsNull( pSrfBotL))
|
||||
return nullptr ;
|
||||
pSrfBotL->Mirror( ptCen, vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvRb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
|
||||
if ( IsNull( pSrfRgt))
|
||||
return nullptr ;
|
||||
pSrfRgt->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvLb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
|
||||
if ( IsNull( pSrfLft))
|
||||
return nullptr ;
|
||||
// unisco le parti
|
||||
PtrOwner<ISurfTriMesh> pSTM( Release( pSrfTop)) ;
|
||||
pSTM->DoSewing( *pSrfTopR) ;
|
||||
pSTM->DoSewing( *pSrfTopL) ;
|
||||
pSTM->DoSewing( *pSrfRgt) ;
|
||||
pSTM->DoSewing( *pSrfLft) ;
|
||||
pSTM->DoSewing( *pSrfBotR) ;
|
||||
pSTM->DoSewing( *pSrfBotL) ;
|
||||
pSTM->DoSewing( *pSrfBot) ;
|
||||
// salvo tolleranza lineare usata e imposto angolo per smooth
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
pSTM->SetSmoothAngle( 20) ;
|
||||
// se guida aperta e tappi piatti
|
||||
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
Plane3d plEnds ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// aggiungo il cap sull'inizio
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
// se altrimenti guida aperta e tappi arrotondati
|
||||
if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
//POLYLINEVECTOR vPL ;
|
||||
//if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
// return nullptr ;
|
||||
//Plane3d plEnds ; double dArea ;
|
||||
//if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
//if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// step di rotazione per rispettare il tipo o la tolleranza
|
||||
double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ;
|
||||
// aggiungo il cap sull'inizio
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
vtStart.Rotate( vtNorm, 0, 1) ;
|
||||
PolyLine PLStart ;
|
||||
PLStart.AddUPoint( 0, ptStart) ;
|
||||
PLStart.AddUPoint( 1, ptStart + ( dDimH / 2 - dBevelH) * vtStart) ;
|
||||
PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dBevelV * vtNorm) ;
|
||||
PLStart.AddUPoint( 3, ptStart + dDimH / 2 * vtStart - ( dDimV - dBevelV) * vtNorm) ;
|
||||
PLStart.AddUPoint( 4, ptStart + ( dDimH / 2 - dBevelH) * vtStart - dDimV * vtNorm) ;
|
||||
PLStart.AddUPoint( 5, ptStart - dDimV * vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtEnd ;
|
||||
pGuide->GetEndDir( vtEnd) ;
|
||||
vtEnd.Rotate( vtNorm, 0, -1) ;
|
||||
PolyLine PLEnd ;
|
||||
PLEnd.AddUPoint( 0, ptEnd) ;
|
||||
PLEnd.AddUPoint( 1, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd) ;
|
||||
PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dBevelV * vtNorm) ;
|
||||
PLEnd.AddUPoint( 3, ptEnd + dDimH / 2 * vtEnd - ( dDimV - dBevelV) * vtNorm) ;
|
||||
PLEnd.AddUPoint( 4, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd - dDimV * vtNorm) ;
|
||||
PLEnd.AddUPoint( 5, ptEnd - dDimV * vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
// elimino eventuali fessure
|
||||
//pSTM->Repair() ;
|
||||
}
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pGuide == nullptr || dBevelH > 0.4 * dDimH || dBevelV > 0.4 * dDimV)
|
||||
return nullptr ;
|
||||
// determino se sezione squadrata o con smusso
|
||||
bool bSharp = ( dBevelH < 100 * EPS_SMALL || dBevelV < 100 * EPS_SMALL) ;
|
||||
// eseguo
|
||||
if ( bSharp)
|
||||
return GetSurfTriMeshSharpRectSwept( dDimH, dDimV, pGuide, nCapType, dLinTol) ;
|
||||
else
|
||||
return GetSurfTriMeshBeveledRectSwept( dDimH, dDimV, dBevelH, dBevelV, pGuide, nCapType, dLinTol) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
|
||||
@@ -364,7 +671,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
while ( bPoint) {
|
||||
// nuova curva
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() > 1)
|
||||
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
|
||||
if ( IsNull( pCurrCrv))
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "/EgtDEv/Include/EgkStringUtils3d.h"
|
||||
#include "/EgtDEv/Include/EGkStringUtils3d.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
+6
-4
@@ -1378,15 +1378,16 @@ SurfBezier::GetAuxSurf( void) const
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK) {
|
||||
m_pSTM = nullptr ;
|
||||
ResetAuxSurf() ;
|
||||
return nullptr ;
|
||||
}
|
||||
// se già calcolata, la restituisco
|
||||
if ( m_pSTM != nullptr)
|
||||
if ( m_pSTM != nullptr)
|
||||
return m_pSTM ;
|
||||
// costruttore della superficie
|
||||
StmFromTriangleSoup stmSoup ;
|
||||
stmSoup.Start() ;
|
||||
if ( ! stmSoup.Start())
|
||||
return nullptr ;
|
||||
// definisco il numero degli step in U e in V
|
||||
double dMaxLenU = 0 ;
|
||||
for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j)
|
||||
@@ -1440,7 +1441,8 @@ SurfBezier::GetAuxSurf( void) const
|
||||
bSingle1 = bSingle2 ;
|
||||
}
|
||||
// la completo
|
||||
stmSoup.End() ;
|
||||
if ( ! stmSoup.End())
|
||||
return nullptr ;
|
||||
// la salvo
|
||||
m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ;
|
||||
return m_pSTM ;
|
||||
|
||||
+250
-1
@@ -19,6 +19,7 @@
|
||||
#include "NgeReader.h"
|
||||
#include "CurveAux.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "CurveLine.h"
|
||||
#include "AdjustLoops.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
@@ -576,7 +577,7 @@ SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
// è il bounding box dei loop esterni
|
||||
for ( auto i : m_vExtInd) {
|
||||
BBox3d b3Tmp ;
|
||||
if ( m_vpLoop[i]->GetBBox( m_frF, b3Loc, nFlag))
|
||||
if ( m_vpLoop[i]->GetBBox( m_frF, b3Tmp, nFlag))
|
||||
b3Loc.Add( b3Tmp) ;
|
||||
}
|
||||
return ( ! b3Loc.IsEmpty()) ;
|
||||
@@ -1354,3 +1355,251 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
return REGC_INTERS ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const
|
||||
{
|
||||
// ingombro della regione
|
||||
BBox3d b3Pocket ;
|
||||
GetLocalBBox( b3Pocket) ;
|
||||
Point3d ptMin ; double dDimX, dDimY, dDimZ ;
|
||||
b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ;
|
||||
|
||||
// lunghezza dei contorni
|
||||
DBLVECTOR vLen( m_vpLoop.size()) ;
|
||||
for ( size_t i = 0 ; i < vLen.size() ; i++)
|
||||
m_vpLoop[i]->GetLength( vLen[i]) ;
|
||||
|
||||
// passi in Y
|
||||
double dYStep = dStep ;
|
||||
int nYStep = static_cast<int>( floor( dDimY / dStep)) ;
|
||||
int nRef = 0 ;
|
||||
if ( bStepCorrection) {
|
||||
// se permesso, lo modifico per coprire uniformemente la regione
|
||||
nYStep = static_cast<int>( ceil( ( dDimY - 30 * EPS_SMALL) / dStep)) ;
|
||||
dYStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ;
|
||||
nRef = ( ( nYStep + ( bInvert ? 0 : 1)) % 2) ;
|
||||
}
|
||||
|
||||
// tratto valido
|
||||
struct Section {
|
||||
bool bActive ;
|
||||
Point3d ptS ;
|
||||
Point3d ptE ;
|
||||
double dOs ;
|
||||
double dOe ;
|
||||
size_t nIdxS ; // indice del loop a cui appartiene ptS
|
||||
size_t nIdxE ; // indice del loop a cui appartiene ptE
|
||||
} ;
|
||||
// raccolta di tratti
|
||||
typedef vector<vector<Section>> VECVECSECT ;
|
||||
|
||||
VECVECSECT vvSec ;
|
||||
vvSec.resize( nYStep + 1) ;
|
||||
|
||||
// calcolo le linee di svuotatura
|
||||
int nCount = 0 ;
|
||||
for ( int i = 0 ; i <= nYStep ; ++ i) {
|
||||
// determino senso
|
||||
bool bPlus = (( i % 2) == nRef) ;
|
||||
// definisco correzione per essere sicura di poter fare primo e ultimo step
|
||||
double dCorr = 0 ;
|
||||
if ( i == 0)
|
||||
dCorr = 10 * EPS_SMALL ;
|
||||
else if ( i == nYStep)
|
||||
dCorr = - 10 * EPS_SMALL ;
|
||||
// definisco la linea
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
const double EXP_LEN = 1.0 ;
|
||||
Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + dCorr + i * dYStep, ptMin.z + dDimZ) ;
|
||||
if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX , dDimX + 2 * EXP_LEN)) {
|
||||
return false ;
|
||||
}
|
||||
|
||||
// calcolo la classificazione della curva rispetto alla regione
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! GetCurveClassification( *pLine, EPS_SMALL, ccClass))
|
||||
return false ;
|
||||
|
||||
// determino gli intervalli di curva da conservare
|
||||
Intervals inOk ;
|
||||
for ( auto& ccOne : ccClass) {
|
||||
if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M)
|
||||
inOk.Add( ccOne.dParS, ccOne.dParE) ;
|
||||
}
|
||||
// inserisco i tratti validi (secondo X+ i pari, secondo X- i dispari)
|
||||
double dParS, dParE ;
|
||||
bool bFound = ( bPlus ? inOk.GetFirst( dParS, dParE) : inOk.GetLast( dParE, dParS)) ;
|
||||
while ( bFound) {
|
||||
// determino i dati della sezione
|
||||
Section Sect ;
|
||||
Sect.bActive = true ;
|
||||
pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, Sect.ptS) ;
|
||||
pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, Sect.ptE) ;
|
||||
|
||||
// porto i punti nel riferimento della curva
|
||||
if ( ! AreSameFrame( m_frF, GLOB_FRM)) {
|
||||
Sect.ptS.ToLoc( m_frF) ;
|
||||
Sect.ptE.ToLoc( m_frF) ;
|
||||
}
|
||||
|
||||
// cerco la curva della regione che passa per ptS
|
||||
bool bCrvFound = false ;
|
||||
for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) {
|
||||
bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptS, Sect.dOs, 10 * EPS_SMALL) ;
|
||||
if ( bCrvFound)
|
||||
Sect.nIdxS = k ;
|
||||
}
|
||||
if ( ! bCrvFound)
|
||||
return false ;
|
||||
|
||||
// cerco la curva della regione che passa per ptE
|
||||
bCrvFound = false ;
|
||||
for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) {
|
||||
bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptE, Sect.dOe, 10 * EPS_SMALL) ;
|
||||
if ( bCrvFound)
|
||||
Sect.nIdxE = k ;
|
||||
}
|
||||
if ( ! bCrvFound)
|
||||
return false ;
|
||||
|
||||
// inserisco nel contenitore
|
||||
vvSec[i].emplace_back( Sect) ;
|
||||
++ nCount ;
|
||||
// recupero intervallo successivo
|
||||
bFound = ( bPlus ? inOk.GetNext( dParS, dParE) : inOk.GetPrev( dParE, dParS)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// dominio del contorno
|
||||
DBLVECTOR vUmax( m_vpLoop.size()) ;
|
||||
DBLVECTOR vUmin( m_vpLoop.size()) ;
|
||||
DBLVECTOR vUspan( m_vpLoop.size()) ;
|
||||
for ( size_t i = 0 ; i < m_vpLoop.size() ; i++) {
|
||||
m_vpLoop[i]->GetDomain( vUmin[i], vUmax[i]) ;
|
||||
vUspan[i] = vUmax[i] - vUmin[i] ;
|
||||
}
|
||||
|
||||
// creo i percorsi di svuotatura
|
||||
vpCrvs.reserve( nCount) ;
|
||||
int nI = -1, nJ = -1 ;
|
||||
while ( true) {
|
||||
// se sezione non valida
|
||||
if ( nI < 0 || nJ < 0) {
|
||||
// ricerco la prima valida
|
||||
for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) {
|
||||
for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) {
|
||||
if ( vvSec[k][l].bActive) {
|
||||
nI = k ;
|
||||
nJ = l ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata, creo nuova curva composita
|
||||
if ( nI >= 0 && nJ >= 0) {
|
||||
// creo la curva
|
||||
vpCrvs.emplace_back( CreateCurveComposite()) ;
|
||||
// aggiungo punto iniziale
|
||||
vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ;
|
||||
}
|
||||
// altrimenti, esco
|
||||
else
|
||||
break ;
|
||||
}
|
||||
// determino senso
|
||||
bool bPlus = (( nI % 2) == nRef) ;
|
||||
// aggiungo la sezione alla curva
|
||||
Section& Sec = vvSec[nI][nJ] ;
|
||||
Sec.bActive = false ;
|
||||
vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ;
|
||||
// cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno
|
||||
double dUstart = Sec.dOe ;
|
||||
double dUref = ( bPlus ? INFINITO : - INFINITO) ;
|
||||
int nNextI = -1 ;
|
||||
int nNextJ = -1 ;
|
||||
int li = nJ + 1 ;
|
||||
for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) {
|
||||
for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) {
|
||||
if ( ! vvSec[k][l].bActive)
|
||||
continue ;
|
||||
// la nuova sezione deve partire dalla stessa curva su cui ci si è fermati
|
||||
if ( vvSec[k][l].nIdxS != Sec.nIdxE)
|
||||
continue ;
|
||||
double dU = vvSec[k][l].dOs ;
|
||||
if ( bPlus) {
|
||||
if ( dU < dUstart)
|
||||
dU += vUspan[Sec.nIdxE] ;
|
||||
if ( dU < dUref) {
|
||||
dUref = dU ;
|
||||
nNextI = k ;
|
||||
nNextJ = l ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( dU > dUstart)
|
||||
dU -= vUspan[Sec.nIdxE] ;
|
||||
if ( dU > dUref) {
|
||||
dUref = dU ;
|
||||
nNextI = k ;
|
||||
nNextJ = l ;
|
||||
}
|
||||
}
|
||||
}
|
||||
li = 0 ;
|
||||
}
|
||||
// se trovato, aggiungo il tratto di contorno e continuo
|
||||
if ( nNextI != -1) {
|
||||
PtrOwner<ICurve> pCopy ;
|
||||
size_t idx = vvSec[nNextI][nNextJ].nIdxS ;
|
||||
if ( bPlus) {
|
||||
if ( dUref > vUmax[idx])
|
||||
dUref -= vUspan[idx] ;
|
||||
pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ;
|
||||
if ( ! IsNull( pCopy)) {
|
||||
double dCLen ; pCopy->GetLength( dCLen) ;
|
||||
if ( dCLen > 0.5 * vLen[idx]) {
|
||||
pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ;
|
||||
if ( ! IsNull( pCopy))
|
||||
pCopy->Invert() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( dUref < vUmin[idx])
|
||||
dUref += vUspan[idx] ;
|
||||
pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ;
|
||||
if ( ! IsNull( pCopy)) {
|
||||
pCopy->Invert() ;
|
||||
double dCLen ; pCopy->GetLength( dCLen) ;
|
||||
if ( dCLen > 0.5 * vLen[idx])
|
||||
pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ;
|
||||
}
|
||||
}
|
||||
BBox3d b3Copy ;
|
||||
if ( ! IsNull( pCopy))
|
||||
pCopy->GetBBox( m_frF, b3Copy) ;
|
||||
if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) {
|
||||
vpCrvs.back()->AddCurve( Release( pCopy)) ;
|
||||
nI = nNextI ;
|
||||
nJ = nNextJ ;
|
||||
}
|
||||
else {
|
||||
nI = -1 ;
|
||||
nJ = -1 ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nI = -1 ;
|
||||
nJ = -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
// porto le curve calcolate nel riferimento globale
|
||||
if ( ! AreSameFrame( m_frF, GLOB_FRM)) {
|
||||
for ( int i = 0 ; i < ( int) vpCrvs.size() ; i++)
|
||||
vpCrvs[i]->ToGlob( m_frF) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+3
-1
@@ -18,6 +18,7 @@
|
||||
#include "GeoObjRW.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
|
||||
#include <deque>
|
||||
|
||||
@@ -94,6 +95,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
|
||||
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -136,7 +138,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ;
|
||||
static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ;
|
||||
static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ;
|
||||
static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ;
|
||||
static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EgkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+138
-409
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2019
|
||||
// EgalTech 2014-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMesh.cpp Data : 02.01.19 Versione : 1.9l4
|
||||
// File : SurfTriMesh.cpp Data : 12.08.22 Versione : 2.4h1
|
||||
// Contenuto : Implementazione della classe Superfici TriMesh.
|
||||
//
|
||||
//
|
||||
@@ -18,16 +18,17 @@
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "GeoConst.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <new>
|
||||
#include <set>
|
||||
@@ -239,7 +240,7 @@ SurfTriMesh::RemoveTriangle( int nId)
|
||||
// indice vertice
|
||||
int nV = m_vTria[nId].nIdVert[i] ;
|
||||
// se vertice non c'è passo al prossimo
|
||||
if ( nV < 0 || nV >= int( m_vTria.size()))
|
||||
if ( nV < 0 || nV >= int( m_vVert.size()))
|
||||
continue ;
|
||||
if ( m_vVert[nV].nIdTria == nId) {
|
||||
int nAdjP = m_vTria[nId].nIdAdjac[i] ;
|
||||
@@ -378,6 +379,27 @@ SurfTriMesh::GetCentroid( Point3d& ptCen) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IsEmpty( void) const
|
||||
{
|
||||
// verifico presenza di almeno un vertice
|
||||
bool bVertFound = false ;
|
||||
for ( int nId = 0 ; nId < GetVertexSize() && ! bVertFound ; ++ nId) {
|
||||
if ( m_vVert[nId].nIdTria != SVT_DEL)
|
||||
bVertFound = true ;
|
||||
}
|
||||
if ( ! bVertFound)
|
||||
return true ;
|
||||
// verifico presenza di almeno un triangolo
|
||||
bool bTriaFound = false ;
|
||||
for ( int nId = 0 ; nId < GetTriangleSize() && ! bTriaFound ; ++ nId) {
|
||||
if ( m_vTria[nId].nIdVert[0] != SVT_DEL)
|
||||
bTriaFound = true ;
|
||||
}
|
||||
return ( ! bTriaFound) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetVertexCount( void) const
|
||||
@@ -805,6 +827,41 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneTriangle( int nT) const
|
||||
{
|
||||
// verifico validità superficie ed esistenza del triangolo
|
||||
if ( ! IsValid() || nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL)
|
||||
return nullptr ;
|
||||
|
||||
// Creo nuovo oggetto SurfTriMesh
|
||||
PtrOwner<SurfTriMesh> pSurfTM( new( nothrow) SurfTriMesh) ;
|
||||
if ( IsNull( pSurfTM))
|
||||
return nullptr ;
|
||||
|
||||
// Copio il valore dei membri
|
||||
pSurfTM->m_dLinTol = m_dLinTol ;
|
||||
pSurfTM->m_dBoundaryAng = m_dBoundaryAng ;
|
||||
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
|
||||
// Copio il triangolo
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[0]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[1]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[2]].ptP)} ;
|
||||
if ( pSurfTM->AddTriangle( nNewInd, m_vTria[nT].nTFlag) == SVT_NULL)
|
||||
return nullptr ;
|
||||
|
||||
// Aggiusto la superficie
|
||||
pSurfTM->DoCompacting() ;
|
||||
|
||||
// Restituisco la nuova superficie
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
|
||||
@@ -1695,8 +1752,10 @@ SurfTriMesh::TestSealing( void)
|
||||
// verifico le adiacenze
|
||||
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL)
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
|
||||
bClosed = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// aggiorno la chiusura della superficie
|
||||
@@ -1716,7 +1775,7 @@ SurfTriMesh::AdjustTopology( void)
|
||||
return true ;
|
||||
}
|
||||
// dichiaro sfaccettatura da ricalcolare
|
||||
ResetFaceting() ;
|
||||
m_bFaceted = false ;
|
||||
// invalido calcolo connessione
|
||||
m_nParts = - 1 ;
|
||||
// verifica indici
|
||||
@@ -2082,79 +2141,26 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
// se rigata a minima distanza tra le due curve
|
||||
if ( nRuledType == RLT_MINDIST) {
|
||||
if ( nRuledType == RLT_MINDIST) {
|
||||
// verifico ci siano almeno due punti diversi per curva
|
||||
if ( ( PL1.IsClosed() && PL1.GetPointNbr() < 3) || PL1.GetPointNbr() < 2)
|
||||
return false ;
|
||||
if ( ( PL2.IsClosed() && PL2.GetPointNbr() < 3) || PL2.GetPointNbr() < 2)
|
||||
return false ;
|
||||
|
||||
return false ;
|
||||
|
||||
// flag di curve entrambe chiuse e correzione conseguente a numero totale punti differenti
|
||||
bool bClosed = PL1.IsClosed() && PL2.IsClosed() ;
|
||||
|
||||
// vettori punti con primo punto dell'altra curva a distanza minima
|
||||
PNTUVECTOR vPnt1 ;
|
||||
vPnt1.reserve( PL1.GetPointNbr()) ;
|
||||
Point3d ptP1 ;
|
||||
bool bF1 = PL1.GetFirstPoint( ptP1) ;
|
||||
while ( bF1) {
|
||||
vPnt1.emplace_back( ptP1, -1) ;
|
||||
bF1 = PL1.GetNextPoint( ptP1) ;
|
||||
}
|
||||
int nTotP1 = int( vPnt1.size()) ;
|
||||
PNTUVECTOR vPnt2 ;
|
||||
vPnt2.reserve( PL2.GetPointNbr()) ;
|
||||
Point3d ptP2 ;
|
||||
bool bF2 = PL2.GetFirstPoint( ptP2) ;
|
||||
while ( bF2) {
|
||||
vPnt2.emplace_back( ptP2, -1) ;
|
||||
bF2 = PL2.GetNextPoint( ptP2) ;
|
||||
}
|
||||
// vettori punti con indice del primo punto dell'altra curva a distanza minima
|
||||
PNTIVECTOR vPnt1, vPnt2 ;
|
||||
bool bCommonInternalPoints ;
|
||||
if ( ! AssociatePolyLinesMinDistPoints( PL1, PL2, vPnt1, vPnt2, bCommonInternalPoints))
|
||||
return false ;
|
||||
// verifico che non ci siano punti interni in comune
|
||||
if ( bCommonInternalPoints)
|
||||
return false ;
|
||||
int nTotP1 = int( vPnt1.size()) ;
|
||||
int nTotP2 = int( vPnt2.size()) ;
|
||||
// calcoli per prima curva
|
||||
int LastJ = 0 ;
|
||||
vPnt1[0].second = 0 ;
|
||||
for ( int i = 1 ; i < nTotP1 ; ++ i) {
|
||||
double dSqDistMin = SqDist( vPnt1[i].first, vPnt2[LastJ].first) ;
|
||||
double dApprDistMin = ApproxDist( vPnt1[i].first, vPnt2[LastJ].first) ;
|
||||
int MinJ = LastJ ;
|
||||
for ( int j = LastJ + 1 ; j < nTotP2 ; ++ j) {
|
||||
double dSqDist = SqDist( vPnt1[i].first, vPnt2[j].first) ;
|
||||
if ( dSqDist < dSqDistMin - 2 * dApprDistMin * EPS_SMALL) {
|
||||
dSqDistMin = dSqDist ;
|
||||
dApprDistMin = ApproxDist( vPnt1[i].first, vPnt2[j].first) ;
|
||||
MinJ = j ;
|
||||
}
|
||||
else if ( dSqDist > 16 * dSqDistMin)
|
||||
break ;
|
||||
}
|
||||
if ( i < nTotP1 - 1 && dSqDistMin < EPS_SMALL)
|
||||
return false ;
|
||||
vPnt1[i].second = MinJ ;
|
||||
LastJ = MinJ ;
|
||||
}
|
||||
// calcoli per seconda curva
|
||||
int LastI = 0 ;
|
||||
vPnt2[0].second = 0 ;
|
||||
for ( int j = 1 ; j < nTotP2 ; ++ j) {
|
||||
double dSqDistMin = SqDist( vPnt2[j].first, vPnt1[LastI].first) ;
|
||||
double dApprDistMin = ApproxDist( vPnt2[j].first, vPnt1[LastI].first) ;
|
||||
int MinI = LastI ;
|
||||
for ( int i = LastI + 1 ; i < nTotP1 ; ++ i) {
|
||||
double dSqDist = SqDist( vPnt2[j].first, vPnt1[i].first) ;
|
||||
if ( dSqDist < dSqDistMin - 2 * dApprDistMin * EPS_SMALL) {
|
||||
dSqDistMin = dSqDist ;
|
||||
dApprDistMin = ApproxDist( vPnt2[j].first, vPnt1[i].first) ;
|
||||
MinI = i ;
|
||||
}
|
||||
else if ( dSqDist > 16 * dSqDistMin)
|
||||
break ;
|
||||
}
|
||||
if ( j < nTotP2 - 1 && dSqDistMin < EPS_SMALL)
|
||||
return false ;
|
||||
vPnt2[j].second = MinI ;
|
||||
LastI = MinI ;
|
||||
}
|
||||
|
||||
// Costruisco la mesh
|
||||
int nVertNbr = nTotP1 + nTotP2 ;
|
||||
@@ -2205,7 +2211,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
}
|
||||
// ciclo sui punti
|
||||
while ( bNext1 || bNext2) {
|
||||
// se c'è nuovo V1s e la diagonale più corta è V2p -> V1s oppure non c'è V2s
|
||||
// se non c'è V2s oppure c'è nuovo V1s e la diagonale più corta è V2p -> V1s
|
||||
if ( ! bNext2 || ( bNext1 && ( nP1s == vPnt2[nP2p].second || vPnt1[nP1s].second == nP2p))) {
|
||||
// inserisco il vertice V1s (se ultimo e curve chiuse, prendo il primo)
|
||||
if ( nP1s == nTotP1 - 1 && bClosed)
|
||||
@@ -2258,7 +2264,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
if ( ! VerifyPolylinesForTwoCurves( PL1, PL2))
|
||||
return false ;
|
||||
|
||||
// flag di curve chiuse
|
||||
// flag di curve chiuse
|
||||
bool bClosed = PL1.IsClosed() && PL2.IsClosed() ;
|
||||
// recupero i parametri delle due polilinee
|
||||
double dU1F ; PL1.GetFirstU( dU1F) ;
|
||||
@@ -2273,6 +2279,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
return false ;
|
||||
|
||||
// costruisco la mesh
|
||||
bool bTwist = false ;
|
||||
int nVertNbr = PL1.GetPointNbr() + PL2.GetPointNbr() ;
|
||||
int nTriaNbr = max( PL1.GetPointNbr(), PL2.GetPointNbr()) + 1 ;
|
||||
if ( ! Init( nVertNbr, nTriaNbr))
|
||||
@@ -2329,8 +2336,57 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
}
|
||||
// ciclo sui punti
|
||||
while ( bNext1 || bNext2) {
|
||||
// se c'è nuovo dA1s e la diagonale più corta è dA2p -> dA1s oppure non c'è dA2s
|
||||
if ( ( bNext1 && ( dA1s - dA2p) <= ( dA2s - dA1p) + EPS_PARAM) || ! bNext2) {
|
||||
// se richiesto smoothing, ci sono entrambi i successivi, hanno circa lo stesso parametro e i segmenti sono sghembi oltre il limite
|
||||
double dDiagDist = 0 ;
|
||||
if ( nRuledType == RLT_ISOPAR_SMOOTH &&
|
||||
bNext1 && bNext2 && abs( dA1p + dA1s - dA2p - dA2s) < min( dA1s - dA1p, dA2s - dA2p) &&
|
||||
DistLineLine( ptP1p, ptP2s, ptP2p, ptP1s).GetDist( dDiagDist) && dDiagDist > STM_TWIST_DIAG_DIST) {
|
||||
bTwist = true ;
|
||||
// inserisco il vertice A1s
|
||||
if ( ( nV1s = AddVertex( ptP1s)) == SVT_NULL)
|
||||
return false ;
|
||||
// inserisco il vertice A2s
|
||||
if ( ( nV2s = AddVertex( ptP2s)) == SVT_NULL)
|
||||
return false ;
|
||||
// inserisco un nuovo vertice punto medio della linea tra i punti medi
|
||||
Point3d ptCen = ( ptP1s + ptP1p + ptP2s + ptP2p) / 4 ;
|
||||
int nVCen = AddVertex( ptCen) ;
|
||||
if ( nVCen == SVT_NULL)
|
||||
return false ;
|
||||
// creo 4 triangoli dai lati del quadrilatero al vertice
|
||||
nIdV[0] = nV2p ;
|
||||
nIdV[1] = nV1p ;
|
||||
nIdV[2] = nVCen ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
nIdV[0] = nV1p ;
|
||||
nIdV[1] = nV1s ;
|
||||
nIdV[2] = nVCen ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
nIdV[0] = nV1s ;
|
||||
nIdV[1] = nV2s ;
|
||||
nIdV[2] = nVCen ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
nIdV[0] = nV2s ;
|
||||
nIdV[1] = nV2p ;
|
||||
nIdV[2] = nVCen ;
|
||||
if ( AddTriangle( nIdV) == SVT_NULL)
|
||||
return false ;
|
||||
// passo al punto successivo su 1
|
||||
nV1p = nV1s ; dA1p = dA1s ; dU1p = dU1s ; ptP1p = ptP1s ;
|
||||
bNext1 = PL1.GetNextUPoint( &dU1s, &ptP1s, bClosed) ;
|
||||
if ( bNext1)
|
||||
dA1s = ( dU1s - dU1F) / dDeltaU1 ;
|
||||
// passo al punto successivo su 2
|
||||
nV2p = nV2s ; dA2p = dA2s ; dU2p = dU2s ; ptP2p = ptP2s ;
|
||||
bNext2 = PL2.GetNextUPoint( &dU2s, &ptP2s, bClosed) ;
|
||||
if ( bNext2)
|
||||
dA2s = ( dU2s - dU2F) / dDeltaU2 ;
|
||||
}
|
||||
// se non c'è dA2s oppure c'è nuovo dA1s e la diagonale più corta è dA2p -> dA1s
|
||||
else if ( ! bNext2 || ( bNext1 && ( dA1s - dA2p) <= ( dA2s - dA1p) + EPS_PARAM)) {
|
||||
// inserisco il vertice A1s
|
||||
if ( ( nV1s = AddVertex( ptP1s)) == SVT_NULL)
|
||||
return false ;
|
||||
@@ -2413,6 +2469,9 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nR
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// in presenza di twist aumento il limite sulla deviazione angolare
|
||||
if ( bTwist)
|
||||
SetSmoothAngle( STM_TWIST_SMOOTH_ANG) ;
|
||||
}
|
||||
|
||||
// sistemo la topologia
|
||||
@@ -2858,7 +2917,7 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
// definisco un Grid per i vertici della superficie
|
||||
PointGrid3d VertGrid ;
|
||||
int nBuckets = GetVertexSize() ;
|
||||
VertGrid.Init( nBuckets) ;
|
||||
VertGrid.Init( nBuckets, max( dTol, 100 * EPS_SMALL)) ;
|
||||
|
||||
// inserisco i vertici della trimesh (evitando ripetizioni coi precedenti),
|
||||
// salvando in un vettore di reindirizzo i nuovi Id
|
||||
@@ -2982,7 +3041,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, dou
|
||||
}
|
||||
int nVIdSize = int( vVId.size()) ;
|
||||
|
||||
// inserisco i triangoli dell'altra trimesh
|
||||
// aggiungo i triangoli dell'altra trimesh
|
||||
for ( int nOtId = 0 ; nOtId < pOther->GetTriangleSize() ; ++ nOtId) {
|
||||
// recupero gli indici dei vertici del triangolo
|
||||
int vOId[3] ;
|
||||
@@ -3178,7 +3237,7 @@ bool
|
||||
SurfTriMesh::InvertTriangle( int nT)
|
||||
{
|
||||
// controllo validità triangolo
|
||||
if ( m_vTria[nT].nIdVert[0] == SVT_DEL)
|
||||
if ( ! ExistsTriangle( nT))
|
||||
return true ;
|
||||
// scambio di due vertici
|
||||
swap( m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]) ;
|
||||
@@ -3399,336 +3458,6 @@ SurfTriMesh::Invert( void)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// classifico i vertici rispetto al piano
|
||||
double dTol = max( min( 0.5 * m_dLinTol, 10 * EPS_SMALL), EPS_SMALL) ;
|
||||
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
|
||||
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
|
||||
if ( abs( dDist) < dTol) {
|
||||
m_vVert[i].nTemp = 0 ;
|
||||
if ( abs( dDist) > EPS_SMALL)
|
||||
m_vVert[i].ptP -= plPlane.GetVersN() * dDist ;
|
||||
}
|
||||
else if ( dDist > 0)
|
||||
m_vVert[i].nTemp = +1 ;
|
||||
else
|
||||
m_vVert[i].nTemp = -1 ;
|
||||
}
|
||||
|
||||
// aggiorno timestamp dei triangoli
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nTemp = m_nTimeStamp ;
|
||||
++ m_nTimeStamp ;
|
||||
|
||||
// sistemo i triangoli (eventualmente li elimino)
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// salto i triangoli cancellati e quelli aggiunti
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
|
||||
continue ;
|
||||
// se flag abilita e giace sul piano ed equiverso, lo salvo
|
||||
if ( bSaveOnEq &&
|
||||
m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp == 0 &&
|
||||
AreSameVectorApprox( m_vTria[i].vtN, plPlane.GetVersN()))
|
||||
;
|
||||
// se giace sul piano o dalla parte esterna del piano, lo cancello
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != -1) {
|
||||
bModif = true ;
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != 1)
|
||||
;
|
||||
// altrimenti attraversa il piano, devo modificarlo
|
||||
else {
|
||||
bModif = true ;
|
||||
int nDisc = m_vVert[ m_vTria[i].nIdVert[0]].nTemp +
|
||||
m_vVert[ m_vTria[i].nIdVert[1]].nTemp +
|
||||
m_vVert[ m_vTria[i].nIdVert[2]].nTemp ;
|
||||
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
|
||||
if ( nDisc == 0) {
|
||||
// classifico i vertici
|
||||
int nVertOn, nVertIn, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0) {
|
||||
nVertOn = 0 ;
|
||||
nVertIn = 1 ;
|
||||
nVertOut = 2 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0) {
|
||||
nVertOn = 1 ;
|
||||
nVertIn = 2 ;
|
||||
nVertOut = 0 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[2]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else {
|
||||
nVertOn = 2 ;
|
||||
nVertIn = 0 ;
|
||||
nVertOut = 1 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
// calcolo il punto di intersezione del lato che attraversa il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut)) ;
|
||||
// inserisco il nuovo vertice
|
||||
int nNewV = AddVertex( ptInt) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
nIdVert[nVertOut] = nNewV ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( nIdTria == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria != SVT_DEL)
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
|
||||
else if ( nDisc == 1) {
|
||||
// classifico i vertici
|
||||
int nVertIn, nVertOut1, nVertOut2 ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == -1) {
|
||||
nVertIn = 0 ;
|
||||
nVertOut1 = 1 ;
|
||||
nVertOut2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == -1) {
|
||||
nVertIn = 1 ;
|
||||
nVertOut1 = 2 ;
|
||||
nVertOut2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertIn = 2 ;
|
||||
nVertOut1 = 0 ;
|
||||
nVertOut2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP, plPlane) ;
|
||||
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut1)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut2)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
nIdVert[nVertOut1] = nNewV1 ;
|
||||
nIdVert[nVertOut2] = nNewV2 ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( nIdTria == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria != SVT_DEL)
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
|
||||
else {
|
||||
// classifico i vertici
|
||||
int nVertIn1, nVertIn2, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 1) {
|
||||
nVertOut = 0 ;
|
||||
nVertIn1 = 1 ;
|
||||
nVertIn2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 1) {
|
||||
nVertOut = 1 ;
|
||||
nVertIn1 = 2 ;
|
||||
nVertIn2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertOut = 2 ;
|
||||
nVertIn1 = 0 ;
|
||||
nVertIn2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, plPlane) ;
|
||||
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn1 / ( dDistIn1 + dDistOut)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP,
|
||||
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
|
||||
dDistIn2 / ( dDistIn2 + dDistOut)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco i nuovi triangoli
|
||||
int nIdVert1[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
int nIdVert2[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
|
||||
double dSqDist1 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, ptInt2) ;
|
||||
double dSqDist2 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, ptInt1) ;
|
||||
if ( dSqDist1 <= dSqDist2) {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert1[nVertIn2] = nNewV2 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
}
|
||||
else {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
nIdVert2[nVertIn1] = nNewV1 ;
|
||||
}
|
||||
int nIdTria1 = AddTriangle( nIdVert1) ;
|
||||
int nIdTria2 = AddTriangle( nIdVert2) ;
|
||||
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria1 != SVT_DEL)
|
||||
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
|
||||
if ( nIdTria2 != SVT_DEL)
|
||||
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
|
||||
{
|
||||
// Setto posizione triangoli non definita
|
||||
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT)
|
||||
m_vTria[nT].nTempPart = 0 ;
|
||||
|
||||
INTERSCHAINMAP IntersLineMap ;
|
||||
|
||||
// Ciclo su tutte le facce.
|
||||
for ( int nF = 0 ; nF < GetFacetCount() ; ++ nF) {
|
||||
// Dati della faccia
|
||||
POLYLINEVECTOR vLoopVec ;
|
||||
GetFacetLoops( nF, vLoopVec) ;
|
||||
if ( vLoopVec.empty())
|
||||
continue ;
|
||||
// Verifico la posizione del loop esterno
|
||||
int nIntType = VerifyLoopPlane( vLoopVec[0], plPlane) ;
|
||||
// Se interseca il piano di taglio, calcolo la divisione della faccia
|
||||
LineFacetClassVector IntersLinePart ;
|
||||
if ( nIntType == FPI_CUT) {
|
||||
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
|
||||
if ( IsNull( pReg) || ! pReg->IsValid())
|
||||
return false ;
|
||||
nIntType = IntersFacetPlane( *pReg, plPlane, IntersLinePart) ;
|
||||
}
|
||||
// Gestione dei risultati
|
||||
if ( nIntType == FPI_CUT) {
|
||||
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
|
||||
// Salvo intersezione per la faccia.
|
||||
auto it = IntersLineMap.find( nF) ;
|
||||
if ( it != IntersLineMap.end()) {
|
||||
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
|
||||
}
|
||||
else {
|
||||
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( nIntType == FPI_ON) {
|
||||
INTVECTOR vT ;
|
||||
GetAllTriaInFacet( nF, vT) ;
|
||||
Vector3d vtNf ;
|
||||
GetFacetNormal( nF, vtNf) ;
|
||||
for ( auto& nT : vT)
|
||||
m_vTria[nT].nTempPart = ( vtNf * plPlane.GetVersN() > 0 ? 2 : -2) ;
|
||||
}
|
||||
else if ( nIntType == FPI_IN) {
|
||||
INTVECTOR vT ;
|
||||
GetAllTriaInFacet( nF, vT) ;
|
||||
for ( auto& nT : vT)
|
||||
m_vTria[nT].nTempPart = 1 ;
|
||||
}
|
||||
else if ( nIntType == FPI_OUT) {
|
||||
INTVECTOR vT ;
|
||||
GetAllTriaInFacet( nF, vT) ;
|
||||
for ( auto& nT : vT)
|
||||
m_vTria[nT].nTempPart = -1 ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Divido le facce.
|
||||
PieceMap NewFacet ;
|
||||
SplitFacet( IntersLineMap, NewFacet) ;
|
||||
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
|
||||
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
|
||||
|
||||
// Elimino i triangoli superflui
|
||||
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
|
||||
if ( m_vTria[nT].nTempPart == 0 ||
|
||||
m_vTria[nT].nTempPart == -1 ||
|
||||
m_vTria[nT].nTempPart == -2 ||
|
||||
( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) {
|
||||
RemoveTriangle( nT) ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// recupero il numero originale di triangoli e di facce
|
||||
int nTriaOriCnt = GetTriangleCount() ;
|
||||
int nFacetOriCnt = GetFacetCount() ;
|
||||
|
||||
// eseguo il taglio con il metodo delle faccette o dei triangoli (per ora solo coi triangoli)
|
||||
bool bModif = false ;
|
||||
if ( true || ! CutByFacets( plPlane, bSaveOnEq, bModif)) {
|
||||
bModif = false ;
|
||||
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se effettuate modifiche
|
||||
if ( bModif) {
|
||||
// aggiorno tutto
|
||||
if ( ! AdjustVertices() || ! DoCompacting())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se superficie originale a facce, cerco di semplificarle in ogni caso
|
||||
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
|
||||
if ( ! SimplifyFacets( 500.0))
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Cut")
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
SurfTriMesh::ResetHashGrids3d( void) const
|
||||
|
||||
+29
-59
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2021
|
||||
// EgalTech 2014-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMesh.h Data : 26.09.21 Versione : 2.3i2
|
||||
// File : SurfTriMesh.h Data : 10.10.22 Versione : 2.4i4
|
||||
// Contenuto : Dichiarazione della classe Superficie TriMesh.
|
||||
//
|
||||
//
|
||||
@@ -94,30 +94,11 @@ typedef std::unordered_map< int, Chain> CHAINMAP ;
|
||||
typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Struttura per la ricerca delle T-Junction
|
||||
struct TEdgeId {
|
||||
int nTriaId ;
|
||||
int nEdge ;
|
||||
} ;
|
||||
// Overloading dell'operatore < per TEdgeSet
|
||||
inline bool operator<( const TEdgeId& TEdgeA, const TEdgeId& TEdgeB) {
|
||||
if ( TEdgeA.nTriaId != TEdgeB.nTriaId)
|
||||
return ( TEdgeA.nTriaId < TEdgeB.nTriaId) ;
|
||||
return ( TEdgeA.nEdge < TEdgeB.nEdge) ;
|
||||
}
|
||||
// Loop con T-Junction
|
||||
typedef std::vector<TEdgeId> TJuncLoop ;
|
||||
// Vettore di loop con T-Junction
|
||||
typedef std::vector<TJuncLoop> TJuncLoopVec ;
|
||||
// Set di TEdgeId
|
||||
typedef std::set<TEdgeId> TJEdgeSet ;
|
||||
|
||||
// Definizione strutture intersezione linea-faccia
|
||||
//----------------------------------------------------------------------------
|
||||
// Struttura intersezione linea-faccia
|
||||
struct LineFacetClass {
|
||||
Point3d ptSt, ptEn ;
|
||||
int nTypeA, nTypeB ;
|
||||
LineFacetClass() {
|
||||
LineFacetClass( void) {
|
||||
nTypeA = 0 ;
|
||||
nTypeB = 0 ;
|
||||
}
|
||||
@@ -134,25 +115,24 @@ typedef std::vector<LineFacetClass> LineFacetClassVector ;
|
||||
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_IN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Definizione strutture e contenitori
|
||||
// Contatti interno-interno
|
||||
// Strutture e contenitori contatti interno-interno
|
||||
struct IntersInnSeg {
|
||||
Point3d ptSt ;
|
||||
Point3d ptEn ;
|
||||
Vector3d vtOuter ;
|
||||
IntersInnSeg(void) {
|
||||
IntersInnSeg( void) {
|
||||
;
|
||||
}
|
||||
IntersInnSeg(const Point3d& ptS, const Point3d& ptE) {
|
||||
ptSt = ptS;
|
||||
ptEn = ptE;
|
||||
IntersInnSeg( const Point3d& ptS, const Point3d& ptE) {
|
||||
ptSt = ptS ;
|
||||
ptEn = ptE ;
|
||||
}
|
||||
IntersInnSeg(const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
|
||||
ptSt = ptS;
|
||||
ptEn = ptE;
|
||||
vtOuter = vtO;
|
||||
IntersInnSeg( const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
|
||||
ptSt = ptS ;
|
||||
ptEn = ptE ;
|
||||
vtOuter = vtO ;
|
||||
}
|
||||
};
|
||||
} ;
|
||||
typedef std::vector<IntersInnSeg> IntersInnChain ;
|
||||
typedef std::vector<IntersInnChain> INNCHAINVECTOR ;
|
||||
typedef std::unordered_map<int, IntersInnChain> INTERSCHAINMAP ;
|
||||
@@ -164,7 +144,7 @@ struct IntersEdge {
|
||||
IntersEdge( const Point3d& ptS, const Point3d& ptE, const INTVECTOR& vOFI) {
|
||||
ptSt = ptS;
|
||||
ptEn = ptE;
|
||||
vOthFacetIndex = vOFI;
|
||||
vOthFacetIndex = vOFI ;
|
||||
}
|
||||
} ;
|
||||
typedef std::vector<IntersEdge> IntersEdgeVec ;
|
||||
@@ -250,6 +230,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
double dAngRot, double dStepRot, double dMove) override ;
|
||||
bool DoCompacting( double dTol = EPS_SMALL) override ;
|
||||
bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM, double dTol = 2 * EPS_SMALL) override ;
|
||||
bool IsEmpty( void) const override ;
|
||||
int GetVertexCount( void) const override ;
|
||||
int GetTriangleCount( void) const override ;
|
||||
int GetTriangleCount( int nTFlag) const override ;
|
||||
@@ -277,6 +258,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetVertexSmoothNormal( int nV, int nT, Vector3d& vtN) const override ;
|
||||
bool GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const override ;
|
||||
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
|
||||
SurfTriMesh* CloneTriangle( int nT) const override ;
|
||||
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const override ;
|
||||
int GetFacetCount( void) const override ;
|
||||
@@ -305,6 +287,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
|
||||
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
|
||||
bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ;
|
||||
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
|
||||
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
|
||||
const BBox3d& GetAllTriaBox( void) const override ;
|
||||
int GetPartCount( void) const override ;
|
||||
@@ -329,6 +312,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
|
||||
return *this ; }
|
||||
bool Clear( void) ;
|
||||
bool ExistsTriangle( int nT) const
|
||||
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
|
||||
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
|
||||
bool GetTriangleFlag( int nId, int& nFlag) const ;
|
||||
bool GetTriangleTempInt( int nId, int& nTempInt) const ;
|
||||
@@ -370,9 +355,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
|
||||
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
|
||||
bool AddBiTriangle( const int nIdVert[4]) ;
|
||||
bool ResetFaceting( void) ;
|
||||
bool VerifyFaceting( void) const ;
|
||||
bool UpdateFaceting( void) ;
|
||||
bool UpdateOneFace( int nFacet, int nT) ;
|
||||
bool UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT) ;
|
||||
bool SetFacet( int nInd, int nT) ;
|
||||
bool VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const ;
|
||||
@@ -381,36 +366,21 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
void ResetHashGrids3d( void) const ;
|
||||
bool VerifyHashGrids3d( void) const ;
|
||||
bool VerifyConnection( void) const ;
|
||||
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
|
||||
bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
|
||||
bool CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
|
||||
bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ;
|
||||
bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ;
|
||||
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
|
||||
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
|
||||
int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ;
|
||||
int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane,
|
||||
LineFacetClassVector& IntersLinePart) ;
|
||||
bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA,
|
||||
const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB,
|
||||
LineFacetClassVector& IntersLinePart) ;
|
||||
bool IntersectTriMeshFacets( SurfTriMesh& Other) ;
|
||||
bool RetriangulateFacetPieces( const PieceMap& NewFacet,
|
||||
const INTERSEDGEMAP& EdgeInterLineMap,
|
||||
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen) ;
|
||||
bool EdgeInteriorContactManager( const SurfTriMesh& OthSurf,
|
||||
const INTERSCHAINMAP& InterInterLineMap,
|
||||
const INTERSEDGEMAP& EdgeInterLineMap) ;
|
||||
bool EdgeEdgeContactManager( const SurfTriMesh& OthSurf,
|
||||
const INTERSCHAINMAP& InterInterLineMap,
|
||||
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
|
||||
bool SplitFacet( const INTERSCHAINMAP& IntersLineMap, PieceMap& NewFacet);
|
||||
bool IdentifyParts( void) const ;
|
||||
bool RemoveTJunctions( void) ;
|
||||
bool RemoveCaps( void) ;
|
||||
bool RemoveTripleTriangles( void) ;
|
||||
bool ScanForTripleTriangles( bool& bModified) ;
|
||||
bool RemoveDoubleTriangles( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified) ;
|
||||
bool FlipTriangles( int nTA, int nTB) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
|
||||
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
|
||||
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
|
||||
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
|
||||
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
|
||||
+213
-2756
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,786 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2019-2021
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMeshCuts.cpp Data : 06.11.21 Versione : 2.3k3
|
||||
// Contenuto : Implementazione delle funzioni di taglio per SurfFTrimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 06.11.21 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const double CUT_SCALE = 1024 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// recupero il numero originale di triangoli e di facce
|
||||
int nTriaOriCnt = GetTriangleCount() ;
|
||||
int nFacetOriCnt = GetFacetCount() ;
|
||||
|
||||
// eseguo il taglio con il metodo dei triangoli
|
||||
bool bModif = false ;
|
||||
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
|
||||
return false ;
|
||||
|
||||
// se effettuate modifiche
|
||||
if ( bModif) {
|
||||
// aggiorno tutto
|
||||
if ( ! AdjustVertices() || ! DoCompacting())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se superficie originale a facce, cerco di semplificarle in ogni caso
|
||||
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
|
||||
if ( ! SimplifyFacets())
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Cut")
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// classifico i vertici rispetto al piano
|
||||
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
|
||||
// salto i vertici cancellati
|
||||
if ( m_vVert[i].nIdTria == SVT_DEL)
|
||||
continue ;
|
||||
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
m_vVert[i].nTemp = 0 ;
|
||||
else if ( dDist > 0)
|
||||
m_vVert[i].nTemp = +1 ;
|
||||
else
|
||||
m_vVert[i].nTemp = -1 ;
|
||||
}
|
||||
|
||||
// aggiorno timestamp dei triangoli
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nTemp = m_nTimeStamp ;
|
||||
++ m_nTimeStamp ;
|
||||
|
||||
// sistemo i triangoli (eventualmente li elimino)
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// salto i triangoli cancellati e quelli aggiunti
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
|
||||
continue ;
|
||||
CutTriangleByPlane( i, plPlane, bSaveOnEq, bModif) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CutTriangleByPlane( int nT, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
|
||||
{
|
||||
// se flag abilita e giace sul piano ed equiverso, lo salvo
|
||||
if ( bSaveOnEq &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp == 0 &&
|
||||
AreSameVectorApprox( m_vTria[nT].vtN, plPlane.GetVersN()))
|
||||
;
|
||||
// se giace sul piano o dalla parte esterna del piano, lo cancello
|
||||
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != -1 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != -1) {
|
||||
bModif = true ;
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
|
||||
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != 1 &&
|
||||
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != 1)
|
||||
;
|
||||
// altrimenti attraversa il piano, devo modificarlo
|
||||
else {
|
||||
bModif = true ;
|
||||
int nDisc = m_vVert[ m_vTria[nT].nIdVert[0]].nTemp +
|
||||
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp +
|
||||
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp ;
|
||||
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
|
||||
if ( nDisc == 0) {
|
||||
// classifico i vertici
|
||||
int nVertOn, nVertIn, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0) {
|
||||
nVertOn = 0 ;
|
||||
nVertIn = 1 ;
|
||||
nVertOut = 2 ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0) {
|
||||
nVertOn = 1 ;
|
||||
nVertIn = 2 ;
|
||||
nVertOut = 0 ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[2]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
else {
|
||||
nVertOn = 2 ;
|
||||
nVertIn = 0 ;
|
||||
nVertOut = 1 ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp > 0)
|
||||
swap( nVertIn, nVertOut) ;
|
||||
}
|
||||
// calcolo il punto di intersezione del lato che attraversa il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut)) ;
|
||||
// inserisco il nuovo vertice
|
||||
int nNewV = AddVertex( ptInt) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
|
||||
nIdVert[nVertOut] = nNewV ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( nIdTria == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria != SVT_DEL)
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
|
||||
else if ( nDisc == 1) {
|
||||
// classifico i vertici
|
||||
int nVertIn, nVertOut1, nVertOut2 ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == -1) {
|
||||
nVertIn = 0 ;
|
||||
nVertOut1 = 1 ;
|
||||
nVertOut2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == -1) {
|
||||
nVertIn = 1 ;
|
||||
nVertOut1 = 2 ;
|
||||
nVertOut2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertIn = 2 ;
|
||||
nVertOut1 = 0 ;
|
||||
nVertOut2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
|
||||
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP, plPlane) ;
|
||||
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut1)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
|
||||
m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP,
|
||||
dDistIn / ( dDistIn + dDistOut2)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco il nuovo triangolo
|
||||
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
|
||||
nIdVert[nVertOut1] = nNewV1 ;
|
||||
nIdVert[nVertOut2] = nNewV2 ;
|
||||
int nIdTria = AddTriangle( nIdVert) ;
|
||||
if ( nIdTria == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria != SVT_DEL)
|
||||
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
|
||||
else {
|
||||
// classifico i vertici
|
||||
int nVertIn1, nVertIn2, nVertOut ;
|
||||
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 1) {
|
||||
nVertOut = 0 ;
|
||||
nVertIn1 = 1 ;
|
||||
nVertIn2 = 2 ;
|
||||
}
|
||||
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 1) {
|
||||
nVertOut = 1 ;
|
||||
nVertIn1 = 2 ;
|
||||
nVertIn2 = 0 ;
|
||||
}
|
||||
else {
|
||||
nVertOut = 2 ;
|
||||
nVertIn1 = 0 ;
|
||||
nVertIn2 = 1 ;
|
||||
}
|
||||
// calcolo i punti di intersezione dei lati che attraversano il piano
|
||||
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, plPlane) ;
|
||||
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, plPlane) ;
|
||||
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
|
||||
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP,
|
||||
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
|
||||
dDistIn1 / ( dDistIn1 + dDistOut)) ;
|
||||
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP,
|
||||
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
|
||||
dDistIn2 / ( dDistIn2 + dDistOut)) ;
|
||||
// inserisco i nuovi vertici
|
||||
int nNewV1 = AddVertex( ptInt1) ;
|
||||
int nNewV2 = AddVertex( ptInt2) ;
|
||||
// inserisco i nuovi triangoli
|
||||
int nIdVert1[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
|
||||
int nIdVert2[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
|
||||
double dSqDist1 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, ptInt2) ;
|
||||
double dSqDist2 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, ptInt1) ;
|
||||
if ( dSqDist1 <= dSqDist2) {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert1[nVertIn2] = nNewV2 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
}
|
||||
else {
|
||||
nIdVert1[nVertOut] = nNewV1 ;
|
||||
nIdVert2[nVertOut] = nNewV2 ;
|
||||
nIdVert2[nVertIn1] = nNewV1 ;
|
||||
}
|
||||
int nIdTria1 = AddTriangle( nIdVert1) ;
|
||||
int nIdTria2 = AddTriangle( nIdVert2) ;
|
||||
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
|
||||
return false ;
|
||||
if ( nIdTria1 != SVT_DEL)
|
||||
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
|
||||
if ( nIdTria2 != SVT_DEL)
|
||||
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
|
||||
// cancello il vecchio triangolo
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Risultato : 0=nessuna intersezione, 1=intersezione è un punto, 2=intersezione è un segmento
|
||||
static int
|
||||
IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3d& vtL2,
|
||||
const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg)
|
||||
{
|
||||
// Assegno tolleranza lineare
|
||||
double dTol = EPS_SMALL ;
|
||||
// Definisco il piano del rettangolo
|
||||
Plane3d plRectanglePlane ;
|
||||
if ( ! plRectanglePlane.Set( ptP, vtL1 ^ vtL2))
|
||||
return -1 ;
|
||||
// Interseco il piano con il triangolo (recupero estremi in ordine inverso per mantenere l'esterno a destra nei loop)
|
||||
int nPlTrIntRes = IntersPlaneTria( plRectanglePlane, trTria, ptEnSeg, ptStSeg) ;
|
||||
if ( nPlTrIntRes != IntPlaneTriaType::IPTT_YES)
|
||||
return 0 ;
|
||||
// Limito il segmento col rettangolo
|
||||
Vector3d vtSegDir = ptEnSeg - ptStSeg ;
|
||||
double dSegLen = vtSegDir.Len() ;
|
||||
vtSegDir /= dSegLen ;
|
||||
// utilizzo piani ortogonali al rettangolo passanti per i suoi estremi
|
||||
Plane3d plTrim1 ; plTrim1.Set( ptP, -vtL1) ;
|
||||
Plane3d plTrim2 ; plTrim2.Set( ptP + vtL1, vtL1) ;
|
||||
if ( vtSegDir * vtL1 < 0.)
|
||||
swap( plTrim1, plTrim2) ;
|
||||
Point3d ptInt1 ;
|
||||
int nLnPl1IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim1, ptInt1, false) ;
|
||||
Point3d ptInt2 ;
|
||||
int nLnPl2IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim2, ptInt2, false) ;
|
||||
// Se il segmento giace in uno dei due piani
|
||||
if ( ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_INPLANE) ||
|
||||
( nLnPl2IntRes == ILPT_NO && nLnPl1IntRes == ILPT_INPLANE))
|
||||
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
|
||||
// Se non ci sono intersezioni
|
||||
if ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_NO) {
|
||||
// se è tra i due piani
|
||||
if (( ptStSeg - plTrim1.GetPoint()) * plTrim1.GetVersN() < 0. &&
|
||||
( ptStSeg - plTrim2.GetPoint()) * plTrim2.GetVersN() < 0.)
|
||||
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
|
||||
// altrimenti è esterno
|
||||
else
|
||||
return 0 ;
|
||||
}
|
||||
// Posizioni parametriche delle intersezioni sul segmento
|
||||
double dLen1 = ( ptInt1 - ptStSeg) * vtSegDir ;
|
||||
double dLen2 = ( ptInt2 - ptStSeg) * vtSegDir ;
|
||||
// Se la prima intersezione supera la fine o la seconda viene prima dell'inizio, non ci sono intersezioni
|
||||
if ( dLen1 > dSegLen + EPS_ZERO || dLen2 < -EPS_ZERO)
|
||||
return 0 ;
|
||||
// Eventuale aggiustamento inizio
|
||||
if ( dLen1 > 0.) {
|
||||
ptStSeg = ptInt1 ;
|
||||
dSegLen -= dLen1 ;
|
||||
dLen2 -= dLen1 ;
|
||||
}
|
||||
// Eventuale aggiustamento fine
|
||||
if ( dLen2 < dSegLen) {
|
||||
ptEnSeg = ptInt2 ;
|
||||
dSegLen = dLen2 ;
|
||||
}
|
||||
// Assegno il tipo di intersezione
|
||||
return ( dSegLen > dTol ? 2 : 1) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
{
|
||||
// La superficie deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// La curva deve essere valida e chiusa, il vettore estrusione deve essere non nullo
|
||||
Vector3d vtExtr ;
|
||||
if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed())
|
||||
return false ;
|
||||
|
||||
// Recupero il numero originale di triangoli e di facce
|
||||
int nTriaOriCnt = GetTriangleCount() ;
|
||||
int nFacetOriCnt = GetFacetCount() ;
|
||||
|
||||
// Approssimo la curva con segmenti
|
||||
CurveComposite cvCompo ;
|
||||
{
|
||||
PolyLine PL ;
|
||||
if ( ! cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || ! cvCompo.FromPolyLine( PL))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Eseguo scalature
|
||||
Frame3d frScalingRef;
|
||||
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
|
||||
Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
|
||||
cvCompo.Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
|
||||
|
||||
// Appiattisco la polilinea nel piano perpendicolare all'estrusione
|
||||
Frame3d frCurve ;
|
||||
Point3d ptStart ; cvCompo.GetStartPoint( ptStart) ;
|
||||
frCurve.Set( ptStart, vtExtr) ;
|
||||
cvCompo.ToLoc( frCurve) ;
|
||||
if ( ! cvCompo.Scale( GLOB_FRM, 1, 1, 0)) {
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
return false ;
|
||||
}
|
||||
double dArea ;
|
||||
cvCompo.GetAreaXY( dArea) ;
|
||||
BBox3d b3Crv ;
|
||||
cvCompo.GetLocalBBox( b3Crv) ;
|
||||
cvCompo.ToGlob( frCurve) ;
|
||||
// Assegno il senso di rotazione della curva (visto dalla punta del vettore estrusione)
|
||||
bool bCCW = ( dArea > 0) ;
|
||||
|
||||
// Recupero Bounding-box della trimesh
|
||||
BBox3d b3SurfBox ;
|
||||
GetLocalBBox( b3SurfBox) ;
|
||||
// Trovo minima e massima distanza dei vertici del bounding-box della TriMesh dal piano della curva
|
||||
b3SurfBox.ToLoc( frCurve) ;
|
||||
Point3d ptMin, ptMax ;
|
||||
b3SurfBox.GetMinMax( ptMin, ptMax) ;
|
||||
Vector3d vtMax = ( ptMax.z + 10) * vtExtr ;
|
||||
Vector3d vtMin = ( ptMin.z - 10) * vtExtr ;
|
||||
|
||||
// Ciclo sui triangoli
|
||||
bool bModif = false ;
|
||||
int nNumTria = GetTriangleSize() ;
|
||||
for ( int nT = 0 ; nT < nNumTria ; ++ nT) {
|
||||
// Recupero il triangolo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria))
|
||||
continue ;
|
||||
// Box del triangolo nel riferimento locale della curva
|
||||
BBox3d b3Tria ;
|
||||
trTria.GetLocalBBox( b3Tria) ;
|
||||
b3Tria.ToLoc( frCurve) ;
|
||||
// Se il box del triangolo non interseca quello locale della curva
|
||||
if ( ! b3Crv.OverlapsXY( b3Tria)) {
|
||||
// Se la parte da conservare è quella all'interno della curva, elimino il triangolo
|
||||
if ( bCCW) {
|
||||
RemoveTriangle( nT) ;
|
||||
bModif = true ;
|
||||
}
|
||||
continue ;
|
||||
}
|
||||
// Determino se il centro del triangolo cade all'interno della curva
|
||||
bool bTriaCenIn = false ;
|
||||
{
|
||||
// centro proiettato sul piano della curva
|
||||
Point3d ptCen = trTria.GetCentroid() ;
|
||||
ptCen = ptCen - ( ptCen - ptStart) * vtExtr * vtExtr ;
|
||||
// calcolo distanza
|
||||
DistPointCurve dstPC( ptCen, cvCompo) ;
|
||||
double dDist ; dstPC.GetDist( dDist) ;
|
||||
// se maggiore oltre il limite originale
|
||||
if ( dDist > CUT_SCALE * EPS_SMALL) {
|
||||
int nSide ;
|
||||
if ( dstPC.GetSideAtMinDistPoint( 0, vtExtr, nSide))
|
||||
bTriaCenIn = ( nSide == MDS_LEFT) ;
|
||||
}
|
||||
// altrimenti ricalcolo con centro del triangolo spostato all'interno sulla normale
|
||||
else {
|
||||
Point3d ptCen2 = trTria.GetCentroid() - CUT_SCALE * EPS_SMALL * trTria.GetN() ;
|
||||
DistPointCurve dstP2C( ptCen2, cvCompo) ;
|
||||
int nSide2 ;
|
||||
if ( dstP2C.GetSideAtMinDistPoint( 0, vtExtr, nSide2))
|
||||
bTriaCenIn = ( nSide2 == MDS_LEFT && bSaveOnEq) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Vettore di catene di punti e flag sulla complanarità del triangolo con uno dei rettangoli
|
||||
CHAINVECTOR vChain ;
|
||||
bool bTriaOn = false ;
|
||||
// Segnalatore di taglio piccolo, punto e vettore per costruire il piano per eseguirlo
|
||||
int nSmallCutState = 0 ;
|
||||
Point3d ptSmallCutPnt ;
|
||||
Vector3d vtSmallCutVec ;
|
||||
// Ciclo sui segmenti
|
||||
int nChainCnt = 0 ;
|
||||
bool bChain = false ;
|
||||
Point3d ptChSt, ptChEn ;
|
||||
const ICurve* pCrv = cvCompo.GetFirstCurve() ;
|
||||
while ( pCrv != nullptr) {
|
||||
// estremi del segmento
|
||||
Point3d ptSt ; pCrv->GetStartPoint( ptSt) ;
|
||||
Point3d ptEn ; pCrv->GetEndPoint( ptEn) ;
|
||||
// Se il segmento giace sul piano del triangolo, lo segnalo.
|
||||
if ( abs( ( ptSt - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
|
||||
abs( ( ptEn - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
|
||||
abs( trTria.GetN() * vtExtr) < EPS_SMALL)
|
||||
bTriaOn = true ;
|
||||
// Intersezione fra il rettangolo (ottenuto dall'estrusione del segmento corrente) e il triangolo
|
||||
Point3d ptSegSt, ptSegEn ;
|
||||
int nInt = IntersRectangleTriangle( ptSt + vtMin, ptEn - ptSt, vtMax - vtMin, trTria, ptSegSt, ptSegEn) ;
|
||||
if ( nInt == 2) {
|
||||
// Creo nuova catena se non c'è già o se discontinuità
|
||||
if ( ! bChain || ( ! AreSamePointApprox( ptSegSt, ptChEn) && ! AreSamePointApprox( ptSegEn, ptChSt))) {
|
||||
++ nChainCnt ;
|
||||
vChain.resize( nChainCnt) ;
|
||||
bChain = false ;
|
||||
}
|
||||
// Assegno i dati di intersezione
|
||||
IntSegment CurInters ;
|
||||
CurInters.ptSt = ptSegSt ;
|
||||
CurInters.ptEn = ptSegEn ;
|
||||
// Inserisco nella catena
|
||||
if ( ! bChain) {
|
||||
vChain[nChainCnt - 1].emplace_back( CurInters) ;
|
||||
ptChSt = CurInters.ptSt ;
|
||||
ptChEn = CurInters.ptEn ;
|
||||
}
|
||||
else if ( AreSamePointApprox(ptSegSt, ptChEn)) {
|
||||
vChain[nChainCnt - 1].emplace_back(CurInters) ;
|
||||
ptChEn = CurInters.ptEn ;
|
||||
}
|
||||
else {
|
||||
vChain[nChainCnt - 1].insert(vChain[nChainCnt - 1].begin(), CurInters) ;
|
||||
ptChSt = CurInters.ptSt ;
|
||||
}
|
||||
bChain = true ;
|
||||
}
|
||||
else {
|
||||
// Taglio piccolo
|
||||
if ( nInt == 1) {
|
||||
if ( nSmallCutState == 0)
|
||||
nSmallCutState = 1 ;
|
||||
else
|
||||
nSmallCutState = 2 ;
|
||||
ptSmallCutPnt = ptSt ;
|
||||
vtSmallCutVec = ptEn - ptSt ;
|
||||
}
|
||||
bChain = false ;
|
||||
}
|
||||
pCrv = cvCompo.GetNextCurve() ;
|
||||
}
|
||||
// Gestisco il taglio piccolo.
|
||||
if ( nSmallCutState == 1 && int( vChain.size()) == 0) {
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptSmallCutPnt, vtSmallCutVec ^ ( vtMax - vtMin)) ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
double dDist = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nV]].ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL) {
|
||||
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = 0 ;
|
||||
if ( abs( dDist) > EPS_SMALL)
|
||||
m_vVert[m_vTria[nT].nIdVert[nV]].ptP -= plPlane.GetVersN() * dDist ;
|
||||
}
|
||||
else if ( dDist > 0)
|
||||
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = +1 ;
|
||||
else
|
||||
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = -1 ;
|
||||
}
|
||||
CutTriangleByPlane( nT, plPlane, bSaveOnEq, bModif) ;
|
||||
continue ;
|
||||
}
|
||||
for ( auto itI = vChain.begin() ; itI != vChain.end() ; ) {
|
||||
bool bErased = false ;
|
||||
auto itJ = itI ;
|
||||
++ itJ ;
|
||||
for ( ; itJ != vChain.end() && ! bErased ; ) {
|
||||
if ( int( itI->size()) == 1 && int( itJ->size()) == 1 &&
|
||||
AreSamePointEpsilon( itI->back().ptSt, itJ->back().ptEn, 2 * EPS_SMALL) &&
|
||||
AreSamePointEpsilon( itI->back().ptEn, itJ->back().ptSt, 2 * EPS_SMALL)) {
|
||||
itJ = vChain.erase( itJ) ;
|
||||
bErased = true ;
|
||||
}
|
||||
else
|
||||
++ itJ ;
|
||||
}
|
||||
if ( bErased) {
|
||||
itI = vChain.erase( itI) ;
|
||||
bErased = false ;
|
||||
}
|
||||
else
|
||||
++ itI ;
|
||||
}
|
||||
nChainCnt = int( vChain.size()) ;
|
||||
|
||||
// unisco eventuali catene estreme che sono parte di una stessa catena
|
||||
if ( nChainCnt > 1) {
|
||||
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
|
||||
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
|
||||
vChain.pop_back() ;
|
||||
-- nChainCnt ;
|
||||
}
|
||||
else if ( AreSamePointApprox( vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) {
|
||||
vChain[0].insert(vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
|
||||
vChain.pop_back() ;
|
||||
-- nChainCnt ;
|
||||
}
|
||||
}
|
||||
|
||||
// Elimino la seconda copia di catene doppie
|
||||
for ( int nI = 0 ; nI < nChainCnt ; ++ nI) {
|
||||
for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) {
|
||||
if ( vChain[nI].size() == vChain[nJ].size()) {
|
||||
bool bSame = true ;
|
||||
for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) {
|
||||
if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) ||
|
||||
! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bSame) {
|
||||
vChain.erase( vChain.begin() + nJ) ;
|
||||
-- nChainCnt ;
|
||||
-- nJ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fra le catene trovate separo le aperte dalle chiuse
|
||||
CHAINVECTOR cvClosedChain ;
|
||||
CHAINVECTOR cvOpenChain ;
|
||||
for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) {
|
||||
int nCurLoopLast = max( int(vChain[nL].size()) - 1, 0) ;
|
||||
if ( AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn) && nCurLoopLast > 0)
|
||||
cvClosedChain.emplace_back( vChain[nL]) ;
|
||||
else {
|
||||
cvOpenChain.emplace_back( vChain[nL]) ;
|
||||
}
|
||||
}
|
||||
for ( auto it = cvClosedChain.begin() ; it != cvClosedChain.end() ; ) {
|
||||
if ( int( it->size()) < 3)
|
||||
it = cvClosedChain.erase( it) ;
|
||||
else
|
||||
++ it ;
|
||||
}
|
||||
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
|
||||
if ( cvClosedChain.size() > 1 || ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > 0)) {
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Se c'è una catena chiusa
|
||||
if ( cvClosedChain.size() == 1) {
|
||||
// Ne ricavo una PolyLine
|
||||
PolyLine plInLoop ;
|
||||
for ( int nLine = 0 ; nLine < int( cvClosedChain[0].size()) ; ++ nLine) {
|
||||
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptSt) ;
|
||||
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptEn) ;
|
||||
}
|
||||
// I tre vertici sono dalla parte interna della curva (triangolo con buco)
|
||||
if ( ! bCCW) {
|
||||
// Rimuovo il triangolo corrente
|
||||
RemoveTriangle( nT) ;
|
||||
// Definisco il loop esterno (è il triangolo)
|
||||
PolyLine plExtLoop ;
|
||||
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
|
||||
plExtLoop.AddUPoint( 0., trTria.GetP( 1)) ;
|
||||
plExtLoop.AddUPoint( 0., trTria.GetP( 2)) ;
|
||||
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
|
||||
// Eseguo triangolazione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.emplace_back( plExtLoop) ;
|
||||
vPL.emplace_back( plInLoop) ;
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( vPL, vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
||||
int nNewId[3] = { AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
AddVertex( vPt[nNewTriaVertId[1]]),
|
||||
AddVertex( vPt[nNewTriaVertId[2]]) } ;
|
||||
AddTriangle( nNewId) ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se nessun vertice dalla parte interna della curva (rimane solo l'area della curva)
|
||||
else {
|
||||
// Rimuovo il triangolo corrente
|
||||
RemoveTriangle( nT) ;
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( plInLoop, vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
||||
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
|
||||
AddVertex(vPt[nNewTriaVertId[1]]),
|
||||
AddVertex(vPt[nNewTriaVertId[2]]) } ;
|
||||
AddTriangle( nNewId) ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop aperti, devo chiuderli
|
||||
else if ( cvOpenChain.size() > 0) {
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
|
||||
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
|
||||
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
|
||||
// chiusi di cui è formato il perimetro.
|
||||
PNTVECTOR cvFirstLoop ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
|
||||
|
||||
PNTMATRIX cvBoundClosedLoopVec ;
|
||||
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
|
||||
BOOLVECTOR vbInOut ;
|
||||
vbInOut.push_back( true) ;
|
||||
// Divido il loop di partenza in sotto-loop
|
||||
while ( cvOpenChain.size() > 0) {
|
||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
|
||||
// Estremi del loop aperto
|
||||
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
|
||||
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
|
||||
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
|
||||
PNTVECTOR Loop1, Loop2 ;
|
||||
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
|
||||
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
|
||||
if ( ! ( bChangedStart && bSplitted))
|
||||
continue ;
|
||||
Chain cvCounterChain ;
|
||||
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
|
||||
IntSegment CurSeg ;
|
||||
CurSeg.ptSt = cvOpenChain[nLastOpenLoopN][nPt].ptEn ;
|
||||
CurSeg.ptEn = cvOpenChain[nLastOpenLoopN][nPt].ptSt ;
|
||||
cvCounterChain.emplace_back( CurSeg) ;
|
||||
}
|
||||
bool bAdded1 = AddChainToChain( cvCounterChain, Loop1) ;
|
||||
bool bAdded2 = AddChainToChain( cvOpenChain[nLastOpenLoopN], Loop2) ;
|
||||
if ( ! ( bAdded1 && bAdded2))
|
||||
continue ;
|
||||
// Aggiungo i nuovi loop nel vettore
|
||||
int nCurSize = int( cvBoundClosedLoopVec.size()) ;
|
||||
cvBoundClosedLoopVec.resize( nCurSize + 1) ;
|
||||
vbInOut.resize( nCurSize + 1) ;
|
||||
for ( int nCL = nCurSize - 1 ; nCL > nLoop ; -- nCL) {
|
||||
cvBoundClosedLoopVec[nCL + 1] = cvBoundClosedLoopVec[nCL] ;
|
||||
vbInOut[nCL + 1] = vbInOut[nCL] ;
|
||||
}
|
||||
cvBoundClosedLoopVec[nLoop] = Loop1 ;
|
||||
cvBoundClosedLoopVec[nLoop + 1] = Loop2 ;
|
||||
vbInOut[nLoop] = false ;
|
||||
vbInOut[nLoop + 1] = true ;
|
||||
++ nLoop ;
|
||||
}
|
||||
cvOpenChain.resize( nLastOpenLoopN) ;
|
||||
}
|
||||
// Rimuovo il triangolo corrente
|
||||
RemoveTriangle( nT) ;
|
||||
// Se il triangolo originale aveva il centro interno alla curva oppure devo tenere le parti
|
||||
// di superficie che hanno una parte giacente sul rettangolo della superficie di taglio,
|
||||
// aggiungo i nuovi triangoli.
|
||||
if ( ! bTriaOn || bSaveOnEq) {
|
||||
// Trasformo i loop compositi in loop polyline
|
||||
POLYLINEVECTOR vplPolyVec ;
|
||||
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
|
||||
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
|
||||
}
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
|
||||
if ( vbInOut[nLoop]) {
|
||||
// Eseguo triangolazione
|
||||
Triangulate CreateTriangulation ;
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( vplPolyVec[nLoop], vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
|
||||
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
|
||||
AddVertex(vPt[nNewTriaVertId[1]]),
|
||||
AddVertex(vPt[nNewTriaVertId[2]]) } ;
|
||||
AddTriangle( nNewId) ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// da eliminare
|
||||
else if ( ! bTriaCenIn) {
|
||||
RemoveTriangle( nT) ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se avvenuta modifica, aggiorno tutto
|
||||
if ( bModif) {
|
||||
// aggiorno tutto
|
||||
if ( ! AdjustVertices() || ! DoCompacting()) {
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ripristino scala originale
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
|
||||
// se superficie originale a facce, cerco di semplificarle in ogni caso
|
||||
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
|
||||
if ( ! SimplifyFacets())
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::GeneralizedCut")
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
+67
-41
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//
|
||||
// Modifiche : 26.03.14 DS Creazione modulo.
|
||||
// 15.05.14 DS Corr. errore CreateByTwoCurves che dava loop infinito.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -22,15 +22,6 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::ResetFaceting( void)
|
||||
{
|
||||
m_bFaceted = false ;
|
||||
m_vFacet.clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::VerifyFaceting( void) const
|
||||
@@ -44,14 +35,36 @@ SurfTriMesh::VerifyFaceting( void) const
|
||||
bool
|
||||
SurfTriMesh::UpdateFaceting( void)
|
||||
{
|
||||
// salvo vecchio vettore facce
|
||||
INTVECTOR vOldFacet = m_vFacet ;
|
||||
|
||||
// reset faceting
|
||||
m_bFaceted = false ;
|
||||
m_vFacet.clear() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
|
||||
m_vTria[i].nIdFacet = SVT_NULL ;
|
||||
|
||||
// ricostruisco le sfaccettature
|
||||
bool bOk = true ;
|
||||
// indice faccia corrente
|
||||
int nFacet = -1 ;
|
||||
|
||||
// ricostruisco le sfaccettature come definite in precedenza (dove possibile)
|
||||
bool bOk = true ;
|
||||
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
|
||||
int i = vOldFacet[j] ;
|
||||
// salto triangoli inesistenti o già assegnati
|
||||
if ( i >= int( m_vTria.size()) ||
|
||||
m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nIdFacet != SVT_NULL)
|
||||
continue ;
|
||||
// assegno indice di faccia al triangolo
|
||||
m_vTria[i].nIdFacet = ++ nFacet ;
|
||||
m_vFacet.push_back( i) ;
|
||||
// aggiorno faccia
|
||||
if ( ! UpdateOneFace( nFacet, i))
|
||||
bOk = false ;
|
||||
}
|
||||
|
||||
// ricostruisco le altre sfaccettature
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
@@ -60,32 +73,9 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
// assegno indice di faccia al triangolo
|
||||
m_vTria[i].nIdFacet = ++ nFacet ;
|
||||
m_vFacet.push_back( i) ;
|
||||
// piano del triangolo
|
||||
Plane3d plPlane ;
|
||||
if ( ! plPlane.Set( m_vVert[m_vTria[i].nIdVert[0]].ptP, m_vTria[i].vtN)) {
|
||||
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
|
||||
return false ;
|
||||
}
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( i) ;
|
||||
// finchè set non vuoto
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
const auto iIt = stTria.begin() ;
|
||||
int nT = *iIt ;
|
||||
stTria.erase( iIt) ;
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
|
||||
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
|
||||
bOk = false ;
|
||||
if ( m_vTria[nAdjT].nIdFacet == nFacet)
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// aggiorno faccia
|
||||
if ( ! UpdateOneFace( nFacet, i))
|
||||
bOk = false ;
|
||||
}
|
||||
|
||||
// se ci sono stati problemi, salvo nel log
|
||||
@@ -97,6 +87,40 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::UpdateOneFace( int nFacet, int nT)
|
||||
{
|
||||
// piano del triangolo
|
||||
Plane3d plPlane ;
|
||||
if ( ! plPlane.Set( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vTria[nT].vtN)) {
|
||||
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
|
||||
return false ;
|
||||
}
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( nT) ;
|
||||
// finchè set non vuoto
|
||||
bool bOk = true ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
const auto iIt = stTria.begin() ;
|
||||
int nT = *iIt ;
|
||||
stTria.erase( iIt) ;
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
|
||||
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
|
||||
bOk = false ;
|
||||
if ( m_vTria[nAdjT].nIdFacet == nFacet)
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT)
|
||||
@@ -458,12 +482,14 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
|
||||
// verifico appartenga alla stessa faccia
|
||||
if ( m_vTria[nAdjT].nIdFacet != nF)
|
||||
return false ;
|
||||
// recupero il suo lato di adiacenza
|
||||
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
|
||||
int nAdjS = SVT_NULL ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
|
||||
nAdjS = i ;
|
||||
break ;
|
||||
if ( nAdjS == SVT_NULL)
|
||||
nAdjS = i ;
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
if ( nAdjS == SVT_NULL)
|
||||
|
||||
+467
-17
@@ -12,13 +12,244 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "Triangulate.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "CurveLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
{
|
||||
bModified = false ;
|
||||
// ciclo sui triangoli
|
||||
int nTriaNum = GetTriangleSize() ;
|
||||
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
|
||||
// se cancellato passo al successivo
|
||||
if ( m_vTria[nT].nIdVert[0] == SVT_DEL)
|
||||
continue ;
|
||||
// recupero i vertici dei triangoli
|
||||
int nIdV[3] ;
|
||||
GetTriangle( nT, nIdV) ;
|
||||
// ciclo sui triangoli adiacenti
|
||||
for ( int nE = 0 ; nE < 3 ; ++ nE) {
|
||||
// recupero triangolo adiacente, se non esiste passo al successivo
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[nE] ;
|
||||
if ( nAdjT == SVT_NULL || nAdjT == SVT_DEL)
|
||||
continue ;
|
||||
// recupero i vertici del triangolo adiacente
|
||||
int nAdjIdV[3] ;
|
||||
GetTriangle( nAdjT, nAdjIdV) ;
|
||||
// verifico se questi vertici coincidono con quelli del triangolo di riferimento
|
||||
int nCoinc = 0 ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
if ( nIdV[i] == nAdjIdV[j])
|
||||
++ nCoinc ;
|
||||
}
|
||||
}
|
||||
if ( nCoinc == 3) {
|
||||
RemoveTriangle( nAdjT) ;
|
||||
bModified = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
{
|
||||
// Verifico esistenza triangoli
|
||||
if ( ! ExistsTriangle( nTA) || ! ExistsTriangle( nTB))
|
||||
return false ;
|
||||
// Verifico adiacenza triangoli
|
||||
int nEdgeA ;
|
||||
for ( nEdgeA = 0 ; nEdgeA < 3 ; ++ nEdgeA) {
|
||||
if ( m_vTria[nTA].nIdAdjac[nEdgeA] == nTB)
|
||||
break ;
|
||||
}
|
||||
int nEdgeB ;
|
||||
for ( nEdgeB = 0 ; nEdgeB < 3 ; ++ nEdgeB) {
|
||||
if ( m_vTria[nTB].nIdAdjac[nEdgeB] == nTA)
|
||||
break ;
|
||||
}
|
||||
// Se non sono adiacenti tra loro, impossibile flip
|
||||
if ( nEdgeA == 3 && nEdgeB == 3)
|
||||
return false ;
|
||||
// Recupero i vertici del triangolo A
|
||||
Point3d ptSegSt, ptSegEn, ptVertA ;
|
||||
if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
|
||||
return false ;
|
||||
// Recupero il vertice opposto del triangolo B
|
||||
Point3d ptVertB ;
|
||||
if ( ! GetVertex( m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3], ptVertB))
|
||||
return false ;
|
||||
// Verifico se possibile il flip (le diagonali del quadrilatero si intersecano internamente)
|
||||
DistLineLine DiagDist( ptSegSt, ptSegEn, ptVertA, ptVertB) ;
|
||||
if ( ! DiagDist.IsSmall())
|
||||
return false ;
|
||||
double dPos1, dPos2 ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) ||
|
||||
dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL ||
|
||||
dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL)
|
||||
return false ;
|
||||
// Eseguo il flipping
|
||||
m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
{
|
||||
bModified = false ;
|
||||
|
||||
// Vettore di indici dei vertici sui lati del triangolo corrente
|
||||
unordered_map< int, INTVECTOR> TriaMap ;
|
||||
|
||||
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
|
||||
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
continue ;
|
||||
// Vettore degli altri vertici sul contorno del triangolo
|
||||
INTVECTOR vVertOtl ;
|
||||
// Box del triangolo
|
||||
BBox3d b3Tria ;
|
||||
trTria.GetLocalBBox( b3Tria) ;
|
||||
INTVECTOR vNearTria ;
|
||||
GetAllTriaOverlapBox( b3Tria, vNearTria) ;
|
||||
// Ciclo sui lati del triangolo
|
||||
for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) {
|
||||
// aggiungo al vettore il vertice iniziale del lato
|
||||
vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ;
|
||||
// Se in questo lato il triangolo è adiacente a un altro, lo salto.
|
||||
if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL)
|
||||
continue ;
|
||||
int nPrevSize = int( vVertOtl.size()) ;
|
||||
// recupero la geometria del lato
|
||||
Point3d ptSegSt = trTria.GetP( nSeg) ;
|
||||
Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ;
|
||||
Vector3d vtSeg = ptSegEn - ptSegSt ;
|
||||
double dSegLen = vtSeg.Len() ;
|
||||
if ( dSegLen < EPS_SMALL)
|
||||
continue ;
|
||||
vtSeg /= dSegLen ;
|
||||
// Ciclo sui triangoli vicini
|
||||
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
|
||||
// Salto il triangolo se è quello di riferimento
|
||||
if ( vNearTria[nI] == nT)
|
||||
continue ;
|
||||
// Cerco i vertici che stanno sul lato del triangolo
|
||||
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
|
||||
Point3d ptVert ;
|
||||
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
|
||||
continue ;
|
||||
double dProj = ( ptVert - ptSegSt) * vtSeg ;
|
||||
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
|
||||
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H)
|
||||
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
|
||||
}
|
||||
}
|
||||
// Riordino i vertici sul segmento
|
||||
auto SortVertices = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2)
|
||||
{ Point3d ptV1, ptV2 ;
|
||||
GetVertex( nV1, ptV1) ;
|
||||
GetVertex( nV2, ptV2) ;
|
||||
return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ;
|
||||
} ;
|
||||
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVertices) ;
|
||||
}
|
||||
// Se ci sono più di 3 vertici
|
||||
if ( vVertOtl.size() > 3) {
|
||||
// Elimino i vertici ripetuti
|
||||
vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ;
|
||||
// Se ci sono ancora più di 3 vertici, inserisco nel Map
|
||||
if ( vVertOtl.size() > 3)
|
||||
TriaMap.emplace( nT, vVertOtl) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ciclo sui triangoli da sistemare
|
||||
for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) {
|
||||
// Indice del triangolo
|
||||
int nT = itT->first ;
|
||||
// Vettore degli altri vertici sul perimetro
|
||||
const INTVECTOR& vVertOtl = itT->second ;
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
continue ;
|
||||
// Salvo eventuale indice di faccetta
|
||||
int nFacet = m_vTria[nT].nIdFacet ;
|
||||
if ( nFacet > int( m_vFacet.size()) || m_vFacet[nFacet] != nT)
|
||||
nFacet = SVT_NULL ;
|
||||
// Rimuovo il triangolo
|
||||
int nTFlag = m_vTria[nT].nTFlag ;
|
||||
RemoveTriangle( nT) ;
|
||||
bModified = true ;
|
||||
// Aggiungo i nuovi triangoli
|
||||
int nLastNewTria = SVT_NULL ;
|
||||
// Se ci sono 4 vertici, inserisco due triangoli
|
||||
if ( vVertOtl.size() == 4) {
|
||||
// se 1-2-3 è triangolo (e quindi 0-1-3)
|
||||
int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ;
|
||||
int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ;
|
||||
if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) {
|
||||
nLastNewTria = nNew1Tria ;
|
||||
int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ;
|
||||
int nNew2Tria = AddTriangle( nNew2Id, nTFlag) ;
|
||||
if ( nNew2Tria != SVT_NULL && nNew2Tria != SVT_DEL)
|
||||
nLastNewTria = nNew2Tria ;
|
||||
}
|
||||
// altrimenti 0-1-2 e 2-3-0
|
||||
else {
|
||||
int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ;
|
||||
int nNew3Tria = AddTriangle( nNew3Id, nTFlag) ;
|
||||
if ( nNew3Tria != SVT_NULL && nNew3Tria != SVT_DEL)
|
||||
nLastNewTria = nNew3Tria ;
|
||||
int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ;
|
||||
int nNew4Tria = AddTriangle( nNew4Id, nTFlag) ;
|
||||
if ( nNew4Tria != SVT_NULL && nNew4Tria != SVT_DEL)
|
||||
nLastNewTria = nNew4Tria ;
|
||||
}
|
||||
}
|
||||
// altrimenti inserisco un ventaglio di triangoli dal centro ai vertici
|
||||
else {
|
||||
Point3d ptTriaCen = trTria.GetCentroid() ;
|
||||
int nCenIndex = AddVertex( ptTriaCen) ;
|
||||
int nVertNum = int( vVertOtl.size()) ;
|
||||
for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) {
|
||||
int nEnV = ( nStV + 1) % nVertNum ;
|
||||
int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ;
|
||||
int nNewTria = AddTriangle( nNewId, nTFlag) ;
|
||||
if ( nNewTria != SVT_NULL && nNewTria != SVT_DEL)
|
||||
nLastNewTria = nNewTria ;
|
||||
}
|
||||
}
|
||||
// Eventuale aggiustamento per indice di faccetta
|
||||
if ( nFacet != SVT_NULL && nLastNewTria != SVT_NULL)
|
||||
m_vFacet[nFacet] = nLastNewTria ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)
|
||||
@@ -57,6 +288,9 @@ ChooseGoodStartPoint( PNTULIST& PointList)
|
||||
// altrimenti cerco il vertice più vicino
|
||||
for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) {
|
||||
if ( IsVertex( PointList, it)) {
|
||||
// se ultimo punto non devo fare alcunché
|
||||
if ( next( it) == PointList.end())
|
||||
return false ;
|
||||
// cancello ultimo punto ( coincide con primo)
|
||||
PointList.pop_back() ;
|
||||
// sposto la parte iniziale dei punti alla fine
|
||||
@@ -160,13 +394,13 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
{
|
||||
// La trimesh deve essere valida
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla, non devo fare alcunché
|
||||
if ( dMaxEdgeLen < EPS_SMALL)
|
||||
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
|
||||
if ( dMaxEdgeLen < EPS_SMALL && ! bForced)
|
||||
return true ;
|
||||
|
||||
// Recupero il numero delle facce (esegue anche una verifica delle stesse)
|
||||
@@ -175,13 +409,13 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
|
||||
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
|
||||
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
|
||||
|
||||
|
||||
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
GetFacetLoops( nF, LoopVec) ;
|
||||
|
||||
// Ciclo sui loop della faccia
|
||||
bool bToRetriangulate = false ;
|
||||
bool bToRetriangulate = bForced ;
|
||||
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL) {
|
||||
|
||||
// Lista dei punti del loop
|
||||
@@ -189,7 +423,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
|
||||
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
|
||||
if ( ! ChooseGoodStartPoint( PointList))
|
||||
return false ;
|
||||
continue ;
|
||||
|
||||
// Sistemo il loop
|
||||
bool bModif = false ;
|
||||
@@ -199,7 +433,24 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
bToRetriangulate = true ;
|
||||
}
|
||||
|
||||
// Se da ritriangolare,
|
||||
// Se non richiesta ritriangolazione dai bordi, verifico se ci sono vertici di triangoli interni (*** disabilitato ***)
|
||||
if ( false && ! bToRetriangulate) {
|
||||
// numero dei triangoli nella faccia
|
||||
INTVECTOR vFacetTria ;
|
||||
GetAllTriaInFacet( nF, vFacetTria) ;
|
||||
int nTriaCnt = int( vFacetTria.size()) ;
|
||||
// numero dei lati di contorno della faccia
|
||||
int nSideCnt = 0 ;
|
||||
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL)
|
||||
nSideCnt += LoopVec[nL].GetLineNbr() ;
|
||||
// numero dei buchi della faccia
|
||||
int nHoleCnt = int( LoopVec.size()) - 1 ;
|
||||
// dalla formula di Eulero adattata al caso ( nTriaCnt = nSideCnt + 2 * ( nHoleCnt - 1))
|
||||
if ( nTriaCnt != nSideCnt + 2 * ( nHoleCnt - 1))
|
||||
bToRetriangulate = true ;
|
||||
}
|
||||
|
||||
// Se da ritriangolare
|
||||
if ( bToRetriangulate) {
|
||||
// Eseguo la ritriangolazione della faccia
|
||||
PNTVECTOR vPt ;
|
||||
@@ -214,33 +465,43 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
}
|
||||
|
||||
// Ciclo sulle facce da ritriangolare per eliminare i triangoli (nel contempo salvo flag colore)
|
||||
INTVECTOR vDelTria ;
|
||||
unordered_map< int, int> ColorMap ;
|
||||
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
|
||||
// Recupero i triangoli della faccia
|
||||
INTVECTOR vFacetTria ;
|
||||
GetAllTriaInFacet( itF->first, vFacetTria) ;
|
||||
vDelTria.insert( vDelTria.end(), vFacetTria.begin(), vFacetTria.end()) ;
|
||||
// Salvo il colore della faccia da flag di un suo triangolo
|
||||
ColorMap.emplace( itF->first, m_vTria[m_vFacet[itF->first]].nTFlag) ;
|
||||
// Cancello i triangoli della faccia.
|
||||
for ( int nT : vFacetTria)
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
|
||||
// Cancello i triangoli
|
||||
for ( int nT : vDelTria)
|
||||
RemoveTriangle( nT) ;
|
||||
|
||||
// Applico le nuove triangolazioni delle facce
|
||||
for ( auto itFac = FacetMap.begin() ; itFac != FacetMap.end() ; ++ itFac) {
|
||||
const PNTVECTOR& vPt = itFac->second.first ;
|
||||
const INTVECTOR& vTr = itFac->second.second ;
|
||||
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
|
||||
const PNTVECTOR& vPt = itF->second.first ;
|
||||
const INTVECTOR& vTr = itF->second.second ;
|
||||
// Inserisco i nuovi triangoli
|
||||
bool bFirstTria = true ;
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
auto itCol = ColorMap.find( itFac->first) ;
|
||||
auto itCol = ColorMap.find( itF->first) ;
|
||||
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
|
||||
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
|
||||
if ( nNewTriaId != SVT_NULL && nNewTriaId != SVT_DEL) {
|
||||
m_vTria[nNewTriaId].nIdFacet = itF->first ;
|
||||
if ( bFirstTria) {
|
||||
m_vFacet[itF->first] = nNewTriaId ;
|
||||
bFirstTria = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
@@ -248,3 +509,192 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen)
|
||||
// Eseguo aggiustamenti
|
||||
return ( AdjustVertices() && DoCompacting()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
|
||||
{
|
||||
// Se la catena da aggiungere è vuota, non devo fare alcunchè
|
||||
if ( ChainToAdd.size() == 0)
|
||||
return true ;
|
||||
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
||||
if ( OrigChain.size() == 0)
|
||||
return false ;
|
||||
// Se la catena originale è chiusa non posso aggiungere nulla
|
||||
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
|
||||
if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig]))
|
||||
return false ;
|
||||
int nLastToAdd = max( int( ChainToAdd.size()) - 1, 0) ;
|
||||
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
|
||||
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
|
||||
if ( nPt == nLastToAdd) {
|
||||
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
|
||||
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
|
||||
}
|
||||
else if ( nPt == 1) {
|
||||
if ( ! AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[nPt].ptSt))
|
||||
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
|
||||
}
|
||||
else
|
||||
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Una faccia di una trimesh ha una sola componente connessa, con un loop esterno e possibili loop interni
|
||||
bool
|
||||
SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist)
|
||||
{
|
||||
// Verifico la presenza del loop esterno
|
||||
if ( vPolyVec.size() < 1)
|
||||
return false ;
|
||||
// Proietto il punto sul piano della faccia, utilizzando il loop esterno
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPolyVec[0].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
double dDistPtPl = DistPointPlane( ptP, plPlane) ;
|
||||
Point3d ptProjP = ptP + dDistPtPl * plPlane.GetVersN() ;
|
||||
// Verifico se il punto proiettato è esterno al loop esterno
|
||||
int nPtOut = -1 ;
|
||||
if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL))
|
||||
nPtOut = 0 ;
|
||||
// Verifico se il punto proiettato è interno ai loop interni (quindi esterno alla faccia)
|
||||
for ( int nLoop = 1 ; nLoop < int( vPolyVec.size()) && nPtOut < 0 ; ++ nLoop) {
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPolyVec[nLoop].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
if ( IsPointInsidePolyLine( ptProjP, vPolyVec[nLoop], EPS_SMALL))
|
||||
nPtOut = nLoop ;
|
||||
}
|
||||
// Se il punto si proietta sulla faccia, la distanza dalla faccia coincide con quella dal piano
|
||||
if ( nPtOut < 0) {
|
||||
dPointFacetDist = abs( dDistPtPl) ;
|
||||
return true ;
|
||||
}
|
||||
// Altrimenti calcolo la minima distanza del punto dalla polilinea del contorno a cui è esterno
|
||||
double dDist ;
|
||||
if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) {
|
||||
dPointFacetDist = dDist ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
|
||||
{
|
||||
// Cerco il tratto del loop chiuso più vicino al punto
|
||||
int nMinSeg = - 1 ;
|
||||
double dMinSqDinst = DBL_MAX ;
|
||||
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
|
||||
// Estremi del segmento corrente del loop
|
||||
Point3d ptSegSt = Loop[nPt] ;
|
||||
Point3d ptSegEn = Loop[( nPt + 1) % int( Loop.size())] ;
|
||||
// Distanza del punto dal segmento del loop
|
||||
DistPointLine dDistCalc( ptNewStart, ptSegSt, ptSegEn) ;
|
||||
double dSqDist ;
|
||||
dDistCalc.GetSqDist( dSqDist) ;
|
||||
if ( dSqDist < dMinSqDinst) {
|
||||
dMinSqDinst = dSqDist ;
|
||||
nMinSeg = nPt ;
|
||||
}
|
||||
}
|
||||
// Se il punto non sta sul loop, errore
|
||||
if ( dMinSqDinst > SQ_EPS_SMALL)
|
||||
return false ;
|
||||
// Verifico che il punto stia su un vertice, in tal caso non devo fare nulla
|
||||
bool bOnStart = AreSamePointApprox( Loop[nMinSeg], ptNewStart) ;
|
||||
bool bOnEnd = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptNewStart) ;
|
||||
if ( bOnStart || bOnEnd) {
|
||||
if ( bOnEnd) {
|
||||
++ nMinSeg ;
|
||||
if ( nMinSeg % int( Loop.size()) == 0)
|
||||
return true ;
|
||||
}
|
||||
PNTVECTOR vTempVec ;
|
||||
for ( int nPt = 0 ; nPt < nMinSeg ; ++ nPt)
|
||||
vTempVec.emplace_back( Loop[nPt]) ;
|
||||
int nSize = int( Loop.size()) ;
|
||||
for ( int nPt = 0 ; nPt < nSize - nMinSeg ; ++ nPt) {
|
||||
Loop[nPt] = Loop[nPt + nMinSeg] ;
|
||||
}
|
||||
for ( int nPt = 0 ; nPt < int( vTempVec.size()) ; ++ nPt) {
|
||||
Loop[nPt + nSize - nMinSeg] = vTempVec[nPt] ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
// Ridimensiono il loop
|
||||
Loop.resize( Loop.size() + 1) ;
|
||||
// Copio i primi punti
|
||||
PNTVECTOR LoopTemp ;
|
||||
for ( int nPt = 0 ; nPt <= nMinSeg ; ++ nPt)
|
||||
LoopTemp.emplace_back( Loop[nPt]) ;
|
||||
// Aggiungo il nuovo punto all'inizio
|
||||
Loop[0] = ptNewStart ;
|
||||
// Sposto gli ultimi in testa
|
||||
int nLastPointNum = int( Loop.size()) - 1 - nMinSeg ;
|
||||
for ( int nPt = 1 ; nPt <= nLastPointNum ; ++ nPt) {
|
||||
Loop[nPt] = Loop[nPt + nMinSeg] ;
|
||||
}
|
||||
// Porto i primi in fondo
|
||||
for ( int nPt = 0 ; nPt < int( LoopTemp.size()) ; ++ nPt) {
|
||||
Loop[nPt + nLastPointNum] = LoopTemp[nPt] ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2)
|
||||
{
|
||||
// Cerco il tratto del loop chiuso più vicino al punto
|
||||
int nMinSeg = -1 ;
|
||||
double dMinSqDinst = DBL_MAX ;
|
||||
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
|
||||
// Estremi del segmento corrente del loop
|
||||
Point3d ptSegSt = Loop[nPt] ;
|
||||
Point3d ptSegEn = Loop[( nPt + 1) % int(Loop.size())] ;
|
||||
// Distanza del punto dal segmento del loop
|
||||
DistPointLine dDistCalc( ptStop, ptSegSt, ptSegEn) ;
|
||||
double dSqDist ;
|
||||
dDistCalc.GetSqDist( dSqDist) ;
|
||||
if ( dSqDist < dMinSqDinst) {
|
||||
dMinSqDinst = dSqDist ;
|
||||
nMinSeg = nPt ;
|
||||
}
|
||||
}
|
||||
// Se il punto non sta sul loop, errore
|
||||
if ( dMinSqDinst > SQ_EPS_SMALL)
|
||||
return false ;
|
||||
// Verifico che il punto stia su un vertice, in tal caso non devo aggiungerlo
|
||||
bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ;
|
||||
bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ;
|
||||
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
|
||||
if ( bLast)
|
||||
++ nMinSeg ;
|
||||
// Inglobo fino a nSeg nel primo loop
|
||||
for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt)
|
||||
Loop1.emplace_back( Loop[nPt]) ;
|
||||
// Se il punto è interno al segmento, lo inglobo in entrambi i loop
|
||||
if ( ! ( bFirst || bLast)) {
|
||||
Loop1.emplace_back( ptStop) ;
|
||||
Loop2.emplace_back( ptStop) ;
|
||||
}
|
||||
else {
|
||||
if ( nMinSeg != int( Loop.size()) )
|
||||
Loop2.emplace_back( Loop[nMinSeg]) ;
|
||||
}
|
||||
// Inglobo gli ultimi vertici in Loop2
|
||||
for ( int nPt = nMinSeg + 1 ; nPt < int( Loop.size()) ; ++ nPt)
|
||||
Loop2.emplace_back( Loop[nPt]) ;
|
||||
Loop2.emplace_back( Loop[0]) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
#include "GeomDB.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgnStringKeyVal.h"
|
||||
#include "/EgtDev/Include/EGnStringKeyVal.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2018
|
||||
// EgalTech 2015-2022
|
||||
//----------------------------------------------------------------------------
|
||||
// File : Tool.cpp Data : 04.07.18 Versione : 1.9g1
|
||||
// File : Tool.cpp Data : 04.07.18 Versione : 2.4f3
|
||||
// Contenuto : Implementazione della classe Tool
|
||||
//
|
||||
//
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "/EgtDev/Include/EGkFilletChamfer.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -40,8 +41,9 @@ Tool::~Tool( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tool::Clear( void)
|
||||
Tool::Clear( bool bApproxWithLines)
|
||||
{
|
||||
m_bApproxWithLines = bApproxWithLines ;
|
||||
m_dLinTol = LIN_TOL_STD ;
|
||||
m_dAngTolDeg = ANG_TOL_APPROX_DEG ;
|
||||
m_nType = UNDEF ;
|
||||
@@ -129,7 +131,7 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
|
||||
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
|
||||
}
|
||||
// utensile sferico
|
||||
else if ( dCornR < dR + EPS_SMALL) {
|
||||
else {
|
||||
m_nType = BALLMILL ;
|
||||
m_dHeight = dH ;
|
||||
m_dRadius = dR ;
|
||||
@@ -147,9 +149,6 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
|
||||
m_Outline.AddLine( pt2);
|
||||
m_Outline.AddArcTg( pt4) ;
|
||||
}
|
||||
// impossibile
|
||||
else
|
||||
return false ;
|
||||
|
||||
// eventuali sistemazioni per altezza tagliente
|
||||
if ( ModifyForCutterHeight())
|
||||
@@ -182,7 +181,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
|
||||
// Caso avanzato
|
||||
m_dHeight = dH ;
|
||||
m_dRadius = dR ;
|
||||
m_dTipHeight = min( max( dTipH, 0.), m_dHeight) ;
|
||||
m_dTipHeight = Clamp( dTipH, 0., dH) ;
|
||||
m_dTipRadius = max( dTipR, 0.) ;
|
||||
m_dRCorner = dCornR ;
|
||||
|
||||
@@ -278,7 +277,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
|
||||
}
|
||||
}
|
||||
|
||||
// altrimenti Tip a coda di rondine ( TipRadius è raggio misurabile della parte finale dell'utensile)
|
||||
// altrimenti Tip a coda di rondine ( TipRadius è raggio misurabile della parte finale dell'utensile)
|
||||
else {
|
||||
// il raggio della punta non può essere inferiore al raggio corner
|
||||
if ( m_dTipRadius < m_dRCorner)
|
||||
@@ -382,14 +381,15 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
|
||||
}
|
||||
// altrimenti con raggio corner
|
||||
else {
|
||||
double dCR = Clamp( dCornR, 0., dThick / 2) ;
|
||||
// creazione profilo
|
||||
m_Outline.AddPoint( pt0) ;
|
||||
m_Outline.AddLine( pt1) ;
|
||||
m_Outline.AddLine( pt2) ;
|
||||
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
|
||||
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
|
||||
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
|
||||
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
|
||||
m_Outline.AddLine( pt3 - X_AX * dCR) ;
|
||||
m_Outline.AddArcTg( pt3 - Y_AX * dCR) ;
|
||||
m_Outline.AddLine( pt4 + Y_AX * dCR) ;
|
||||
m_Outline.AddArcTg( pt4 - X_AX * dCR) ;
|
||||
m_Outline.AddLine( pt5) ;
|
||||
}
|
||||
}
|
||||
@@ -410,12 +410,13 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
|
||||
}
|
||||
// altrimenti con raggio corner
|
||||
else {
|
||||
double dCR = Clamp( dCornR, 0., dThick / 2) ;
|
||||
// creazione profilo
|
||||
m_Outline.AddPoint( pt0) ;
|
||||
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
|
||||
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
|
||||
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
|
||||
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
|
||||
m_Outline.AddLine( pt3 - X_AX * dCR) ;
|
||||
m_Outline.AddArcTg( pt3 - Y_AX * dCR) ;
|
||||
m_Outline.AddLine( pt4 + Y_AX * dCR) ;
|
||||
m_Outline.AddArcTg( pt4 - X_AX * dCR) ;
|
||||
m_Outline.AddLine( pt5) ;
|
||||
}
|
||||
}
|
||||
@@ -524,7 +525,7 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
|
||||
// Assegno il raggio di riferimento se non già assegnato
|
||||
if ( m_dRefRadius < EPS_SMALL)
|
||||
m_dRefRadius = 0.25 * m_dRadius ;
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -540,14 +541,13 @@ Tool::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh
|
||||
m_ArcLineApprox.Clear() ;
|
||||
|
||||
// Verifica dimensioni globali
|
||||
if ( dH < EPS_SMALL || dW < EPS_SMALL ||
|
||||
dTh < EPS_SMALL || dRc < 0 || dW - 2 * dRc < 0)
|
||||
if ( dH < EPS_SMALL || dW < EPS_SMALL || dTh < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
m_dHeight = dH ;
|
||||
m_dRCorner = dRc ;
|
||||
m_dMrtChsWidth = dW ;
|
||||
m_dMrtChsThickness = dTh ;
|
||||
m_dRCorner = Clamp( dRc, 0., dW / 2) ;
|
||||
|
||||
// Imposto il tipo
|
||||
m_nType = MORTISER ;
|
||||
@@ -557,7 +557,7 @@ Tool::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nToolNum)
|
||||
Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nToolNum)
|
||||
{
|
||||
// Impostazioni generali
|
||||
m_sName = sToolName ;
|
||||
@@ -567,7 +567,7 @@ Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh,
|
||||
m_ArcLineApprox.Clear() ;
|
||||
|
||||
// Verifica dimensioni globali
|
||||
if ( dH < EPS_SMALL || dW < EPS_SMALL || dTh < 0)
|
||||
if ( dH < EPS_SMALL || dW < EPS_SMALL || dTh < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
m_dHeight = dH ;
|
||||
|
||||
@@ -23,7 +23,7 @@ class Tool
|
||||
~Tool( void) ;
|
||||
|
||||
public :
|
||||
bool Clear( void) ;
|
||||
bool Clear( bool bApproxWithLines = false) ;
|
||||
bool SetTolerances( double dLinTol, double dAngTolDeg = 45) ;
|
||||
bool SetStdTool( const std::string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nToolNum) ;
|
||||
bool SetAdvTool( const std::string& sToolName,
|
||||
@@ -37,7 +37,7 @@ class Tool
|
||||
{ m_nCurrentNum = nToolNum ; return true ; }
|
||||
int GetType() const
|
||||
{ return m_nType ; }
|
||||
int GetCurrentToolNum() const
|
||||
int GetToolNum() const
|
||||
{ return m_nCurrentNum ; }
|
||||
double GetHeigth() const
|
||||
{ return m_dHeight ; }
|
||||
|
||||
+290
-93
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2021
|
||||
//----------------------------------------------------------------------------
|
||||
// File : Triangulate.cpp Data : 23.06.14 Versione : 1.5f6
|
||||
// File : Triangulate.cpp Data : 18.12.21 Versione : 2.3l
|
||||
// Contenuto : Implementazione della classe Triangulate.
|
||||
//
|
||||
//
|
||||
@@ -16,9 +16,11 @@
|
||||
#include "DllMain.h"
|
||||
#include "Triangulate.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "earcut.hpp"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -29,6 +31,9 @@ enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
|
||||
//----------------------------------------------------------------------------
|
||||
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool FORCE_EARCUT_HPP = false ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// In : PolyLine
|
||||
// Out : PNTVECTOR (Point3d Vector) : points of the polyline
|
||||
@@ -37,6 +42,12 @@ static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
|
||||
bool
|
||||
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// pulisco i vettori di ritorno
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
|
||||
if ( PL.GetPointNbr() < 4)
|
||||
return false ;
|
||||
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
|
||||
double dArea ;
|
||||
Plane3d plPlane ;
|
||||
@@ -46,8 +57,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
bool bCCW ;
|
||||
if ( ! CalcProjPlane( plPlane.GetVersN(), m_nPlane, bCCW))
|
||||
return false ;
|
||||
|
||||
// forzo esecuzione triangolazione con earcut.hpp
|
||||
if ( FORCE_EARCUT_HPP) {
|
||||
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
|
||||
// riempio il vettore con i vertici del poligono da triangolare
|
||||
vPt.clear() ;
|
||||
vPt.reserve( PL.GetPointNbr() - 1) ;
|
||||
// salto il primo punto (coincide con l'ultimo)
|
||||
Point3d ptP ;
|
||||
@@ -59,18 +75,19 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// se non CCW inverto il vettore dei punti
|
||||
if ( ! bCCW)
|
||||
reverse( vPt.begin(), vPt.end()) ;
|
||||
// creo il vettore degli indici del Poligono
|
||||
INTVECTOR vPol ;
|
||||
int n = int( vPt.size()) ;
|
||||
vPol.reserve( n) ;
|
||||
for ( int i = 0 ; i < n ; ++ i)
|
||||
vPol.push_back( i) ;
|
||||
|
||||
// eseguo la triangolazione
|
||||
if ( ! MakeByEC2( vPt, vPol, vTr) &&
|
||||
! MakeByEC3( vPt, vPol, vTr)) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(1)")
|
||||
return false ;
|
||||
double dMinMinAng2, dMinMinAng3 ;
|
||||
if ( ! MakeByEC2( vPt, vTr, dMinMinAng2)) {
|
||||
if ( ! MakeByEC3( vPt, vTr, dMinMinAng3)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(1)")
|
||||
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
}
|
||||
else if ( dMinMinAng2 < 5) {
|
||||
INTVECTOR vMyTr ;
|
||||
if ( MakeByEC3( vPt, vMyTr, dMinMinAng3) && dMinMinAng3 > dMinMinAng2)
|
||||
vTr = vMyTr ;
|
||||
}
|
||||
|
||||
// se era CW, devo invertire il senso dei triangoli
|
||||
@@ -115,6 +132,12 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// forzo esecuzione triangolazione con earcut.hpp
|
||||
if ( FORCE_EARCUT_HPP) {
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
|
||||
// se non CCW inverto tutte le polilinee
|
||||
if ( ! bCCW) {
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
|
||||
@@ -122,8 +145,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
}
|
||||
// calcolo ordine decrescente su Xmax o Ymax o Zmax secondo m_nPlane per le curve interne
|
||||
INTVECTOR vOrd ;
|
||||
if ( ! SortInternalLoops( vPL, vOrd))
|
||||
return false ;
|
||||
bool bOk = SortInternalLoops( vPL, vOrd) ;
|
||||
// riempio il vettore con i punti dei poligoni da triangolare
|
||||
// calcolo spazio totale e spazio massimo per un percorso interno
|
||||
int nTot = vPL[0].GetPointNbr() - 1 ;
|
||||
@@ -136,22 +158,27 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// riservo spazio pari al totale dei punti (anche quelli ripetuti di chiusura che servono per i link)
|
||||
vPt.reserve( nTot) ;
|
||||
// inserisco i punti del contorno esterno (tranne il primo che coincide con l'ultimo)
|
||||
if ( ! GetPntVectorFromPolyline( vPL[0], false, vPt))
|
||||
return false ;
|
||||
bOk = bOk && GetPntVectorFromPolyline( vPL[0], false, vPt) ;
|
||||
// ciclo sui percorsi interni ordinati secondo Xmax decrescente
|
||||
PNTVECTOR vPi ;
|
||||
vPi.reserve( nMax) ;
|
||||
for ( int i = 1 ; i < int( vPL.size()) ; ++ i) {
|
||||
for ( int i = 1 ; bOk && i < int( vPL.size()) ; ++ i) {
|
||||
// riordino il percorso per avere punto iniziale con Xmax
|
||||
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi))
|
||||
return false ;
|
||||
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi)) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
// cerco un punto del percorso esterno visibile dal punto iniziale del precedente interno
|
||||
int nI ;
|
||||
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI))
|
||||
return false ;
|
||||
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI)) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
// riordino percorso esterno per avere questo punto all'inizio
|
||||
if ( ! ChangeStartPntVector( nI, vPt))
|
||||
return false ;
|
||||
if ( ! ChangeStartPntVector( nI, vPt)) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
// ripeto punto iniziale
|
||||
vPt.push_back( vPt[0]) ;
|
||||
// accodo percorso interno
|
||||
@@ -167,20 +194,21 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
|
||||
const_cast<PolyLine&>(vPL[i]).Invert( true) ;
|
||||
}
|
||||
|
||||
// creo il vettore degli indici del Poligono
|
||||
INTVECTOR vPol ;
|
||||
int n = int( vPt.size()) ;
|
||||
vPol.reserve( n) ;
|
||||
// non devo gestire separatamente CCW perchè ho già invertito i punti
|
||||
for ( int i = 0 ; i < n ; ++ i)
|
||||
vPol.push_back( i) ;
|
||||
if ( ! bOk)
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
|
||||
// eseguo la triangolazione
|
||||
if ( ! MakeByEC2( vPt, vPol, vTr) &&
|
||||
! MakeByEC3( vPt, vPol, vTr)) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(N)")
|
||||
return false ;
|
||||
double dMinMinAng2, dMinMinAng3 ;
|
||||
if ( ! MakeByEC2( vPt, vTr, dMinMinAng2)) {
|
||||
if ( ! MakeByEC3( vPt, vTr, dMinMinAng3)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(N)")
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
}
|
||||
else if ( dMinMinAng2 < 5) {
|
||||
INTVECTOR vMyTr ;
|
||||
if ( MakeByEC3( vPt, vMyTr, dMinMinAng3) && dMinMinAng3 > dMinMinAng2)
|
||||
vTr = vMyTr ;
|
||||
}
|
||||
|
||||
// se era CW, devo invertire il senso dei triangoli
|
||||
@@ -190,33 +218,113 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
|
||||
// Ear Clipping algorithm from mapbox
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
const INTVECTOR& vPrev, const INTVECTOR& vNext)
|
||||
Triangulate::MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// points number
|
||||
int n = int( vPol.size()) ;
|
||||
// overall box
|
||||
BBox3d b3All ;
|
||||
for ( int j = 0 ; j < n ; ++ j)
|
||||
b3All.Add( vPt[vPol[j]]) ;
|
||||
// grid cell dimension
|
||||
double dCellDim ;
|
||||
b3All.GetRadius( dCellDim) ;
|
||||
dCellDim *= 2 / sqrt( n) ;
|
||||
// grid
|
||||
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
|
||||
// pulisco i vettori di ritorno
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// riempio il vettore con i vertici del poligono da triangolare
|
||||
vPt.reserve( PL.GetPointNbr() - 1) ;
|
||||
// salto il primo punto (coincide con l'ultimo)
|
||||
Point3d ptP ;
|
||||
if ( ( bCCW && ! PL.GetFirstPoint( ptP)) ||
|
||||
( ! bCCW && ! PL.GetLastPoint( ptP)))
|
||||
return false ;
|
||||
for ( int j = 0 ; j < n ; ++ j) {
|
||||
// insert only reflex vertex
|
||||
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
|
||||
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
|
||||
return false ;
|
||||
// inserisco i punti
|
||||
while ( ( bCCW && PL.GetNextPoint( ptP)) ||
|
||||
( ! bCCW && PL.GetPrevPoint( ptP)))
|
||||
vPt.push_back( ptP) ;
|
||||
// Create array
|
||||
using Point = array<double, 2> ;
|
||||
vector<vector<Point>> polygon ;
|
||||
// Fill polygon structure with actual data. Any winding order works.
|
||||
// The first polyline defines the main polygon.
|
||||
polygon.resize( 1) ;
|
||||
polygon[0].reserve( vPt.size()) ;
|
||||
for ( int i = 0 ; i < int( vPt.size()) ; ++i) {
|
||||
switch ( m_nPlane) {
|
||||
default : // PL_XY
|
||||
polygon[0].push_back( { vPt[i].x, vPt[i].y}) ;
|
||||
break ;
|
||||
case PL_YZ :
|
||||
polygon[0].push_back( { vPt[i].y, vPt[i].z}) ;
|
||||
break ;
|
||||
case PL_ZX :
|
||||
polygon[0].push_back( { vPt[i].z, vPt[i].x}) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
m_vVert.reserve( n / 5) ;
|
||||
// Run tessellation
|
||||
// Returns array of indices that refer to the vertices of the input polygon.
|
||||
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
|
||||
vTr = mapbox::earcut<int32_t>( polygon) ;
|
||||
if ( vTr.empty()) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC_HPP(1)")
|
||||
return false ;
|
||||
}
|
||||
if ( ! bCCW)
|
||||
reverse( vTr.begin(), vTr.end()) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// pulisco i vettori di ritorno
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// Creo il vettore con i punti dei poligoni da triangolare
|
||||
// calcolo spazio totale e spazio massimo per un percorso interno
|
||||
int nTot = vPL[0].GetPointNbr() - 1 ;
|
||||
for ( int i = 1 ; i < int( vPL.size()) ; ++i)
|
||||
nTot += vPL[i].GetPointNbr() - 1 ;
|
||||
// riservo spazio pari al totale dei punti (esclusi quelli ripetuti)
|
||||
vPt.reserve( nTot) ;
|
||||
// Create array
|
||||
using Point = array<double, 2> ;
|
||||
vector<vector<Point>> polygon ;
|
||||
polygon.resize( vPL.size()) ;
|
||||
// Eseguo riempimento di vettore e array
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
|
||||
polygon[i].reserve( vPL[i].GetPointNbr() - 1) ;
|
||||
// salto il primo punto (coincide con l'ultimo)
|
||||
Point3d ptP ;
|
||||
if ( ( bCCW && ! vPL[i].GetFirstPoint( ptP)) ||
|
||||
( ! bCCW && ! vPL[i].GetLastPoint( ptP)))
|
||||
return false ;
|
||||
// inserisco i punti
|
||||
while ( ( bCCW && vPL[i].GetNextPoint( ptP)) ||
|
||||
( ! bCCW && vPL[i].GetPrevPoint( ptP))) {
|
||||
vPt.push_back( ptP) ;
|
||||
switch ( m_nPlane) {
|
||||
default : // PL_XY
|
||||
polygon[i].push_back( { ptP.x, ptP.y}) ;
|
||||
break ;
|
||||
case PL_YZ :
|
||||
polygon[i].push_back( { ptP.y, ptP.z}) ;
|
||||
break ;
|
||||
case PL_ZX :
|
||||
polygon[i].push_back( { ptP.z, ptP.x}) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run tessellation
|
||||
// Returns array of indices that refer to the vertices of the input polygon.
|
||||
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
|
||||
vTr = mapbox::earcut<int32_t>( polygon) ;
|
||||
if ( vTr.empty()) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC_HPP(N)")
|
||||
return false ;
|
||||
}
|
||||
if ( ! bCCW)
|
||||
reverse( vTr.begin(), vTr.end()) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -225,16 +333,22 @@ Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
// Ear Clipping algorithm
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
|
||||
Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// Clear triangle vector
|
||||
vTr.clear() ;
|
||||
|
||||
// At least 3 points
|
||||
int n = int( vPol.size()) ;
|
||||
int n = int( vPt.size()) ;
|
||||
if ( n < 3)
|
||||
return false ;
|
||||
|
||||
// Creo il vettore degli indici del Poligono
|
||||
INTVECTOR vPol ;
|
||||
vPol.reserve( n) ;
|
||||
for ( int i = 0 ; i < n ; ++ i)
|
||||
vPol.push_back( i) ;
|
||||
|
||||
// Preallocate triangle vector ( #triangles = n - 2)
|
||||
vTr.reserve( 3 * ( n - 2)) ;
|
||||
|
||||
@@ -297,16 +411,23 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& v
|
||||
// Ear Clipping algorithm enhanced, choose smaller diagonal
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
|
||||
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng)
|
||||
{
|
||||
// Clear triangle vector
|
||||
vTr.clear() ;
|
||||
dMinMinAng = ANG_STRAIGHT ;
|
||||
|
||||
// At least 3 points
|
||||
int n = int( vPol.size()) ;
|
||||
int n = int( vPt.size()) ;
|
||||
if ( n < 3)
|
||||
return false ;
|
||||
|
||||
// Creo il vettore degli indici del Poligono
|
||||
INTVECTOR vPol ;
|
||||
vPol.reserve( n) ;
|
||||
for ( int i = 0 ; i < n ; ++ i)
|
||||
vPol.push_back( i) ;
|
||||
|
||||
// Preallocate triangle vector ( #triangles = n - 2)
|
||||
vTr.reserve( 3 * ( n - 2)) ;
|
||||
|
||||
@@ -351,11 +472,11 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
int nLimN = min( 19, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimN ; ++ h) {
|
||||
j = vNext[j] ;
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
dSqDist = dMySqDist ;
|
||||
i = j ;
|
||||
}
|
||||
@@ -365,11 +486,11 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
int nLimP = min( 19, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimP ; ++ h) {
|
||||
k = vPrev[k] ;
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
dSqDist = dMySqDist ;
|
||||
i = k ;
|
||||
}
|
||||
@@ -389,6 +510,8 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
vTr.push_back( vPol[vPrev[i]]) ;
|
||||
vTr.push_back( vPol[i]) ;
|
||||
vTr.push_back( vPol[vNext[i]]) ;
|
||||
double dMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
dMinMinAng = min( dMinMinAng, dMinAng) ;
|
||||
}
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
@@ -414,20 +537,26 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
|
||||
// Ear Clipping algorithm enhanced, choose smaller triangle aspect ratio
|
||||
// AR = ( Lmax * Lmax) / ( 2 * Area) = SqLenMax / L1 * L2
|
||||
// Ear Clipping algorithm enhanced, choose max MinAng
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
|
||||
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng)
|
||||
{
|
||||
// Clear triangle vector
|
||||
vTr.clear() ;
|
||||
dMinMinAng = ANG_STRAIGHT ;
|
||||
|
||||
// At least 3 points
|
||||
int n = int( vPol.size()) ;
|
||||
int n = int( vPt.size()) ;
|
||||
if ( n < 3)
|
||||
return false ;
|
||||
|
||||
// Creo il vettore degli indici del Poligono
|
||||
INTVECTOR vPol ;
|
||||
vPol.reserve( n) ;
|
||||
for ( int i = 0 ; i < n ; ++ i)
|
||||
vPol.push_back( i) ;
|
||||
|
||||
// Preallocate triangle vector ( #triangles = n - 2)
|
||||
vTr.reserve( 3 * ( n - 2)) ;
|
||||
|
||||
@@ -462,32 +591,50 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
vEar[i] = ( TestTriangle( vPt, vPol, vPrev, vNext, i) ? EAS_OK : EAS_NO) ;
|
||||
bool bIsEar = ( vEar[i] == EAS_OK) ;
|
||||
bool bSave = bIsEar ;
|
||||
double dMinAng = -1 ;
|
||||
if ( bIsEar) {
|
||||
// Square Length & Aspect Ratio
|
||||
// Square Length & MinAngle
|
||||
double dSqLen = SqDist(vPt[vPol[vPrev[i]]], vPt[vPol[vNext[i]]]) ;
|
||||
double dAR = CalcTriangleAspectRatio( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
// Try with all other vertices
|
||||
int ii = i ;
|
||||
int j = vNext[i] ;
|
||||
while ( j != ii) {
|
||||
// New Square Length
|
||||
double dNewSqLen = SqDist(vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dNewSqLen < 0.99 * dSqLen) {
|
||||
// New Aspect Ratio
|
||||
double dNewAR = CalcTriangleAspectRatio( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]]) ;
|
||||
// if better, test if triangle ok
|
||||
if ( dNewAR < 30 || dNewAR < 1.2 * dAR) {
|
||||
dMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
// Start point for trials
|
||||
int j = i ;
|
||||
int k = i ;
|
||||
// Try with 29 next
|
||||
int nLimN = min( 29, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimN ; ++ h) {
|
||||
j = vNext[j] ;
|
||||
double dMySqLen = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqLen < 2 * dSqLen) {
|
||||
double dMyMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMyMinAng > 1.01 * dMinAng) {
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
dSqLen = dNewSqLen ;
|
||||
dAR = min( dAR, dNewAR) ;
|
||||
dSqLen = dMySqLen ;
|
||||
dMinAng = dMyMinAng ;
|
||||
i = j ;
|
||||
}
|
||||
}
|
||||
}
|
||||
j = vNext[j] ;
|
||||
}
|
||||
}
|
||||
// Try with 29 prev
|
||||
int nLimP = min( 29, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimP ; ++ h) {
|
||||
k = vPrev[k] ;
|
||||
double dMySqLen = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqLen < 2 * dSqLen) {
|
||||
double dMyMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[k]]], vPt[vPol[k]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMyMinAng > 1.01 * dMinAng) {
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
dSqLen = dMySqLen ;
|
||||
dMinAng = dMyMinAng ;
|
||||
i = k ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify if triangle is null (accept to discard)
|
||||
else {
|
||||
@@ -502,6 +649,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
vTr.push_back( vPol[vPrev[i]]) ;
|
||||
vTr.push_back( vPol[i]) ;
|
||||
vTr.push_back( vPol[vNext[i]]) ;
|
||||
dMinMinAng = min( dMinMinAng, dMinAng) ;
|
||||
}
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
@@ -525,6 +673,36 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
const INTVECTOR& vPrev, const INTVECTOR& vNext)
|
||||
{
|
||||
// points number
|
||||
int n = int( vPol.size()) ;
|
||||
// overall box
|
||||
BBox3d b3All ;
|
||||
for ( int j = 0 ; j < n ; ++ j)
|
||||
b3All.Add( vPt[vPol[j]]) ;
|
||||
// grid cell dimension
|
||||
double dCellDim ;
|
||||
b3All.GetRadius( dCellDim) ;
|
||||
dCellDim *= 2 / sqrt( n) ;
|
||||
// grid
|
||||
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
|
||||
return false ;
|
||||
for ( int j = 0 ; j < n ; ++ j) {
|
||||
// insert only reflex vertex
|
||||
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
|
||||
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
m_vVert.reserve( n / 5) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
@@ -578,7 +756,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Ratio between max side and opposite height
|
||||
// Ratio between Circumcircle Radius and Incircle Diameter (minimum 1 for equilateral)
|
||||
double
|
||||
Triangulate::CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc)
|
||||
{
|
||||
@@ -592,6 +770,25 @@ Triangulate::CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb,
|
||||
return ( max( { dSqDistA, dSqDistB, dSqDistC}) / dTwoArea) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
Triangulate::CalcTriangleMinAngle( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc)
|
||||
{
|
||||
double dSqLenA = SquareDist( ptPa, ptPb) ;
|
||||
double dSqLenB = SquareDist( ptPb, ptPc) ;
|
||||
double dSqLenC = SquareDist( ptPc, ptPa) ;
|
||||
if ( dSqLenA > dSqLenB)
|
||||
swap( dSqLenA, dSqLenB) ;
|
||||
if ( dSqLenA > dSqLenC)
|
||||
swap( dSqLenA, dSqLenC) ;
|
||||
double dLenB = sqrt( dSqLenB) ;
|
||||
double dLenC = sqrt( dSqLenC) ;
|
||||
double dCosA = ( dSqLenB + dSqLenC - dSqLenA) / ( 2 * dLenB * dLenC) ;
|
||||
dCosA = Clamp( dCosA, -1., +1.) ;
|
||||
double dAngA = acos( dCosA) * RADTODEG ;
|
||||
return dAngA ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
Triangulate::SquareDist( const Point3d& ptA, const Point3d& ptB)
|
||||
@@ -800,7 +997,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
||||
// indice punto successivo
|
||||
int j = ( i + 1 < nNumPt) ? i + 1 : 0 ;
|
||||
// mi metto nel piano principale
|
||||
switch (m_nPlane) {
|
||||
switch ( m_nPlane) {
|
||||
default : // PL_XY
|
||||
// se i punti coincidono
|
||||
if ( abs( vPt[i].x - ptP.x) < EPS_SMALL && abs( vPt[i].y - ptP.y) < EPS_SMALL) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user