Compare commits
458 Commits
Zmap
...
FasterVMill5Axis
| Author | SHA1 | Date | |
|---|---|---|---|
| 83bd050868 | |||
| 1ba1eb6a27 | |||
| 7e78f0d0e3 | |||
| df828ab2ba | |||
| a4b66af304 | |||
| 0a5d655bfc | |||
| 6393817f41 | |||
| f871bfedc9 | |||
| e38b065357 | |||
| 704a977475 | |||
| 51fb1f4993 | |||
| dbb751a441 | |||
| 371ff54d9c | |||
| 6a4b4feff5 | |||
| 6f1f3441ea | |||
| b955b12f38 | |||
| f22ea484db | |||
| 1b9738eace | |||
| 0a8cc414a5 | |||
| 7a682653cd | |||
| 9286ab6535 | |||
| 85736ab03f | |||
| 673f5c7a9b | |||
| 34d0bcbdfe | |||
| 7abf3027d4 | |||
| ffe3d44cac | |||
| dd23b848ac | |||
| 33cca03698 | |||
| d4d14dd866 | |||
| d6f0fdac50 | |||
| 080605510c | |||
| 1a7b789ef3 | |||
| cc4183a677 | |||
| c2bae56656 | |||
| 38a5c0cbb3 | |||
| 81a8eb698e | |||
| ee4bb7d7c4 | |||
| 8b0d5bddbf | |||
| ba75033f0a | |||
| eb2b90c6f2 | |||
| 3b5c34cb05 | |||
| 2fe22a62c2 | |||
| ff6307fcca | |||
| c6e80a0b6a | |||
| b957cc75be | |||
| fc18539472 | |||
| de7229aee7 | |||
| 53e66032a0 | |||
| 2fc6c30c8f | |||
| f05c5f1261 | |||
| 6af5591cf6 | |||
| 41cbe862e5 | |||
| 057b8273e2 | |||
| 6421c12408 | |||
| 0aca5aeb07 | |||
| bdbd3583b8 | |||
| 626d5b0e51 | |||
| 0bffa0039c | |||
| 9819c8cee8 | |||
| 53ab676750 | |||
| afa4872c97 | |||
| bf56d53faf | |||
| f03adb9206 | |||
| 529fa2e4a0 | |||
| 6df1b90e95 | |||
| 9cba0e6d15 | |||
| f16de3a20c | |||
| 8cfa41d09f | |||
| b59b501366 | |||
| 504bb50b13 | |||
| 969f1266e7 | |||
| fa680b7799 | |||
| e185c85d5e | |||
| acb0a5bd5e | |||
| 62ce576d4d | |||
| 161d3d9b17 | |||
| d88baa070f | |||
| 2b087dde51 | |||
| 7894a8fdc8 | |||
| 0f14e8335a | |||
| 7edf4bced8 | |||
| 4a5639780b | |||
| 0a21a582be | |||
| 0e663c02c4 | |||
| 21afe8165c | |||
| 0247fe5e7c | |||
| 50bad83fba | |||
| 9c93d6c2f3 | |||
| 4d9a50cf94 | |||
| bbdaac5d8d | |||
| 0417c43bcf | |||
| 15585b8f11 | |||
| 59755ec8a5 | |||
| b16dd260d8 | |||
| d37a5a37b7 | |||
| 79dfb4ae87 | |||
| 8b75b6e4c3 | |||
| bcaad08b61 | |||
| cbdeffd93a | |||
| 0ce477a3e7 | |||
| 44eb4d1834 | |||
| 2e26b73208 | |||
| de3fa3201e | |||
| f068aafbb5 | |||
| daedb07135 | |||
| 702e1e446d | |||
| ea87db1ae1 | |||
| b65800843a | |||
| e4c5d8645d | |||
| 85b06c29b4 | |||
| 5254d0c5ca | |||
| 292c2bf87a | |||
| 9d038142a8 | |||
| c5573e438b | |||
| 8c7a0ac026 | |||
| e45bbf2afd | |||
| fc6de68d83 | |||
| a008c169ae | |||
| 3cd6c9299f | |||
| 8e5801d656 | |||
| 1691b7f84a | |||
| 76e4197729 | |||
| fb8bac8681 | |||
| 55a9685add | |||
| afa4be3717 | |||
| 57c03a54c9 | |||
| 91a9adaea4 | |||
| 8657fa32c5 | |||
| b7a4f0bff3 | |||
| f0716e2727 | |||
| b1acf7f4f0 | |||
| 851c053f7c | |||
| 71276a8de3 | |||
| b2e799e1d6 | |||
| eb9aaef53a | |||
| 49340d2629 | |||
| 0b9c9f375c | |||
| cd56f80790 | |||
| 65d826168b | |||
| ea012988df | |||
| 67f3df353f | |||
| 9d34df708d | |||
| 72947f1e36 | |||
| 1cdae73b24 | |||
| a2825b2b6d | |||
| 5bc7036e98 | |||
| 7e545aecd7 | |||
| 0fc8291ef5 | |||
| 0d668c1a4a | |||
| 4b1270f231 | |||
| 9263dc0516 | |||
| b0f7cb93fd | |||
| add3788db4 | |||
| 37c23faae3 | |||
| fa6f12ba3b | |||
| 730dd396f4 | |||
| 3b9f6773f2 | |||
| 97315f6ca4 | |||
| b2be420e36 | |||
| 4ee34b79f8 | |||
| e4ee403d24 | |||
| b709776f5f | |||
| b5a2490fd4 | |||
| 7a18cd1c5c | |||
| 26e1448bbb | |||
| a1ebdb4eb6 | |||
| 6603061f81 | |||
| 1c3d7bf2a6 | |||
| a4a030b776 | |||
| 64a8294ea0 | |||
| 847383d82d | |||
| c16d916a63 | |||
| 91cae44533 | |||
| 56c3e28ac3 | |||
| 3238c86cec | |||
| f050e682ef | |||
| 01c875b34f | |||
| 50b8a8aa94 | |||
| 9f1aad5e49 | |||
| a38c50197b | |||
| fe54dde44e | |||
| 62a3405d6a | |||
| cb9dd807ce | |||
| d60d38a24b | |||
| e598e7986f | |||
| 9bebd2f2ad | |||
| 36d5c39094 | |||
| 1b08f4bbdd | |||
| 4a952b1c9b | |||
| 7a25927054 | |||
| cf022921a7 | |||
| dc798aaaba | |||
| eed89dab37 | |||
| 990bc1a1e4 | |||
| 03433fe3af | |||
| e02611504b | |||
| a835433be4 | |||
| da8f40db17 | |||
| 5468e3f4fa | |||
| 88684e305f | |||
| f8ca8029d7 | |||
| aa9c46cbb5 | |||
| f0cf3c9559 | |||
| 9a638b9470 | |||
| b07fbfc72e | |||
| 0317c37557 | |||
| a98b6bcc09 | |||
| c19861a911 | |||
| 8f8597d442 | |||
| 0c0eb9ef8f | |||
| 4ffb7087bd | |||
| dc070c4556 | |||
| 60729d5f39 | |||
| da7e9dd6e2 | |||
| aeff9fb418 | |||
| e9e897593b | |||
| bfc09d135c | |||
| 0998d0fffc | |||
| 93c87ee720 | |||
| a67a0502fa | |||
| cec0a48be4 | |||
| 0cc63d40eb | |||
| 623eb6e630 | |||
| 1f22299096 | |||
| 3f6c439983 | |||
| 8e22267476 | |||
| aa2b6ccde5 | |||
| ec6cb79a8d | |||
| 76dceb4fc9 | |||
| b1564f7de0 | |||
| 21e4bd6d93 | |||
| 2101d72abe | |||
| 7a01f67c8b | |||
| 2267343afe | |||
| 9a5fe24781 | |||
| 4050aa11c5 | |||
| b75ddae396 | |||
| 2d3f8487ee | |||
| 964647d7e6 | |||
| f78dd0fa83 | |||
| 55ce22b06c | |||
| 50df4f3503 | |||
| 5c8f0c79f6 | |||
| de3f187ddf | |||
| f649954ee1 | |||
| 6e08f2a878 | |||
| 887922a715 | |||
| 640fef2e0a | |||
| 1a338a1a82 | |||
| 4f3fe68283 | |||
| 3908e11d18 | |||
| 4e6c5112e4 | |||
| e1ab88302f | |||
| 2b4090619b | |||
| b90289e42b | |||
| 5e84408685 | |||
| b53c2f833a | |||
| b5fcceaa75 | |||
| f0bfbb6c85 | |||
| 2710f735d1 | |||
| ddffbd2c88 | |||
| fde952499d | |||
| b28102a8cc | |||
| f46db233dc | |||
| df10b45c6b | |||
| 1b13580340 | |||
| 742305b99b | |||
| 1261de4dbb | |||
| b50588f974 | |||
| 9b87de9fa2 | |||
| 5bab4a9aa8 | |||
| c3e7d3d8c7 | |||
| 89c22ffd06 | |||
| 5375752609 | |||
| 0a8f26c993 | |||
| cba9c253e1 | |||
| 71f3bf8809 | |||
| d491536eb4 | |||
| e68465c80b | |||
| dfb8fd2160 | |||
| 746fa61e08 | |||
| d0e0c46e2c | |||
| 19c7f63303 | |||
| 87f6a29db3 | |||
| b04d1ed7a9 | |||
| 54dba7ab41 | |||
| 146c06d27f | |||
| 7c45c1e287 | |||
| d6dc5b8428 | |||
| 28695f9138 | |||
| 66cec4a872 | |||
| 8d1d3f766a | |||
| befed079c8 | |||
| b9138029db | |||
| 2246dbc284 | |||
| 67180b3569 | |||
| 3a2aa2c679 | |||
| 9dd4e043d4 | |||
| 4748bd5ac8 | |||
| 649f97e933 | |||
| 21feed172d | |||
| e853ff7f13 | |||
| 95ff8b21b9 | |||
| a7be952e11 | |||
| 7a67ce9333 | |||
| 695350d3f6 | |||
| aade1d19f1 | |||
| fd4677d099 | |||
| f7a28447fb | |||
| 79b470b18b | |||
| f6d3873ecb | |||
| 92a8cdad99 | |||
| 0c346e2bc7 | |||
| d54caf4ae3 | |||
| ff9ea34ae1 | |||
| c7035305e2 | |||
| bc3c1e377e | |||
| 98eff1b0b9 | |||
| 052cc9e841 | |||
| b6a7ce4eef | |||
| 7a66ad27d8 | |||
| b4878f1ac0 | |||
| 447ebe11e5 | |||
| 8981057d29 | |||
| 3270b573a8 | |||
| 6df0cf3203 | |||
| d67cca385e | |||
| f9d67442d6 | |||
| dea96ccbcc | |||
| 0f4be10330 | |||
| 121abf5864 | |||
| 38e836de2b | |||
| 376c4e3693 | |||
| 48ffd52b16 | |||
| 9a16259ff5 | |||
| 10ae269882 | |||
| 9d845179a4 | |||
| 88bf84cca1 | |||
| 5ba8f1df36 | |||
| c4a05bcb2f | |||
| 5841c9cae0 | |||
| 4fd03a78de | |||
| 420c072670 | |||
| 36477623b8 | |||
| 84d859dfe2 | |||
| 09220bfd68 | |||
| 42aaf6f3eb | |||
| 3f1f365451 | |||
| 9a29ee0e27 | |||
| 619905d720 | |||
| 36ce855ef3 | |||
| 9b0f2c7f59 | |||
| c637ccec47 | |||
| 8f27154604 | |||
| 5d02732db6 | |||
| 36657e17c4 | |||
| e2008bd479 | |||
| e32b85bc2d | |||
| 6dfc50e630 | |||
| b4820ff255 | |||
| 515247a394 | |||
| b5c649821f | |||
| 9ba0c6f4cc | |||
| 35fc94d8cb | |||
| a0316e280c | |||
| 84bcc715a8 | |||
| b34d31029b | |||
| f67865f9cc | |||
| f48053a541 | |||
| 8e917aa6d2 | |||
| f08dee836b | |||
| 261e9ac0c8 | |||
| b51d0c3e64 | |||
| ac23938dd0 | |||
| b9bac347e8 | |||
| 980a1f62df | |||
| 10c5d0fffe | |||
| d7d36b670a | |||
| 581551ee3e | |||
| 487ce0c84b | |||
| 5679733028 | |||
| cd0fc4e449 | |||
| e20b4b5b78 | |||
| b931582120 | |||
| bf14ab1332 | |||
| 3b81a6b92e | |||
| 01bf44cf1e | |||
| b5d879cd3d | |||
| 2b3c285190 | |||
| 99bb83211c | |||
| b854c9588b | |||
| 2361225321 | |||
| eaf1138624 | |||
| ef5c67a4d5 | |||
| 3e924113d3 | |||
| dcc3fc772a | |||
| a48f373e4d | |||
| ffd714d069 | |||
| dc082d495e | |||
| e8e57ff793 | |||
| 3e16c4b56c | |||
| 77d3fcc7af | |||
| 7322bf5034 | |||
| 2ed2a34d55 | |||
| d340505593 | |||
| 247849d112 | |||
| fcbdee1dba | |||
| 33d1ef4123 | |||
| fe2aba43e5 | |||
| c0b5f38301 | |||
| 1c157f323e | |||
| 3e6aa0d81b | |||
| 34089648b0 | |||
| 0bef1638d0 | |||
| 1d4bccac4b | |||
| cc7aa66904 | |||
| 303a270359 | |||
| 17759877d4 | |||
| 5f56152a8b | |||
| d6567e94c4 | |||
| d00064a671 | |||
| dc91f932f7 | |||
| a3f05c41fe | |||
| d911862c84 | |||
| 1b025ec60e | |||
| 9d18e1a9ba | |||
| 3143c00729 | |||
| 3a8900983a | |||
| 971a76e473 | |||
| 621bf93ee9 | |||
| 35c019a03e | |||
| de97f249a2 | |||
| 81f0cc23bf | |||
| 8a0234093e | |||
| 88d355f2f7 | |||
| 20fd06d67c | |||
| 52f2785e67 | |||
| 2e2bd0ceec | |||
| e4c3c9a2a4 | |||
| e490c173e8 | |||
| 7e165a6dea | |||
| 49ff6e79a8 | |||
| 1160e3d067 | |||
| 91d667bcfc | |||
| b23df89cd3 | |||
| cf9737a48e | |||
| ae52115bda | |||
| 3dd9466938 | |||
| c0f7eb6727 | |||
| 76e2843ed3 | |||
| faa2004c29 | |||
| c9a59dc5ea | |||
| aaaf951990 | |||
| cc263089ca | |||
| d99b8f4c86 | |||
| f5e5441469 | |||
| 4206a4822f | |||
| 788a5bc4eb |
@@ -317,6 +317,8 @@ AdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst, bool bNeedSameProp)
|
||||
pCrvCo->RemoveSmallDefects( 2 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ;
|
||||
// unisco eventuali tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, bNeedSameProp) ;
|
||||
// richiudo i loop per sicurezza
|
||||
pCrvCo->Close() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkArcPntDirTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+2
-1
@@ -134,7 +134,8 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd,
|
||||
|
||||
// calcolo arco non riuscito, se i punti sono allineati nel giusto verso per essere una retta
|
||||
// verifico se i punti sono allineati nel giusto verso
|
||||
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) {
|
||||
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO ||
|
||||
AreSamePointApprox( ptOther, ptStart) || AreSamePointApprox( ptEnd, ptOther)) {
|
||||
// creo l'oggetto retta
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
|
||||
+8
-8
@@ -133,22 +133,22 @@ Attribs::Load( NgeReader& ngeIn)
|
||||
unsigned char ucLev ;
|
||||
if ( ! ngeIn.ReadUchar( ucLev, ","))
|
||||
return false ;
|
||||
m_Data[LEVEL] = CLIP( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
m_Data[LEVEL] = Clamp( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
// modo
|
||||
unsigned char ucMode ;
|
||||
if ( ! ngeIn.ReadUchar( ucMode, ","))
|
||||
return false ;
|
||||
m_Data[MODE] = CLIP( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
m_Data[MODE] = Clamp( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
// stato (se SEL è convertito in ON)
|
||||
unsigned char ucStat ;
|
||||
if ( ! ngeIn.ReadUchar( ucStat, ","))
|
||||
return false ;
|
||||
m_Data[STATUS] = CLIP( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
m_Data[STATUS] = Clamp( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
// marcatura (sempre OFF)
|
||||
unsigned char ucMark ;
|
||||
if ( ! ngeIn.ReadUchar( ucMark, ";"))
|
||||
return false ;
|
||||
m_Data[MARK] = CLIP( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
m_Data[MARK] = Clamp( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
// materiale
|
||||
if ( ! ngeIn.ReadInt( m_Material, ";"))
|
||||
return false ;
|
||||
@@ -185,22 +185,22 @@ Attribs::DataFromString( const string& sParam)
|
||||
int nLev ;
|
||||
if ( ! FromString( vsParams[0], nLev))
|
||||
return false ;
|
||||
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
// modo
|
||||
int nMode ;
|
||||
if ( ! FromString( vsParams[1], nMode))
|
||||
return false ;
|
||||
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
// stato (ammessi solo OFF e ON)
|
||||
int nStat ;
|
||||
if ( ! FromString( vsParams[2], nStat))
|
||||
return false ;
|
||||
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
// marcatura (ammesso solo OFF)
|
||||
int nMark ;
|
||||
if ( ! FromString( vsParams[3], nMark))
|
||||
return false ;
|
||||
m_Data[MARK] = CLIP( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
#include "/EgtDev/Include/EGkGdbConst.h"
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EgtStringBase.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
|
||||
class NgeWriter ;
|
||||
class NgeReader ;
|
||||
class GeomDB ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define CLIP( nV, nMIN, nMAX) (( nV < nMIN) ? nMIN : (( nV > nMAX) ? nMAX : nV))
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class Attribs
|
||||
{
|
||||
@@ -46,14 +44,14 @@ class Attribs
|
||||
bool Load( NgeReader& ngeIn) ;
|
||||
void SetLevel( int nLev)
|
||||
{ m_OldData[LEVEL] = m_Data[LEVEL] ;
|
||||
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
|
||||
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
|
||||
void RevertLevel( void)
|
||||
{ std::swap( m_Data[LEVEL], m_OldData[LEVEL]) ; }
|
||||
int GetLevel( void) const
|
||||
{ return m_Data[LEVEL] ; }
|
||||
void SetMode( int nMode)
|
||||
{ m_OldData[MODE] = m_Data[MODE] ;
|
||||
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
|
||||
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
|
||||
void RevertMode( void)
|
||||
{ std::swap( m_Data[MODE], m_OldData[MODE]) ; }
|
||||
int GetMode( void) const
|
||||
@@ -61,13 +59,13 @@ class Attribs
|
||||
void SetStatus( int nStat)
|
||||
{ if ( m_Data[STATUS] != GDB_ST_SEL)
|
||||
m_OldData[STATUS] = m_Data[STATUS] ;
|
||||
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
|
||||
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
|
||||
void RevertStatus( void)
|
||||
{ SetStatus( m_OldData[STATUS]) ; }
|
||||
int GetStatus( void) const
|
||||
{ return m_Data[STATUS] ; }
|
||||
void SetMark( void)
|
||||
{ m_Data[MARK] = GDB_MK_ON ; }
|
||||
void SetMark( int nMark)
|
||||
{ m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_ON_2) ; }
|
||||
void ResetMark( void)
|
||||
{ m_Data[MARK] = GDB_MK_OFF ; }
|
||||
int GetMark( void) const
|
||||
|
||||
+9
-6
@@ -83,7 +83,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
|
||||
const PolyLine& PL, double& dDist)
|
||||
const PolyLine& PL, double& dDist, double dTol)
|
||||
{
|
||||
// calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco
|
||||
PtrOwner<ICurve> pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ;
|
||||
@@ -122,7 +122,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
}
|
||||
}
|
||||
}
|
||||
// non c'è intersezione, assegno valore medio
|
||||
// non c'è intersezione, assegno valore medio
|
||||
if ( dU < -0.5)
|
||||
dU = 0.5 ;
|
||||
// elimino casi vicino agli estremi, danno solo problemi
|
||||
@@ -142,7 +142,10 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
Point3d ptPrev = ptCurr ;
|
||||
while ( bPnt) {
|
||||
double dLen = Dist( ptCurr, ptPrev) ;
|
||||
int nStep = ( dLen < STEP ? 2 : 1) * int( dLen / STEP) + 1 ;
|
||||
int nStep = int( dLen / STEP) + 1 ;
|
||||
int nMinStep = ( dLen > 50 * dTol ? 3 : ( dLen > 10 * dTol ? 2 : 1)) ;
|
||||
int nMaxStep = 10 ;
|
||||
nStep = Clamp( nStep, nMinStep, nMaxStep) ;
|
||||
for ( int i = 1 ; i <= nStep ; ++ i) {
|
||||
double dCoeff = double( i) / nStep ;
|
||||
Point3d ptP = Media( ptPrev, ptCurr, dCoeff) ;
|
||||
@@ -163,7 +166,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
static ICurve*
|
||||
CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg)
|
||||
{
|
||||
// se i due punti coincidono, non si può fare alcunché
|
||||
// se i due punti coincidono, non si può fare alcunché
|
||||
if ( AreSamePointApprox( ptP0, ptP1))
|
||||
return nullptr ;
|
||||
|
||||
@@ -205,14 +208,14 @@ CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dD
|
||||
double dDir0RelDeg = DiffAngle( dDir0Deg, dDirDiffDeg) ;
|
||||
// direzione iniziale secondo arco limite rispetto a direzione P0->P1 (dalla finale simmetrico e invert)
|
||||
double dDir1RelDeg = - DiffAngle( dDir1Deg, dDirDiffDeg) ;
|
||||
// nel caso di direzioni a 180deg si sceglie la più compatta
|
||||
// nel caso di direzioni a 180deg si sceglie la più compatta
|
||||
if ( abs( abs( dDir1RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
||||
dDir1RelDeg = ( dDir0RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
||||
else if ( abs( abs( dDir0RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
||||
dDir0RelDeg = ( dDir1RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
||||
// intervallo angolare ammissibile a partire da direzione iniziale primo arco ammissibile ( == Dir0)
|
||||
double dDeltaAngDeg = - dDir0RelDeg + dDir1RelDeg ;
|
||||
// se non è nella regione, prendo l'altra parte di arco
|
||||
// se non è nella regione, prendo l'altra parte di arco
|
||||
if ( ! AngleInSpan( dDirStartRelDeg, dDir0RelDeg, dDeltaAngDeg))
|
||||
pArc->ToExplementary() ;
|
||||
// inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ICurve* GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
|
||||
const PolyLine& PL, double& dDist) ;
|
||||
const PolyLine& PL, double& dDist, double dTol) ;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvSilhouetteSurfTm.h Data : 16.06.24 Versione : 2.6f2
|
||||
// Contenuto : Dichiarazione della classe calcolo multi-silhouette.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CAvToolSurfTm.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm
|
||||
{
|
||||
public :
|
||||
// generica
|
||||
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol) override ;
|
||||
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol,
|
||||
double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR,
|
||||
double dMaxDepth) override ;
|
||||
bool GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) override ;
|
||||
|
||||
public :
|
||||
CAvParSilhouettesSurfTm( void) ;
|
||||
|
||||
private :
|
||||
bool Prepare( void) ;
|
||||
|
||||
private :
|
||||
CISURFTMPVECTOR m_vpStm ;
|
||||
CAvToolSurfTm m_cavTstm ;
|
||||
Frame3d m_frGrid ;
|
||||
double m_dTol ;
|
||||
double m_dSharpedTol ;
|
||||
int m_nStepX ;
|
||||
int m_nStepY ;
|
||||
double m_dRad ;
|
||||
double m_dCornRad ;
|
||||
double m_dMaxMat ;
|
||||
double m_dSideAng ;
|
||||
double m_dOffsR ;
|
||||
double m_dDimZ ;
|
||||
double m_dLevelOffs ;
|
||||
double m_dMaxDepth ;
|
||||
bool m_bGridOk ;
|
||||
bool m_bTool ;
|
||||
DBLVECTOR m_vdGrid ;
|
||||
} ;
|
||||
+526
-55
@@ -1,21 +1,21 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2018-2018
|
||||
// EgalTech 2018-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvToolSurfTm.cpp Data : 08.05.18 Versione : 1.9e2
|
||||
// File : CAvToolSurfTm.cpp Data : 07.06.24 Versione : 2.6f2
|
||||
// Contenuto : Implementazione della classe CAvToolSurfTm.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 27.04.18 DS Creazione modulo.
|
||||
//
|
||||
// 07.06.24 DS Con tolleranza lineare negativa non si controlla il punto medio.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CAvToolTriangle.h"
|
||||
#include "CAvToolSurfTm.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
@@ -24,6 +24,7 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const int STEP_PE = 50 ;
|
||||
const double MAX_MOVE = 20000 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICAvToolSurfTm*
|
||||
@@ -37,10 +38,29 @@ CreateCAvToolSurfTm( void)
|
||||
// CAvToolSurfTm
|
||||
//----------------------------------------------------------------------------
|
||||
CAvToolSurfTm::CAvToolSurfTm( void)
|
||||
: m_Tool( false)
|
||||
: m_frMove( false), m_Tool( false)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::Clear( void)
|
||||
{
|
||||
// pulisco la lista dei puntatori a Stm
|
||||
m_vSTM.clear() ;
|
||||
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
|
||||
m_vBaseInd.clear() ;
|
||||
m_vBaseInd.emplace_back( 0) ;
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// reset utensile
|
||||
m_Tool.Clear() ;
|
||||
// reset riferimento
|
||||
m_frMove.Reset( false) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
@@ -50,6 +70,9 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
|
||||
m_vBaseInd.clear() ;
|
||||
m_vBaseInd.emplace_back( 0) ;
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// non tocco l'utensile
|
||||
// aggiungo la superficie
|
||||
return AddSurfTm( Stm) ;
|
||||
}
|
||||
@@ -58,7 +81,7 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
bool
|
||||
CAvToolSurfTm::AddSurfTm( const ISurfTriMesh& Stm)
|
||||
{
|
||||
// verifico validità superficie
|
||||
// verifico validità superficie
|
||||
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &Stm) ;
|
||||
if ( pStm == nullptr || ! pStm->IsValid())
|
||||
return false ;
|
||||
@@ -99,40 +122,227 @@ CAvToolSurfTm::SetGenTool( const ICurveComposite* pToolOutline)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist)
|
||||
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, Vector3d* pvtTriaN) const
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Imposto il riferimento di movimento
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
m_frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
m_frMove.Set( ORIG, vtMove) ;
|
||||
// Eseguo controllo
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se riferimento di movimento già presente
|
||||
if ( m_frMove.IsValid()) {
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
|
||||
if ( AreSameFrame( frMove, m_frMove)) {
|
||||
// Eseguo controllo
|
||||
Point3d ptCurr = ptT ;
|
||||
Vector3d vtTriaN ;
|
||||
dTotDist = MyTestPositionHG( ptCurr, vtDir, vtTriaN) ;
|
||||
if ( pvtTriaN != nullptr)
|
||||
*pvtTriaN = vtTriaN ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
// Altrimenti eseguo controllo diretto
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPosition( ptCurr, vtDir) ;
|
||||
Vector3d vtTriaN ;
|
||||
dTotDist = MyTestPosition( ptCurr, vtDir, vtMove, vtTriaN) ;
|
||||
if ( pvtTriaN != nullptr)
|
||||
*pvtTriaN = vtTriaN ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol)
|
||||
CAvToolSurfTm::TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, VCT3DVECTOR& vVtN) const
|
||||
{
|
||||
// Funzione per calcolo collisione tra utensile e superfici ;
|
||||
// dToTDist è la distanza di traslazione del punto ptT lungo vtDir per evitare la collisione,
|
||||
// vVtN è la normale del triangolo che genera collsione ( NB. Nel caso di più triangoli concorrenti,
|
||||
// vengono restituite tutte le normali trovate)
|
||||
|
||||
// Inizializzazione parametri
|
||||
dTotDist = 0 ;
|
||||
vVtN.clear() ;
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se riferimento di movimento già presente
|
||||
if ( m_frMove.IsValid()) {
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
|
||||
if ( AreSameFrame( frMove, m_frMove)) {
|
||||
// Eseguo controllo
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPositionHGAdv( ptCurr, vtDir, vVtN) ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
// Altrimenti eseguo controllo diretto
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPositionAdv( ptCurr, vtDir, vtMove, vVtN) ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti dell'insieme
|
||||
m_nTotPnt = int( vPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubSeries( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
m_nCurrPnt = 0 ;
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeries, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
}
|
||||
}
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
||||
{
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti da verificare
|
||||
for ( int i = nFirst ; i <= nLast ; ++ i) {
|
||||
// verifico il punto
|
||||
Vector3d vtTriaN ;
|
||||
double dMove = MyTestPositionHG( vPntM[i].first, vtDir, vtTriaN) ;
|
||||
vPntM[i].second = dMove ;
|
||||
if ( dMove < - EPS_SMALL)
|
||||
return false ;
|
||||
++ m_nCurrPnt ;
|
||||
// se singolo thread
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti multithread
|
||||
else {
|
||||
if ( m_bBreak)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff)
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Imposto il riferimento di movimento
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
m_frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
// Controllo la tolleranza lineare (se negativa non vanno fatti controlli sui punti medi)
|
||||
if ( dLinTol > -EPS_ZERO)
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
else
|
||||
m_frMove.Set( ORIG, vtMove) ;
|
||||
// Predispongo Hash Grid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
dLinTol = -1 ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti del path
|
||||
m_nTotPnt = int( lPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
@@ -140,8 +350,9 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol) ;
|
||||
ProcessEvents( 100, 0) ;
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
@@ -161,7 +372,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol) ;
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
@@ -173,7 +384,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 10) ;
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
@@ -185,18 +396,98 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
lPntM.pop_back() ;
|
||||
lPntM.splice( lPntM.end(), vlPntM[i]) ;
|
||||
}
|
||||
ProcessEvents( 100, 0) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol)
|
||||
CAvToolSurfTm::TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
||||
{
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
// NB. la posizione del punto non viene modificata :
|
||||
// get<0> vPntM[i] è il punto su cui viene posizionata la testa dell'utensile ( const)
|
||||
// get<1> vPntM[i] è il parametro di traslazione del punto lungo vtDir per evitare collisioni con i triangoli
|
||||
// get<2> vPntM[i] è un vettore di Vector3d contenente tutte le normali di tangenza ( a meno di 10 * EPS_SMALL)
|
||||
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti del path
|
||||
m_nTotPnt = int( vPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubSeriesAdv( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
m_nCurrPnt = 0 ;
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeriesAdv, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
}
|
||||
}
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff)
|
||||
{
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti
|
||||
@@ -206,11 +497,13 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
while ( itPntMCurr != lPntM.end()) {
|
||||
// verifico il punto
|
||||
ptCurr = itPntMCurr->first ;
|
||||
itPntMCurr->second = MyTestPositionHG( itPntMCurr->first, vtDir) ;
|
||||
if ( itPntMCurr->second < - EPS_SMALL)
|
||||
Vector3d vtTriaN ;
|
||||
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir, vtTriaN) ;
|
||||
itPntMCurr->second = dMove ;
|
||||
if ( dMove < - EPS_SMALL)
|
||||
return false ;
|
||||
// se esiste il punto precedente devo verificare il medio
|
||||
if ( itPntMPrev != lPntM.end()) {
|
||||
// se esiste il punto precedente e richiesto devo verificare il medio
|
||||
if ( itPntMPrev != lPntM.end() && dLinTol > 0) {
|
||||
MyTestMidPointHG( lPntM, itPntMPrev, itPntMCurr, ptPrev, ptCurr, vtDir, dLinTol, 1) ;
|
||||
}
|
||||
// passo al successivo
|
||||
@@ -222,7 +515,7 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 0) ;
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
@@ -236,10 +529,44 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
||||
{
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti da verificare
|
||||
for ( int i = nFirst ; i <= nLast ; ++ i) {
|
||||
// verifico il punto
|
||||
Point3d ptCurr = get<0>( vPntM[i]) ;
|
||||
get<1>( vPntM[i]) = MyTestPositionHGAdv( ptCurr, vtDir, get<2>( vPntM[i])) ;
|
||||
if ( get<1>( vPntM[i]) < - EPS_SMALL)
|
||||
return false ;
|
||||
++ m_nCurrPnt ;
|
||||
// se singolo thread
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti multithread
|
||||
else {
|
||||
if ( m_bBreak)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev)
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const
|
||||
{
|
||||
// se superato limite di ricursione, esco
|
||||
const int MAX_LEV = 10 ;
|
||||
@@ -249,7 +576,8 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
Point3d ptMid = Media( ptPrev, ptCurr, 0.5) ;
|
||||
// ne effettuo la correzione per evitare la collisione
|
||||
Point3d ptNewMid = ptMid ;
|
||||
double dMidMove = MyTestPositionHG( ptNewMid, vtDir) ;
|
||||
Vector3d vtTriaN ;
|
||||
double dMidMove = MyTestPositionHG( ptNewMid, vtDir, vtTriaN) ;
|
||||
if ( dMidMove < - EPS_SMALL)
|
||||
return false ;
|
||||
// massima distanza ammissibile
|
||||
@@ -258,7 +586,7 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
if ( abs(( Media( itPntMPrev->first, itPntMCurr->first, 0.5) - ptNewMid) * m_frMove.VersZ()) > 0.5 * dLinTol ||
|
||||
SqDist( itPntMPrev->first, itPntMCurr->first) > dMaxSqDist) {
|
||||
// aggiungo
|
||||
lPntM.emplace( itPntMCurr, ptNewMid, - dMidMove) ;
|
||||
lPntM.emplace( itPntMCurr, ptNewMid, dMidMove) ;
|
||||
auto itPntMMid = itPntMCurr ;
|
||||
-- itPntMMid ;
|
||||
// verifico intervallo precedente
|
||||
@@ -271,20 +599,48 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
|
||||
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const
|
||||
{
|
||||
// box dell'utensile con suo movimento
|
||||
BBox3d b3Tool ;
|
||||
// utensile
|
||||
b3Tool.Add( ptT) ;
|
||||
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
|
||||
if ( vtDir.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// aggiungo movimento
|
||||
BBox3d b3Moved = b3Tool ;
|
||||
b3Moved.Translate( MAX_MOVE * vtMove) ;
|
||||
b3Tool.Add( b3Moved) ;
|
||||
|
||||
// determino movimento minimo per evitare collisione con superfici
|
||||
double dTotDist = 0 ;
|
||||
vtTriaN = V_NULL ;
|
||||
for ( auto pStm : m_vSTM) {
|
||||
Triangle3d Tria ;
|
||||
for ( int nTria = pStm->GetFirstTriangle( Tria) ;
|
||||
nTria != SVT_NULL ;
|
||||
nTria = pStm->GetNextTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * m_frMove.VersZ() ;
|
||||
INTVECTOR vTria ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
|
||||
for ( int nTria : vTria) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStm->GetTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * vtMove ;
|
||||
vtTriaN = Tria.GetN() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,7 +649,61 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
CAvToolSurfTm::MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const
|
||||
{
|
||||
// box dell'utensile con suo movimento
|
||||
BBox3d b3Tool ;
|
||||
// utensile
|
||||
b3Tool.Add( ptT) ;
|
||||
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
|
||||
if ( vtDir.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// aggiungo movimento
|
||||
BBox3d b3Moved = b3Tool ;
|
||||
b3Moved.Translate( MAX_MOVE * vtMove) ;
|
||||
b3Tool.Add( b3Moved) ;
|
||||
|
||||
// determino movimento minimo per evitare collisione con superfici
|
||||
double dTotDist = 0 ;
|
||||
vVtTriaN.clear() ;
|
||||
for ( auto pStm : m_vSTM) {
|
||||
INTVECTOR vTria ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
|
||||
for ( int nTria : vTria) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStm->GetTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
// se devo traslare il punto, c'è collisione
|
||||
if ( dDist > EPS_SMALL) {
|
||||
if ( dDist > 10 * EPS_SMALL) {
|
||||
vVtTriaN.clear() ;
|
||||
dTotDist += dDist ;
|
||||
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
|
||||
}
|
||||
vVtTriaN.push_back( Tria.GetN()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const
|
||||
{
|
||||
// calcolo box utensile nel riferimento di movimento
|
||||
BBox3d b3Tool ;
|
||||
@@ -313,8 +723,10 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
double dTotDist = 0 ;
|
||||
vtTriaN = V_NULL ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Tool, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
@@ -330,11 +742,70 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * m_frMove.VersZ() ;
|
||||
vtTriaN = Tria.GetN() ;
|
||||
}
|
||||
else if ( dDist < -EPS_SMALL)
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const
|
||||
{
|
||||
// calcolo box utensile nel riferimento di movimento
|
||||
BBox3d b3Tool ;
|
||||
Point3d ptTL = ptT ; ptTL.ToLoc( m_frMove) ;
|
||||
Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ;
|
||||
b3Tool.Add( ptTL) ;
|
||||
b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ;
|
||||
if ( vtDirL.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDirL.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDirL.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDirL.y * vtDirL.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
double dTotDist = 0. ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Tool, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
// recupero la superficie
|
||||
int nInd = vnIds[i] ;
|
||||
int nSurf = GetSurfInd( nInd) ;
|
||||
if ( nSurf == -1)
|
||||
return -1 ;
|
||||
// recupero il triangolo
|
||||
int nT = nInd - m_vBaseInd[nSurf] ;
|
||||
Triangle3d Tria ;
|
||||
if ( ! m_vSTM[nSurf]->GetTriangle( nT, Tria))
|
||||
return -1 ;
|
||||
// calcolo della collisione
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
// se devo traslare il punto, c'è collisione
|
||||
if ( dDist > EPS_SMALL) {
|
||||
if ( dDist > 10 * EPS_SMALL) {
|
||||
vVtTriaN.clear() ;
|
||||
dTotDist += dDist ;
|
||||
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
|
||||
}
|
||||
vVtTriaN.push_back( Tria.GetN()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
@@ -345,7 +816,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// verifico esistenza superfici
|
||||
if ( m_vSTM.size() == 0 || m_vBaseInd.size() < m_vSTM.size() + 1)
|
||||
if ( m_vSTM.empty() || m_vBaseInd.size() < m_vSTM.size() + 1)
|
||||
return false ;
|
||||
// creo HashGrid 2d
|
||||
const int LIM_HG_TRIA = 256 ;
|
||||
@@ -372,7 +843,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
CAvToolSurfTm::GetSurfInd( int nT)
|
||||
CAvToolSurfTm::GetSurfInd( int nT) const
|
||||
{
|
||||
// verifico la presenza di almeno un intervallo
|
||||
if ( m_vBaseInd.size() < 2)
|
||||
|
||||
+32
-7
@@ -34,22 +34,47 @@ class CAvToolSurfTm : public ICAvToolSurfTm
|
||||
{ return m_Tool.GetRadius() ; }
|
||||
double GetToolHeight( void) const override
|
||||
{ return m_Tool.GetHeigth() ; }
|
||||
double GetToolTipHeight( void) const override
|
||||
{ return m_Tool.GetTipHeigth() ; } ;
|
||||
double GetToolTipRadius( void) const override
|
||||
{ return m_Tool.GetTipRadius() ; } ;
|
||||
double GetToolCornRadius( void) const override
|
||||
{ return m_Tool.GetCornRadius() ; } ;
|
||||
CISURFTMPVECTOR GetvStm( void) const {
|
||||
CISURFTMPVECTOR vcStm ;
|
||||
for ( int i = 0 ; i < int( m_vSTM.size()) ; ++ i)
|
||||
vcStm.emplace_back( CloneSurfTriMesh( m_vSTM[i])) ;
|
||||
return vcStm ;
|
||||
}
|
||||
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
|
||||
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
|
||||
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist) override ;
|
||||
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol) override ;
|
||||
|
||||
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ;
|
||||
bool TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, VCT3DVECTOR& vVtN) const override ;
|
||||
|
||||
bool TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
|
||||
bool TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
|
||||
|
||||
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ;
|
||||
|
||||
public :
|
||||
CAvToolSurfTm( void) ;
|
||||
bool Clear( void) ;
|
||||
|
||||
private :
|
||||
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol) ;
|
||||
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir) ;
|
||||
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) ;
|
||||
bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
|
||||
bool TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
|
||||
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff) ;
|
||||
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const ;
|
||||
double MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const ;
|
||||
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const ;
|
||||
double MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const ;
|
||||
bool MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) ;
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ;
|
||||
bool PrepareHashGrid( void) ;
|
||||
int GetSurfInd( int nT) ;
|
||||
int GetSurfInd( int nT) const ;
|
||||
|
||||
private :
|
||||
typedef std::vector<const SurfTriMesh*> CSURFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
#include "CAvToolTriangle.h"
|
||||
#include "IntersLineSurfStd.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "CDeUtility.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
@@ -2503,7 +2503,7 @@ DiskSegmentEscapeDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
|
||||
double dSegDist = 0. ;
|
||||
for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) {
|
||||
// Soluzione interna al segmento
|
||||
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen) {
|
||||
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen + EPS_ZERO) {
|
||||
Point3d ptC = ptSeg + vdRoots[nSol] * vtSeg ;
|
||||
// Distanza del punto soluzione dal piano del disco nella posizione iniziale
|
||||
double dCurDist = PointPlaneSignedDist( ptC, ptDiskCen, vtMove) ;
|
||||
|
||||
+1
-1
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "CDeCylTria.h"
|
||||
#include "CDeConvexTorusTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+1
-2
@@ -12,11 +12,10 @@
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "CDeTriaTria.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "CDeUtility.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+7938
-1834
File diff suppressed because it is too large
Load Diff
+26
-23
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2014
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ChainCurves.cpp Data : 20.07.14 Versione : 1.5g3
|
||||
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
|
||||
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
|
||||
// curve composite a partire dalle curve date.
|
||||
//
|
||||
//
|
||||
@@ -43,10 +43,10 @@ bool
|
||||
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
|
||||
const Point3d& ptEnd, const Vector3d& vtEnd)
|
||||
{
|
||||
// verifico validità Id
|
||||
// verifico validità Id
|
||||
if ( nId <= 0)
|
||||
return false ;
|
||||
// verifico non sia già stata aggiunta la stessa entità
|
||||
// verifico non sia già stata aggiunta la stessa entità
|
||||
if ( ! m_sCrvId.insert( nId).second)
|
||||
return true ;
|
||||
// inserisco i dati della curva nel vettore
|
||||
@@ -68,7 +68,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
m_bIsFork = false ;
|
||||
m_vFork.clear() ;
|
||||
|
||||
// recupero l'entità più vicina al punto di start
|
||||
// recupero l'entità più vicina al punto di start
|
||||
int nStart ;
|
||||
INTVECTOR vStart ;
|
||||
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
|
||||
@@ -82,7 +82,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
// tolgo dal grid
|
||||
RemoveEntityFromGrid( nId) ;
|
||||
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
bool bSkip = false ;
|
||||
if ( bHaltOnFork) {
|
||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptEnd) ;
|
||||
@@ -93,7 +93,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
}
|
||||
}
|
||||
|
||||
// concateno dopo la fine dell'entità di partenza
|
||||
// concateno dopo la fine dell'entità di partenza
|
||||
INTVECTOR vIdsAfter ;
|
||||
bool bClosed = false ;
|
||||
if ( ! bSkip && ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd,
|
||||
@@ -102,7 +102,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
bool bRevSkip = false ;
|
||||
if ( bHaltOnFork) {
|
||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptStart) ;
|
||||
@@ -113,7 +113,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
}
|
||||
}
|
||||
|
||||
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
|
||||
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
|
||||
INTVECTOR vIdsBefore ;
|
||||
if ( ! bClosed) {
|
||||
bool bRevClosed ;
|
||||
@@ -258,7 +258,7 @@ ChainCurves::RemoveEntityFromGrid( int nId)
|
||||
bool
|
||||
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
|
||||
{
|
||||
// numero di entità candidate
|
||||
// numero di entità candidate
|
||||
int nSize = int( vStart.size()) ;
|
||||
|
||||
// se nessuna, errore
|
||||
@@ -273,7 +273,7 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
|
||||
|
||||
// altrimenti, cerco la migliore
|
||||
int nI = - 1 ;
|
||||
double dSqDistMin = SQ_INFINITO ;
|
||||
double dDistMin = INFINITO ;
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
// recupero indice e verso
|
||||
int nId = abs( vStart[i]) - 1 ;
|
||||
@@ -281,9 +281,12 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
|
||||
// calcolo un punto vicino all'estremo lungo la tangente
|
||||
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
|
||||
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
|
||||
double dSqDist = SqDist( ptStart, ptNear) ;
|
||||
if ( dSqDist < dSqDistMin) {
|
||||
dSqDistMin = dSqDist ;
|
||||
double dDist = Dist( ptStart, ptNear) ;
|
||||
// tengo il segmento più vicino al punto
|
||||
// favorendo eventualmente quello equiverso se entro EPS da un concorrente
|
||||
if ( dDist < dDistMin - EPS_SMALL ||
|
||||
((dDist < dDistMin + EPS_SMALL) && bEquiv && vStart[nI] < 0)) {
|
||||
dDistMin = dDist ;
|
||||
nI = i ;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +305,7 @@ bool
|
||||
ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
|
||||
{
|
||||
INTVECTOR vMyNext = vNext ;
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
int nM = -1 ;
|
||||
Point3d ptRef ;
|
||||
double dSqMinDist = m_dToler * m_dToler ;
|
||||
@@ -319,19 +322,19 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) {
|
||||
// salto l'entità più vicina
|
||||
// salto l'entità più vicina
|
||||
if ( i == nM)
|
||||
continue ;
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyNext[i]) - 1 ;
|
||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
||||
// verifico se più vicino al più vicino
|
||||
// verifico se più vicino al più vicino
|
||||
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
|
||||
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
|
||||
if ( dRefSqDist < dCurrSqDist)
|
||||
vMyNext[i] = 0 ;
|
||||
}
|
||||
// cerco la direzione più vicina
|
||||
// cerco la direzione più vicina
|
||||
int nI = -1 ;
|
||||
int nF = 0 ;
|
||||
INTVECTOR vFork ;
|
||||
@@ -343,7 +346,7 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyNext[i]) - 1 ;
|
||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
++ nF ;
|
||||
vFork.push_back( vMyNext[i]) ;
|
||||
// se vietata inversione, salto se controverso
|
||||
@@ -387,7 +390,7 @@ bool
|
||||
ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev)
|
||||
{
|
||||
INTVECTOR vMyPrev = vPrev ;
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
int nM = -1 ;
|
||||
Point3d ptRef ;
|
||||
double dSqMinDist = m_dToler * m_dToler ;
|
||||
@@ -404,19 +407,19 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) {
|
||||
// salto l'entità più vicina
|
||||
// salto l'entità più vicina
|
||||
if ( i == nM)
|
||||
continue ;
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyPrev[i]) - 1 ;
|
||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
||||
// verifico se più vicino al più vicino
|
||||
// verifico se più vicino al più vicino
|
||||
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
|
||||
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
|
||||
if ( dRefSqDist < dCurrSqDist)
|
||||
vMyPrev[i] = 0 ;
|
||||
}
|
||||
// cerco la direzione più vicina
|
||||
// cerco la direzione più vicina
|
||||
int nI = - 1 ;
|
||||
int nF = 0 ;
|
||||
double dProScaMax = - 1.1 ;
|
||||
@@ -428,7 +431,7 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyPrev[i]) - 1 ;
|
||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
++ nF ;
|
||||
vFork.push_back( vMyPrev[i]) ;
|
||||
// se vietata inversione, salto se controverso
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+2
-1
@@ -398,7 +398,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
|
||||
if ( dLenA > ( dRad - EPS_ZERO))
|
||||
dLenH = 0 ;
|
||||
else
|
||||
dLenH= sqrt( dRad * dRad - dLenA * dLenA) ;
|
||||
dLenH = sqrt( dRad * dRad - dLenA * dLenA) ;
|
||||
// versore dal punto medio della corda al centro
|
||||
Vector3d vtH = vtA / dLenA ;
|
||||
vtH.Rotate( Z_AX, 0, ( bCCW ? 1 : -1)) ;
|
||||
@@ -410,6 +410,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
|
||||
m_dRad = dRad ;
|
||||
// calcolo il versore di start
|
||||
m_VtS = ( ptStart - m_PtCen) / m_dRad ;
|
||||
m_VtS.Normalize() ;
|
||||
// calcolo l'angolo al centro
|
||||
bool bDet ;
|
||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
||||
|
||||
+1092
-46
File diff suppressed because it is too large
Load Diff
@@ -33,4 +33,5 @@ bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ;
|
||||
bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ;
|
||||
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
|
||||
+245
-6
@@ -13,13 +13,13 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveAux.h"
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointCrvBezier.h"
|
||||
#include "BiArcs.h"
|
||||
#include "GeoConst.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
@@ -27,12 +27,16 @@
|
||||
#include "Bernstein.h"
|
||||
#include "deCasteljau.h"
|
||||
#include "Voronoi.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveArc.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/ENkPolynomial.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include <array>
|
||||
|
||||
using namespace std ;
|
||||
@@ -138,6 +142,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::SetControlWeight( int nInd, double dW)
|
||||
{
|
||||
// verifico validità, razionalità e indice
|
||||
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
m_vWeCtrl[nInd] = dW ;
|
||||
|
||||
// annullo analisi presenza singolarità
|
||||
m_dParSing = - 2 ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
@@ -195,6 +225,35 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
SetControlPoint( 1, ptNew1, dW) ;
|
||||
SetControlPoint( 2, ptNew2, dW) ;
|
||||
SetControlPoint( 3, ptEnd, 1) ;
|
||||
|
||||
//// anziché usare una bezier cubica approssimo le eliche con più bezier quadratiche razionali.
|
||||
//// più è grande l'angolo al centro dell'arco e maggiore sarà l'errore di approssimazione
|
||||
//
|
||||
// // quadratica razionale
|
||||
// // peso del punto di controllo intermedio
|
||||
// double dW = dCosAhalf ;
|
||||
// // calcolo dei punti di controllo
|
||||
// Point3d ptStart ;
|
||||
// crArc.GetStartPoint( ptStart) ;
|
||||
// Point3d ptEnd ;
|
||||
// crArc.GetEndPoint( ptEnd) ;
|
||||
// // Point3d ptMed = Media( ptStart, ptEnd, 0.5) ;
|
||||
// //Vector3d vtDir = ptMed - crArc.GetCenter() ;
|
||||
// // Point3d ptNew = crArc.GetCenter() + vtDir / ( dCosAhalf * dCosAhalf) ;
|
||||
// Vector3d vtStart ; crArc.GetStartDir( vtStart) ;
|
||||
// Vector3d vtEnd ; crArc.GetEndDir( vtEnd) ;
|
||||
// PtrOwner<CurveLine> pCrvLine1( CreateBasicCurveLine()) ;
|
||||
// pCrvLine1->SetPVL( ptStart, vtStart, 10) ;
|
||||
// PtrOwner<CurveLine> pCrvLine2( CreateBasicCurveLine()) ;
|
||||
// pCrvLine2->SetPVL( ptEnd, vtEnd, 10) ;
|
||||
// IntersLineLine ill( *pCrvLine1, *pCrvLine2, false) ;
|
||||
// IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||
// Point3d ptNew = 0.5 * (iccInfo.IciA->ptI + iccInfo.IciB->ptI) ;
|
||||
// // inserimento nella curva dei punti di controllo con i pesi
|
||||
// Init( 2, true) ;
|
||||
// SetControlPoint( 0, ptStart, 1) ;
|
||||
// SetControlPoint( 1, ptNew, dW) ;
|
||||
// SetControlPoint( 2, ptEnd, 1) ;
|
||||
}
|
||||
|
||||
// copio estrusione e spessore
|
||||
@@ -204,6 +263,30 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::FromLine( const ICurveLine& crLine)
|
||||
{
|
||||
if ( ! crLine.IsValid())
|
||||
return false ;
|
||||
double dWeight = 1 ;
|
||||
int nCount = 0 ;
|
||||
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
|
||||
SetControlPoint( nCount, ptStart, dWeight) ;
|
||||
++nCount ;
|
||||
double dPart = 1. / m_nDeg ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
double dU = i * dPart ;
|
||||
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
|
||||
SetControlPoint( nCount, ptMid, dWeight) ;
|
||||
++nCount ;
|
||||
}
|
||||
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
|
||||
SetControlPoint( nCount, ptEnd, dWeight) ;
|
||||
++nCount ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::IsAPoint( void) const
|
||||
@@ -1486,7 +1569,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
|
||||
return false ;
|
||||
vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ;
|
||||
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
}
|
||||
@@ -1723,12 +1806,24 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
// verifico che i trim non cancellino interamente la curva
|
||||
if ( dUStartTrim > dUEndTrim - EPS_PARAM)
|
||||
return false ;
|
||||
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
|
||||
Point3d ptStart ;
|
||||
if( m_bRat)
|
||||
GetPointD1D2( dUStartTrim, ptStart) ;
|
||||
// trim finale
|
||||
if ( ! TrimEndAtParam( dUEndTrim))
|
||||
return false ;
|
||||
// trim iniziale con il parametro opportunamente ricalcolato
|
||||
double dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
return TrimStartAtParam( dNewUStartTrim) ;
|
||||
double dNewUStartTrim ;
|
||||
if( m_bRat)
|
||||
GetParamAtPoint( ptStart, dNewUStartTrim) ;
|
||||
else
|
||||
dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
//trim iniziale
|
||||
if( ! TrimStartAtParam( dNewUStartTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1744,7 +1839,10 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
return TrimStartAtParam( dUTrim) ;
|
||||
if( ! TrimStartAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1760,7 +1858,10 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
return TrimEndAtParam( dUTrim) ;
|
||||
if( ! TrimEndAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -2152,3 +2253,141 @@ CurveBezier::ResetVoronoiObject() const
|
||||
delete m_pVoronoiObj ;
|
||||
m_pVoronoiObj = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeRational( void)
|
||||
{
|
||||
if ( m_bRat)
|
||||
return true ;
|
||||
// creo il vettore dei pesi e li setto tutti a 1
|
||||
m_vWeCtrl.assign( m_nDeg + 1, 1) ;
|
||||
// aggiorno il flag rational
|
||||
m_bRat = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeRationalStandardForm( void)
|
||||
{
|
||||
if ( ! m_bRat)
|
||||
return false ;
|
||||
double dW0 = m_vWeCtrl.front() ;
|
||||
double dWn = m_vWeCtrl.back() ;
|
||||
if ( dW0 > 1 - EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
return true ;
|
||||
if ( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
return false ;
|
||||
|
||||
// formula del Farin
|
||||
double dCoeff = pow( dW0 / dWn, 1. / m_nDeg) ;
|
||||
for ( int i = 0 ; i < m_nDeg + 1 ; ++i)
|
||||
m_vWeCtrl[i] *= Pow( dCoeff, i) / dW0 ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeNonRational( double dTol)
|
||||
{
|
||||
if ( ! m_bRat)
|
||||
return true ;
|
||||
|
||||
// controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo
|
||||
bool bIsActualRat = false ;
|
||||
for ( int i = 0 ; i < m_nDeg ; ++i) {
|
||||
if ( abs( m_vWeCtrl[i] - 1) > EPS_SMALL) {
|
||||
bIsActualRat = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
bool bOk = true ;
|
||||
if ( ! bIsActualRat) {
|
||||
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
|
||||
for ( int p = 0 ; p < m_nDeg ; ++p) {
|
||||
Point3d pt = GetControlPoint( p) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// provo ad approssimare la curva di bezier con una controparte non razionale
|
||||
int nDeg = m_nDeg ;
|
||||
// punto di rientro in caso fallisca il primo tentativo
|
||||
retry :
|
||||
nDeg += 2 ;
|
||||
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
|
||||
pNewBez->Init( nDeg, false) ;
|
||||
PNTVECTOR vPntCtrl ;
|
||||
PNTVECTOR vPntSampling ;
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
vPntCtrl.push_back( pt) ;
|
||||
}
|
||||
vPntSampling = vPntCtrl ;
|
||||
int c = 0 ;
|
||||
double dErr = INFINITO ;
|
||||
while ( dErr > dTol && c < 100) {
|
||||
double dErrMax = 0 ;
|
||||
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
Vector3d vDiff = vPntSampling[p] - pt ;
|
||||
double dErrLoc = vDiff.Len() ;
|
||||
if( dErrLoc > dErrMax)
|
||||
dErrMax = dErrLoc ;
|
||||
// aggiorno il vettore dei punti di controllo della nuova curva
|
||||
vPntCtrl[p] += vDiff ;
|
||||
}
|
||||
dErr = dErrMax ;
|
||||
// aggiorno i punti di controllo della nuova curva
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i)
|
||||
pNewBez->SetControlPoint( i, vPntCtrl[i]) ;
|
||||
++c ;
|
||||
}
|
||||
|
||||
// calcolo l'errore di approssimazione sulla curva
|
||||
CalcBezierApproxError( this, pNewBez, dErr) ;
|
||||
bOk = dErr < dTol ;
|
||||
if ( bOk) {
|
||||
// aggiorno la curva di bezier originale con quella approssimata
|
||||
Init( nDeg, false) ;
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
|
||||
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
|
||||
}
|
||||
}
|
||||
else if ( nDeg < m_nDeg + 4)
|
||||
goto retry ;
|
||||
}
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::IsALine( void) const
|
||||
{
|
||||
Point3d ptStart ; GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; GetEndPoint( ptEnd) ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
Point3d ptCtrl = GetControlPoint( i) ;
|
||||
DistPointLine dpl( ptCtrl, ptStart, ptEnd) ;
|
||||
double dDist = 0 ; dpl.GetDist( dDist) ;
|
||||
if( dDist > EPS_SMALL)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PNTVECTOR
|
||||
CurveBezier::GetAllControlPoints( void) const
|
||||
{
|
||||
PNTVECTOR vPntCtrl = m_vPtCtrl ;
|
||||
return vPntCtrl ;
|
||||
}
|
||||
+8
-1
@@ -137,7 +137,9 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool Init( int nDeg, bool bIsRational) override ;
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ;
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
|
||||
bool SetControlWeight( int nInd, double dW) override ;
|
||||
bool FromArc( const ICurveArc& crArc) override ;
|
||||
bool FromLine( const ICurveLine& crLine) override ;
|
||||
int GetDegree( void) const override
|
||||
{ return m_nDeg ; }
|
||||
bool IsRational( void) const override
|
||||
@@ -147,6 +149,11 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
double GetControlWeight( int nInd, bool* pbOk = NULL) const override ;
|
||||
bool GetControlPolygonLength( double& dLen) const override ;
|
||||
int GetSingularParam( double& dPar) const override ;
|
||||
bool MakeRational( void) override ;
|
||||
bool MakeRationalStandardForm( void) override ;
|
||||
bool MakeNonRational( double dTol) override ;
|
||||
bool IsALine( void) const override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ; // non aggiunta in interfaccia
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -190,7 +197,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
static const int MAXDEG = 11 ;
|
||||
static const int MAXDEG = 21 ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
|
||||
+14
-11
@@ -16,8 +16,8 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "BiArcs.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyArc.h"
|
||||
@@ -439,12 +439,12 @@ CurveByApprox::CalcSplitPoints( double dLinTol, double dAngTolDeg, double dLinFe
|
||||
m_vSplits.push_back(i) ;
|
||||
continue ;
|
||||
}
|
||||
// verifico linearità del tratto precedente
|
||||
// verifico linearità del tratto precedente
|
||||
bool bPrevLin = vtPrev.SqLen() > dSqLinFea &&
|
||||
( m_vNextDer[i-1] * m_vPrevDer[i]) > dAngTolCos &&
|
||||
( vtPrev ^ m_vNextDer[i-1]).SqLen() < dSqLinTol &&
|
||||
( vtPrev ^ m_vPrevDer[i]).SqLen() < dSqLinTol ;
|
||||
// verifico linearità del tratto successivo
|
||||
// verifico linearità del tratto successivo
|
||||
bool bNextLin = vtNext.SqLen() > dSqLinFea &&
|
||||
( m_vNextDer[i] * m_vPrevDer[i+1]) > dAngTolCos &&
|
||||
( vtNext ^ m_vNextDer[i]).SqLen() < dSqLinTol &&
|
||||
@@ -483,7 +483,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
double dMaxDist ;
|
||||
|
||||
// se la polilinea ha più di 2 punti
|
||||
// se la polilinea ha più di 2 punti
|
||||
if ( PL.GetPointNbr() > 2) {
|
||||
// calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier
|
||||
int nI ;
|
||||
@@ -501,11 +501,12 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
ptP1 = m_vPnt[nI] ;
|
||||
m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ;
|
||||
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
|
||||
// forzo la spezzatura della curva
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 2 * dLinTol ;
|
||||
}
|
||||
// se la polilinea è formata da 2 punti
|
||||
// se la polilinea è formata da 2 punti
|
||||
else if ( PL.GetPointNbr() == 2) {
|
||||
// se molto vicini, esco
|
||||
double dLen ;
|
||||
@@ -524,13 +525,15 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
|
||||
// se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco
|
||||
if ( nLev >= MAX_LEV) {
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 0 ;
|
||||
// segnalo situazione per debug
|
||||
if ( GetEGkDebugLev() >= 5)
|
||||
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions")
|
||||
}
|
||||
|
||||
// se lunghezza abbastanza picccola, forzo l'accettazione della curva
|
||||
// se lunghezza abbastanza piccola, forzo l'accettazione della curva
|
||||
double dLen ;
|
||||
if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL)
|
||||
dMaxDist = 0 ;
|
||||
@@ -561,7 +564,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
return false ;
|
||||
}
|
||||
|
||||
// spezzo l'intervallo in due parti a metà
|
||||
// spezzo l'intervallo in due parti a metà
|
||||
double dParStart, dParEnd ;
|
||||
if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd))
|
||||
return false ;
|
||||
@@ -569,9 +572,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
PolyLine PL2 ;
|
||||
if ( ! PL.Split( dParMid, PL2))
|
||||
return false ;
|
||||
// prima metà
|
||||
// prima metà
|
||||
if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA))
|
||||
return false ;
|
||||
// seconda metà
|
||||
// seconda metà
|
||||
return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ;
|
||||
}
|
||||
|
||||
+143
-90
@@ -14,7 +14,6 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistPointCrvComposite.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
@@ -192,7 +192,7 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
return false ;
|
||||
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && m_nStatus == TO_VERIFY))
|
||||
if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && ( m_nStatus == TO_VERIFY || m_nStatus == IS_A_POINT)))
|
||||
return false ;
|
||||
|
||||
// controllo la tolleranza
|
||||
@@ -224,8 +224,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyStart( ptEnd))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyStart( ptEnd)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptEnd, ptCrvEnd) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
@@ -246,8 +249,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyEnd( ptStart))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyEnd( ptStart)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptCrvStart, ptStart) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
@@ -291,9 +297,15 @@ CurveComposite::Close( void)
|
||||
return true ;
|
||||
// se molto vicini li modifico
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, 10 * EPS_SMALL)) {
|
||||
// se un solo arco
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
|
||||
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
|
||||
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
|
||||
}
|
||||
// caso generale
|
||||
Point3d ptMid = Media( ptStart, ptEnd) ;
|
||||
if ( ! ModifyStart( ptMid) ||
|
||||
! ModifyEnd( ptMid))
|
||||
if ( ! m_CrvSmplS.front()->ModifyStart( ptMid) ||
|
||||
! m_CrvSmplS.back()->ModifyEnd( ptMid))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti aggiungo la linea di chiusura
|
||||
@@ -369,9 +381,10 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
|
||||
return false ;
|
||||
|
||||
// ciclo di inserimento dei segmenti che uniscono i punti
|
||||
double dParIni, dParFin ;
|
||||
Point3d ptIni, ptFin ;
|
||||
PL.GetFirstPoint( ptIni) ;
|
||||
while ( PL.GetNextPoint( ptFin)) {
|
||||
PL.GetFirstUPoint( &dParIni, &ptIni) ;
|
||||
while ( PL.GetNextUPoint( &dParFin, &ptFin)) {
|
||||
// se i punti della coppia coincidono, passo alla coppia successiva
|
||||
if ( AreSamePointApprox( ptIni, ptFin))
|
||||
continue ;
|
||||
@@ -382,10 +395,14 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
|
||||
// assegno i punti estremi
|
||||
if ( ! pCrvLine->Set( ptIni, ptFin))
|
||||
return false ;
|
||||
// assegno i parametri degli estremi
|
||||
pCrvLine->SetTempParam( dParIni, 0) ;
|
||||
pCrvLine->SetTempParam( dParFin, 1) ;
|
||||
// aggiungo la retta alla curva composita
|
||||
if ( ! AddSimpleCurve( Release( pCrvLine)))
|
||||
return false ;
|
||||
// aggiorno dati prossimo punto iniziale
|
||||
dParIni = dParFin ;
|
||||
ptIni = ptFin ;
|
||||
}
|
||||
|
||||
@@ -598,6 +615,10 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc)
|
||||
if ( ! AddCurve( *pCrv))
|
||||
return false ;
|
||||
}
|
||||
if ( ccSrc.m_nStatus == IS_A_POINT) {
|
||||
m_ptStart = ccSrc.m_ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -656,7 +677,7 @@ CurveComposite::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
while ( pCrvSmpl != nullptr && i < MAX_CRV) {
|
||||
// assegno ed emetto nome e tipo della curva semplice
|
||||
sOut += "#" + ToString( i) + " " + pCrvSmpl->GetTitle() + szNewLine ;
|
||||
// salvataggio della curva semplice
|
||||
// dati della curva semplice
|
||||
if ( ! pCrvSmpl->Dump( sOut, bMM, szNewLine))
|
||||
return false ;
|
||||
// passo alla successiva
|
||||
@@ -745,7 +766,7 @@ CurveComposite::Load( NgeReader& ngeIn)
|
||||
ICurve* pCrv = ::GetCurve( pGeoO) ;
|
||||
bOk = bOk && ( pCrv != nullptr && pCrv->IsSimple()) ;
|
||||
// aggiungo questa curva (sicuramente semplice)
|
||||
bOk = bOk && AddSimpleCurve( pCrv) ;
|
||||
bOk = bOk && AddSimpleCurve( pCrv, true, 10 * EPS_SMALL) ;
|
||||
// se errore
|
||||
if ( ! bOk)
|
||||
return false ;
|
||||
@@ -878,10 +899,15 @@ CurveComposite::TestClosure( void)
|
||||
Point3d ptEnd ; m_CrvSmplS.back()->GetEndPoint( ptEnd) ;
|
||||
// se distanza superiore al limite ridotto forzo i punti a coincidere
|
||||
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
|
||||
// se un solo arco
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
|
||||
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
|
||||
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
|
||||
}
|
||||
// caso generale
|
||||
Point3d ptM = Media( ptStart, ptEnd) ;
|
||||
if ( ! m_CrvSmplS.front()->ModifyStart( ptM) ||
|
||||
! m_CrvSmplS.back()->ModifyEnd( ptM))
|
||||
return false ;
|
||||
return ( m_CrvSmplS.front()->ModifyStart( ptM) &&
|
||||
m_CrvSmplS.back()->ModifyEnd( ptM)) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -937,6 +963,8 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con
|
||||
return false ;
|
||||
}
|
||||
} break ;
|
||||
default :
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
@@ -1761,10 +1789,11 @@ bool
|
||||
CurveComposite::AddPoint( const Point3d& ptStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != TO_VERIFY)
|
||||
if ( m_nStatus != TO_VERIFY && m_nStatus != IS_A_POINT)
|
||||
return false ;
|
||||
// assegno il punto
|
||||
// assegno il punto e setto lo stato
|
||||
m_ptStart = ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1808,7 +1837,7 @@ bool
|
||||
CurveComposite::AddLine( const Point3d& ptNew, bool bEndOrStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK && m_nStatus != TO_VERIFY)
|
||||
if ( m_nStatus != OK && m_nStatus != IS_A_POINT)
|
||||
return false ;
|
||||
// costruisco la linea
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
@@ -2972,7 +3001,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
|
||||
m_CrvSmplS.pop_front() ;
|
||||
}
|
||||
// eseguo mini verifica
|
||||
m_nStatus = ( m_CrvSmplS.size() > 0 ? OK : TO_VERIFY) ;
|
||||
m_nStatus = ( ! m_CrvSmplS.empty() ? OK : TO_VERIFY) ;
|
||||
// assegno estrusione e spessore della curva composita
|
||||
pCrv->SetExtrusion( m_VtExtr) ;
|
||||
pCrv->SetThickness( m_dThick) ;
|
||||
@@ -3151,11 +3180,26 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// se precedente molto corta
|
||||
double dLenP ;
|
||||
if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) {
|
||||
// se abbastanza allineata alla successiva
|
||||
// se abbastanza allineata alla successiva
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptStart ;
|
||||
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
|
||||
bool bModifStart = ( pCrvC->GetType() != CRV_ARC) ;
|
||||
if ( ! bModifStart) {
|
||||
/* nel caso in cui la curva corrente sia un arco, bisogna controllare che la somma tra
|
||||
l'angolo al centro e l'angolo sotteso dalla curva precedente non superi l'angolo giro; in
|
||||
caso positivo, la modifica del punto inziale dell'arco ( curva corrente) rimoverebbe
|
||||
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
|
||||
Point3d ptS ; pCrvP->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrvC->GetStartPoint( ptE) ;
|
||||
const ICurveArc* pArcC = GetBasicCurveArc( pCrvC) ;
|
||||
double dAngRef = ( Dist( ptS, ptE) / pArcC->GetRadius()) * RADTODEG ;
|
||||
bModifStart = ( abs( pArcC->GetAngCenter()) + dAngRef < ANG_FULL - 10 * EPS_ANG_SMALL) ;
|
||||
|
||||
}
|
||||
if ( bModifStart) {
|
||||
Point3d ptStart ;
|
||||
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se corrente molto corta
|
||||
@@ -3164,10 +3208,24 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// se abbastanza allineata alla precedente
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptEnd ;
|
||||
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
|
||||
bool bModifEnd = ( pCrvP->GetType() != CRV_ARC) ;
|
||||
if ( ! bModifEnd) {
|
||||
/* nel caso in cui la curva predecente sia un arco, bisogna controllare che la somma tra
|
||||
l'angolo al centro e l'angolo sotteso dalla curva corrente non superi l'angolo giro; in
|
||||
caso positivo, la modifica del punto finale dell'arco ( curva precedente) rimoverebbe
|
||||
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
|
||||
Point3d ptS ; pCrvP->GetEndPoint( ptS) ;
|
||||
Point3d ptE ; pCrvC->GetEndPoint( ptE) ;
|
||||
const CurveArc* pArcP = GetBasicCurveArc( pCrvP) ;
|
||||
double dAngRef = ( Dist( ptS, ptE) / pArcP->GetRadius()) * RADTODEG ;
|
||||
bModifEnd = ( abs( pArcP->GetAngCenter()) + dAngRef < ANG_FULL - 10. * EPS_ANG_SMALL) ;
|
||||
}
|
||||
if ( bModifEnd) {
|
||||
Point3d ptEnd ;
|
||||
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// coefficiente deduzione tolleranza
|
||||
const double COEFF_TOL = 0.7 ;
|
||||
// se entrambe rette
|
||||
@@ -3222,61 +3280,69 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// verifico di non superare l'angolo giro al centro
|
||||
if ( abs( pArcP->GetAngCenter() + pArcC->GetAngCenter()) > ANG_FULL + EPS_ANG_SMALL)
|
||||
return 0 ;
|
||||
// se archi piatti
|
||||
if ( pArcP->IsPlane() && pArcC->IsPlane()) {
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Point3d ptP2 ;
|
||||
pArcP->GetEndPoint( ptP2) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ;
|
||||
if ( bCirc)
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// verifico normale al piano dell'arco
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
// verifico se archi piatti
|
||||
bool bPlaneArcs = pArcP->IsPlane() && pArcC->IsPlane() ;
|
||||
// se archi non piatti verifico coincidenza pendenza sulla normale
|
||||
if ( ! bPlaneArcs) {
|
||||
double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ;
|
||||
if ( abs(( pArcC->GetDeltaN() * pArcP->GetAngCenter() - dN * pArcP->GetDeltaN() * pArcC->GetAngCenter()) /
|
||||
( pArcP->GetAngCenter() + pArcC->GetAngCenter())) > dCurrLinTol)
|
||||
return 0 ;
|
||||
}
|
||||
// verifico coincidenza pendenza sulla normale
|
||||
double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ;
|
||||
if ( abs(( pArcC->GetDeltaN() * pArcP->GetAngCenter() - dN * pArcP->GetDeltaN() * pArcC->GetAngCenter()) /
|
||||
( pArcP->GetAngCenter() + pArcC->GetAngCenter())) < dCurrLinTol) {
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Vector3d vtDir1 ;
|
||||
pArcP->GetStartDir( vtDir1) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) {
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return 0 ;
|
||||
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Point3d ptP2 ;
|
||||
pArcP->GetEndPoint( ptP2) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
|
||||
// se archi non piani costruisco arco sul piano definito dalla normale e dal punto di partenza del primo arco
|
||||
Frame3d frRef ;
|
||||
if ( ! frRef.Set( ptP1, pArcP->GetNormVersor()))
|
||||
return 0 ;
|
||||
if ( ! bPlaneArcs) {
|
||||
ptP1.Scale( frRef, 1, 1, 0) ;
|
||||
ptP2.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
ptC1Fin.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointEpsilon( ptP1, ptP3, dCurrLinTol)) ;
|
||||
if ( bCirc) {
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
if ( ! bPlaneArcs)
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// se vicino a circonferenza arco per 3 punti potrebbe non dare il risultato desiderato quindi faccio controllo su raggio e centro
|
||||
if ( Dist( NewArc.GetCenter(), ptC1Fin) > 2 * dCurrLinTol || abs( NewArc.GetRadius() - pArcP->GetRadius()) > 2 * dCurrLinTol)
|
||||
return 0 ;
|
||||
|
||||
// verifico normale al piano dell'arco
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
// se archi non piani ripristino il deltaN
|
||||
if ( ! bPlaneArcs) {
|
||||
double dDeltaN1 = pArcP->GetDeltaN() ;
|
||||
double dDeltaN2 = pArcC->GetDeltaN() ;
|
||||
NewArc.ChangeDeltaN( dDeltaN1 + dDeltaN2) ;
|
||||
}
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
// nessuna fusione
|
||||
@@ -3774,19 +3840,6 @@ CurveComposite::ResetVoronoiObject() const
|
||||
m_pVoronoiObj = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::FromPoint(Point3d& ptStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != TO_VERIFY)
|
||||
return false ;
|
||||
// assegno il punto e setto lo stato
|
||||
m_ptStart = ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
|
||||
+1
-2
@@ -177,8 +177,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ;
|
||||
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere)
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+1
-1
@@ -14,11 +14,11 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+3
-4
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2022
|
||||
// EgalTech 2020-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistLineLine.h Data : 12.08.22 Versione : 2.4h1
|
||||
// File : DistLineLine.cpp Data : 10.05.24 Versione : 2.6e3
|
||||
// Contenuto : Implementazione della classe distanza fra elementi lineari.
|
||||
//
|
||||
//
|
||||
@@ -12,11 +12,10 @@
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoConst.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistLineLine.h Data : 06.11.20 Versione : 2.2k1
|
||||
// Contenuto : Dichiarazione della classe distanza fra elementi lineari.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 06.11.20 LM Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkVector3d.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class DistLineLine
|
||||
{
|
||||
public :
|
||||
DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1,
|
||||
const Point3d& ptSt2, const Point3d& ptEn2,
|
||||
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
|
||||
DistLineLine( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
|
||||
|
||||
public :
|
||||
bool GetSqDist( double& dSqDist) const ;
|
||||
bool GetDist( double& dDist) const ;
|
||||
bool IsEpsilon( double dTol) const
|
||||
{ double dSqDist ; return ( GetSqDist( dSqDist) && ( dSqDist < SQ_EPS_ZERO || dSqDist < dTol * dTol)) ; }
|
||||
bool IsSmall( void) const
|
||||
{ return IsEpsilon( EPS_SMALL) ; }
|
||||
bool IsZero( void) const
|
||||
{ return IsEpsilon( EPS_ZERO) ; }
|
||||
bool GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) const ;
|
||||
bool GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) const ;
|
||||
|
||||
private :
|
||||
void Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1, bool bIsSegment2) ;
|
||||
private:
|
||||
double m_dSqDist ;
|
||||
mutable double m_dDist ;
|
||||
double m_dPos1 ;
|
||||
double m_dPos2 ;
|
||||
Point3d m_ptMinDist1 ;
|
||||
Point3d m_ptMinDist2 ;
|
||||
} ;
|
||||
+2
-2
@@ -14,9 +14,9 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "DistPointCrvAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "DistPointCrvAux.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -50,7 +50,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
|
||||
}
|
||||
// altrimenti, per curve successive
|
||||
else {
|
||||
// verifico se la distanza minima dal box è superiore al minimo già trovato
|
||||
// verifico se la distanza minima dal box è superiore al minimo già trovato
|
||||
BBox3d b3B ;
|
||||
if ( pCrvSmpl->GetLocalBBox( b3B) &&
|
||||
b3B.SqDistFromPoint( ptP) <= m_dDist * m_dDist) {
|
||||
@@ -105,7 +105,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// con minima distanza più bassa
|
||||
// con minima distanza più bassa
|
||||
else if ( dCurrDist < m_dDist) {
|
||||
// aggiorno i minimi
|
||||
m_dDist = dCurrDist ;
|
||||
|
||||
+20
-7
@@ -13,10 +13,10 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistPointArc.h"
|
||||
#include "DistPointCrvBezier.h"
|
||||
#include "DistPointCrvComposite.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve, bool bI
|
||||
case CRV_COMPO :
|
||||
CrvCompositeCalculate( ptP, Curve) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// salvo il punto
|
||||
m_ptP = ptP ;
|
||||
@@ -150,7 +152,7 @@ DistPointCurve::GetMinDistPoint( double dNearParam, Point3d& ptMinDist, int& nFl
|
||||
}
|
||||
}
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
double dParam ;
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
if ( i == 0 ||
|
||||
@@ -195,7 +197,7 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
|
||||
}
|
||||
}
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
if ( i == 0 ||
|
||||
abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) {
|
||||
@@ -230,9 +232,20 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
Vector3d vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
|
||||
// se tangenti opposte, si deve ricalcolare spostandosi un poco
|
||||
if ( ! vtTg.Normalize()) {
|
||||
double dDeltaU = 1000 * EPS_PARAM ;
|
||||
if ( ! m_pCurve->GetPointTang( m_Info[nInd].dPar - dDeltaU, ICurve::FROM_MINUS, ptQ, vtPreTg) ||
|
||||
! m_pCurve->GetPointTang( m_Info[nInd].dPar + dDeltaU, ICurve::FROM_PLUS, ptQ, vtPostTg))
|
||||
double dDeltaU = 1000 * EPS_PARAM ;
|
||||
double dParPre = m_Info[nInd].dPar - dDeltaU ;
|
||||
double dParPost = m_Info[nInd].dPar + dDeltaU ;
|
||||
// verifico se il parametro deve essere modificato per adattarsi a curva chiusa
|
||||
if ( m_pCurve->IsClosed()) {
|
||||
double dParS, dParE ;
|
||||
m_pCurve->GetDomain( dParS, dParE) ;
|
||||
if ( dParPre < dParS)
|
||||
dParPre = dParE - dDeltaU ;
|
||||
if ( dParPost > dParE)
|
||||
dParPost = dParS + dDeltaU ;
|
||||
}
|
||||
if ( ! m_pCurve->GetPointTang( dParPre, ICurve::FROM_MINUS, ptQ, vtPreTg) ||
|
||||
! m_pCurve->GetPointTang( dParPost, ICurve::FROM_PLUS, ptQ, vtPostTg))
|
||||
return false ;
|
||||
vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
|
||||
if ( ! vtTg.Normalize( EPS_ZERO))
|
||||
@@ -262,7 +275,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
|
||||
if ( m_dDist < 0 || m_Info.empty())
|
||||
return false ;
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
int nInd ;
|
||||
double dParam ;
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
|
||||
+4
-4
@@ -1,19 +1,19 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
// EgalTech 2013-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointLine.cpp Data : 17.12.13 Versione : 1.4l1
|
||||
// File : DistPointLine.cpp Data : 20.05.24 Versione : 2.6e5
|
||||
// Contenuto : Implementazione della classe distanza punto da linea/segmento.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 17.12.13 DS Creazione modulo.
|
||||
//
|
||||
// 20.05.24 DS Reso pubblico in Include.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2014
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointLine.h Data : 02.01.14 Versione : 1.5a1
|
||||
// Contenuto : Dichiarazione della classe distanza punto da linea/segmento.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 30.12.12 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class DistPointLine
|
||||
{
|
||||
friend class DistPointCurve ;
|
||||
|
||||
public :
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const ICurveLine& crvLine, bool bIsSegment = true) ;
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Point3d& ptFin, bool bIsSegment = true) ;
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Vector3d& vtDir, double dLen, bool bIsSegment = true) ;
|
||||
|
||||
public :
|
||||
bool GetSqDist( double& dSqDist) const ;
|
||||
bool GetDist( double& dDist) const ;
|
||||
bool IsEpsilon( double dTol) const
|
||||
{ double dSqDist ; return ( GetSqDist( dSqDist) && ( dSqDist < SQ_EPS_ZERO || dSqDist < dTol * dTol)) ; }
|
||||
bool IsSmall( void) const
|
||||
{ return IsEpsilon( EPS_SMALL) ; }
|
||||
bool IsZero( void) const
|
||||
{ return IsEpsilon( EPS_ZERO) ; }
|
||||
int GetNbrMinDist( void) const
|
||||
{ return (( m_dSqDist < 0) ? 0 : 1) ; }
|
||||
bool GetMinDistPoint( Point3d& ptMinDist) const ;
|
||||
bool GetParamAtMinDistPoint( double& dParam) const ;
|
||||
|
||||
private :
|
||||
DistPointLine( void) ;
|
||||
void Calculate( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Vector3d& vtDir, double dLen, bool bIsSegment) ;
|
||||
|
||||
private :
|
||||
double m_dSqDist ;
|
||||
mutable double m_dDist ;
|
||||
double m_dParam ;
|
||||
Point3d m_ptMinDist ;
|
||||
} ;
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2018-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointSurfTm.cpp Data : 19.12.20 Versione : 2.2l3
|
||||
// Contenuto : Implementazione della classe distanza Punto da Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.12.18 LM Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistPointSurfFr::DistPointSurfFr( const Point3d& ptP, const ISurfFlatRegion& frSurf)
|
||||
: m_dDist( -1)
|
||||
{
|
||||
// FlatRegion non valida
|
||||
if ( &frSurf == nullptr || ! frSurf.IsValid())
|
||||
return ;
|
||||
// Calcolo la distanza
|
||||
Calculate( ptP, frSurf) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
DistPointSurfFr::Calculate( const Point3d& ptP, const ISurfFlatRegion& frSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = -1 ;
|
||||
|
||||
// Converto regione in classe base
|
||||
const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( &frSurf) ;
|
||||
if ( pSfr == nullptr)
|
||||
return ;
|
||||
|
||||
// ciclo sulle parti della regione
|
||||
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; nC ++) {
|
||||
// ciclo sui loop della parte di regione
|
||||
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; nL ++) {
|
||||
PtrOwner<ICurve> pLoop( pSfr->GetLoop( nC, nL)) ;
|
||||
if ( IsNull( pLoop)) {
|
||||
m_dDist = -1 ;
|
||||
return ;
|
||||
}
|
||||
DistPointCurve DPL( ptP, *pLoop) ;
|
||||
double dDist ;
|
||||
if ( DPL.GetDist( dDist) && ( m_dDist < -EPS_SMALL || dDist < m_dDist)) {
|
||||
m_dDist = dDist ;
|
||||
int nFlag ;
|
||||
m_nMinChunk = nC ;
|
||||
m_nMinLoop = nL ;
|
||||
DPL.GetParamAtMinDistPoint( 0, m_dMinPar, nFlag) ;
|
||||
DPL.GetMinDistPoint( 0, m_ptMinDistPoint, nFlag) ;
|
||||
DPL.GetSideAtMinDistPoint( 0, pSfr->GetNormVersor(), m_nSide) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata, aggiorno minima distanza sul piano
|
||||
if ( m_dDist > - EPS_SMALL) {
|
||||
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
|
||||
m_dDistOnPlane = min( Dist( ptOn, m_ptMinDistPoint), m_dDist) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetDist( double& dDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetDistOnRegionPlane( double& dDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
dDist = m_dDistOnPlane ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetPointAtMinDist( Point3d& ptMinDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
ptMinDist = m_ptMinDistPoint ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetParamAtMinDist( int& nMinChunk, int& nMinLoop, double& dMinPar) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
nMinChunk = m_nMinChunk ;
|
||||
nMinLoop = m_nMinLoop ;
|
||||
dMinPar = m_dMinPar ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetSideAtMinDist( int& nSide) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
nSide = m_nSide ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsPointInsideSurfFr( const Point3d& ptP, const ISurfFlatRegion* pSfr, double dMinDist, bool& bInside, int& nChunk)
|
||||
{
|
||||
// default non include
|
||||
bInside = false ;
|
||||
nChunk = -1 ;
|
||||
// verifica regione
|
||||
if ( pSfr == nullptr || ! pSfr->IsValid())
|
||||
return false ;
|
||||
// verifico se la proiezione del punto sul piano della regione sta nel suo box
|
||||
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
|
||||
BBox3d b3Box ;
|
||||
pSfr->GetLocalBBox( b3Box) ;
|
||||
b3Box.Expand( dMinDist) ;
|
||||
if ( ! b3Box.Encloses( ptOn))
|
||||
return true ;
|
||||
// determino dove sta il punto
|
||||
DistPointSurfFr DPR( ptP, *pSfr) ;
|
||||
double dDist ; int nMinCh, nMinL; double dMinPar ; int nSide ;
|
||||
if ( DPR.GetDistOnRegionPlane( dDist) && DPR.GetParamAtMinDist( nMinCh, nMinL, dMinPar) && DPR.GetSideAtMinDist( nSide)) {
|
||||
if ( abs( dMinDist) < EPS_SMALL)
|
||||
bInside = ( nSide != PRS_OUT) ;
|
||||
else if ( dMinDist < 0)
|
||||
bInside = ( nSide == PRS_IN && dDist > abs( dMinDist) - EPS_SMALL) ;
|
||||
else
|
||||
bInside = ( nSide != PRS_OUT || dDist < dMinDist + EPS_SMALL) ;
|
||||
if ( bInside)
|
||||
nChunk = nMinCh ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+99
-30
@@ -15,15 +15,16 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calcola la differenza fra i bounding-box A e B.
|
||||
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
|
||||
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
|
||||
// Se l'insieme differenza fra i box non ha misura nulla viene restituito true, false altrimenti.
|
||||
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
|
||||
// nel box B; uno di questi si verifica se il box A è vuoto.
|
||||
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
|
||||
// nel box B; uno di questi si verifica se il box A è vuoto.
|
||||
// Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B.
|
||||
static bool
|
||||
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
|
||||
@@ -33,7 +34,7 @@ BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDi
|
||||
// Se box A vuoto, risultato vuoto
|
||||
if ( boxA.IsEmpty())
|
||||
return false ;
|
||||
// Se box B vuoto o i box non si intersecano, risultato è ancora A
|
||||
// Se box B vuoto o i box non si intersecano, risultato è ancora A
|
||||
BBox3d boxInt ;
|
||||
if ( boxB.IsSmall() || ! boxA.FindIntersection( boxB, boxInt)) {
|
||||
vBoxDiff.emplace_back( boxA) ;
|
||||
@@ -93,6 +94,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = tmSurf.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ;
|
||||
@@ -104,8 +107,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( b3Stm.IsEmpty())
|
||||
return ;
|
||||
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
|
||||
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
|
||||
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
|
||||
@@ -115,14 +118,17 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
BBox3d boxPPrev( ptP) ;
|
||||
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
|
||||
// Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
|
||||
double dMinSqDist = DBL_MAX ;
|
||||
double dMinDist = DBL_MAX ;
|
||||
int nMinDistTriaIndex = SVT_NULL ;
|
||||
Point3d ptMinDistPoint ;
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
pStm->ResetTempInts() ;
|
||||
bool bContinue = true ;
|
||||
|
||||
// creazione del vettore dei triangoli più vicini a ptP
|
||||
vector<pair<int, Triangle3d>> vTria ; // <indice triangolo, Triangolo>
|
||||
while ( bContinue) {
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
@@ -130,12 +136,12 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
for ( const auto& b3Box : vBox) {
|
||||
// interseco il box con quello della superficie e ne verifico la distanza minima dal punto
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist)
|
||||
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.DistFromPoint( ptP) > dMinDist)
|
||||
continue ;
|
||||
// ricerca sui triangoli nel box
|
||||
bCollide = true ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
INTVECTOR vnIds ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
// Ciclo sui triangoli del sotto-box corrente
|
||||
for ( auto nT : vnIds) {
|
||||
int nTriaTemp ;
|
||||
@@ -143,19 +149,30 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) {
|
||||
pStm->SetTempInt( nT, 1) ;
|
||||
DistPointTriangle distPT( ptP, trCurTria) ;
|
||||
double dCurSqDist ;
|
||||
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) {
|
||||
dMinSqDist = dCurSqDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
double dCurrDist ;
|
||||
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetDist( dCurrDist)) {
|
||||
// se distanze uguali...
|
||||
if ( abs( dCurrDist - dMinDist) < EPS_SMALL)
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
// se minore...
|
||||
else if ( dCurrDist < dMinDist) {
|
||||
// pulisco il vettore
|
||||
vTria.clear() ;
|
||||
dMinDist = dCurrDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
|
||||
if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL)
|
||||
if ( ! bCollide || dMinDist < EPS_SMALL)
|
||||
bContinue = false ;
|
||||
else {
|
||||
boxPPrev = boxP ;
|
||||
@@ -163,15 +180,67 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
}
|
||||
}
|
||||
|
||||
if ( nMinDistTriaIndex != SVT_NULL) {
|
||||
m_dDist = sqrt( max( dMinSqDist, 0.)) ;
|
||||
// se non ho trovato nessun triangolo, esco
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = dMinDist ;
|
||||
// salvo il punto a distanza minima
|
||||
m_ptMinDistPoint = ptMinDistPoint ;
|
||||
// se il punto è sulla TriMesh...
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_nMinDistTriaIndex = nMinDistTriaIndex ;
|
||||
m_ptMinDistPoint = ptMinDistPoint ;
|
||||
Triangle3d trMinDistTria ;
|
||||
pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ;
|
||||
trMinDistTria.Validate() ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ;
|
||||
m_bIsInside = false ;
|
||||
return ;
|
||||
}
|
||||
// se ho un solo triangolo, allora deduco le informazioni da lui
|
||||
else if ( int( vTria.size()) == 1) {
|
||||
m_nMinDistTriaIndex = vTria.back().first ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// controllo se tutti i triangoli a minima distanza forniscono la stessa informazione
|
||||
// ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito )
|
||||
bool bInside = false ;
|
||||
bool bOutside = false ;
|
||||
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) { // scorro i triangoli a minima distanza
|
||||
if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL)
|
||||
bInside = true ;
|
||||
else
|
||||
bOutside = true ;
|
||||
}
|
||||
|
||||
// inizializzo le variabili membro
|
||||
m_nMinDistTriaIndex = nMinDistTriaIndex ;
|
||||
m_bIsInside = false ;
|
||||
|
||||
// se le informazioni non sono coerenti, allora :
|
||||
// 1) calcolo i centroidi dei triangoli in questione
|
||||
// 2) ottengo il punto medio di questi centroidi
|
||||
// 3) controllo quale triangolo interseca il segmento che parte da ptP e arriva a tale punto
|
||||
// 4) userò questo triangolo per classificare ptP
|
||||
if ( bOutside == bInside) {
|
||||
// calcolo il baricentro complessivo
|
||||
Point3d ptBar_tot ;
|
||||
for ( auto& Tria : vTria)
|
||||
ptBar_tot += Tria.second.GetCentroid() ;
|
||||
ptBar_tot /= int( vTria.size()) ;
|
||||
// per ogni triangolo, cerco quello che interseca il segmento
|
||||
for ( auto& Tria : vTria) {
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ;
|
||||
if ( nType == ILTT_IN) { // se intersezione ho finito
|
||||
DistPointTriangle( ptP, Tria.second).GetMinDistPoint( m_ptMinDistPoint) ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ;
|
||||
m_nMinDistTriaIndex = Tria.first ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // se informazioni coerenti
|
||||
m_bIsInside = bInside ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -224,8 +293,8 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( b3Stm.IsEmpty())
|
||||
return SVT_NULL ;
|
||||
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
|
||||
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
|
||||
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
|
||||
@@ -237,11 +306,11 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
// Variabili distanza minima
|
||||
int nVert = SVT_NULL ;
|
||||
double dMinSqDist = DBL_MAX ;
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
pStm->ResetTempInts() ;
|
||||
bool bContinue = true ;
|
||||
while ( bContinue) {
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
+13
-6
@@ -22,7 +22,7 @@
|
||||
<ProjectGuid>{9A98A202-2853-454A-84CA-DCD1714176C9}</ProjectGuid>
|
||||
<RootNamespace>EgtGeomKernel</RootNamespace>
|
||||
<Keyword>MFCDLLProj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -30,7 +30,7 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v141_xp</PlatformToolset>
|
||||
<PlatformToolset>v143</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>v141_xp</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
@@ -281,6 +281,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="BBox3d.cpp" />
|
||||
<ClCompile Include="BiArcs.cpp" />
|
||||
<ClCompile Include="CalcPocketing.cpp" />
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
@@ -309,6 +310,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="DistPointSurfFr.cpp" />
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
@@ -318,16 +320,21 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||
<ClCompile Include="VolZmapOffset.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
<ClCompile Include="Quaternion.cpp" />
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||
<ClCompile Include="SbzFromCurves.cpp" />
|
||||
<ClCompile Include="SbzStandard.cpp" />
|
||||
<ClCompile Include="Voronoi.cpp" />
|
||||
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConeFrustumClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConvexTorusClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeRectPrismoidClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkDistLineLine.h" />
|
||||
<ClInclude Include="..\Include\EGkDistPointLine.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
|
||||
@@ -338,6 +345,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
@@ -423,7 +432,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="OffsetCurveOnX.cpp" />
|
||||
<ClCompile Include="Polygon3d.cpp" />
|
||||
<ClCompile Include="AdjustLoops.cpp" />
|
||||
<ClCompile Include="ProjectCurveSurfTm.cpp" />
|
||||
<ClCompile Include="ProjectCurveSurf.cpp" />
|
||||
<ClCompile Include="RemoveCurveDefects.cpp" />
|
||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||
<ClCompile Include="SfrCreate.cpp" />
|
||||
@@ -595,12 +604,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="CAvSimpleSurfFrMove.h" />
|
||||
<ClInclude Include="CAvToolSurfTm.h" />
|
||||
<ClInclude Include="CreateCurveAux.h" />
|
||||
<ClInclude Include="DistLineLine.h" />
|
||||
<ClInclude Include="DistPointArc.h" />
|
||||
<ClInclude Include="DistPointCrvAux.h" />
|
||||
<ClInclude Include="DistPointCrvBezier.h" />
|
||||
<ClInclude Include="DistPointCrvComposite.h" />
|
||||
<ClInclude Include="DistPointLine.h" />
|
||||
<ClInclude Include="DllMain.h" />
|
||||
<ClInclude Include="earcut.hpp" />
|
||||
<ClInclude Include="ExtDimension.h" />
|
||||
|
||||
@@ -486,7 +486,7 @@
|
||||
<ClCompile Include="IntersLineCaps.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProjectCurveSurfTm.cpp">
|
||||
<ClCompile Include="ProjectCurveSurf.cpp">
|
||||
<Filter>File di origine\GeoProject</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
|
||||
@@ -537,6 +537,21 @@
|
||||
<ClCompile Include="Quaternion.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SbzFromCurves.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DistPointSurfFr.cpp">
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VolZmapOffset.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -593,9 +608,6 @@
|
||||
<ClInclude Include="DistPointArc.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistPointLine.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistPointCrvBezier.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
@@ -1118,9 +1130,6 @@
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistLineLine.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CDeUtility.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
@@ -1214,6 +1223,18 @@
|
||||
<ClInclude Include="..\Include\EGkQuaternion.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkDistLineLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkDistPointLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
@@ -147,6 +147,10 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// verifico il minimo raggio
|
||||
if ( dRadius < 10 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// eseguo calcoli
|
||||
Point3d ptCen, ptTg1, ptTg2 ;
|
||||
int nSide1, nSide2 ;
|
||||
@@ -165,6 +169,11 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// verifico dimensione minima
|
||||
double dLen = Dist( ptTg1, ptTg2) ;
|
||||
if ( dLen < 2 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// orientamento tra le curve
|
||||
bool bCCW = ( dSinA > 0) ;
|
||||
|
||||
@@ -207,6 +216,10 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// verifico lo smusso minimo
|
||||
if ( dDist < 10 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo un riferimento sul piano perpendicolare alla normale
|
||||
Frame3d frIntr ;
|
||||
if ( ! frIntr.Set( ORIG, vtNorm))
|
||||
|
||||
+2
-2
@@ -493,7 +493,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
// salvo la linea, se contiene qualcosa
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
@@ -523,7 +523,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
||||
dMaxW = vtMove.x ;
|
||||
}
|
||||
// salvo eventuale ultima linea
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
|
||||
+2
-2
@@ -619,7 +619,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
// salvo la linea, se contiene qualcosa
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
@@ -646,7 +646,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
||||
dMaxW = vtMove.x ;
|
||||
}
|
||||
// salvo eventuale ultima linea
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
|
||||
+17
@@ -37,6 +37,23 @@ Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirX,
|
||||
! m_vtVersZ.Normalize())
|
||||
return false ;
|
||||
|
||||
// se ci sono errori molto piccoli di ortogonalità, li correggo
|
||||
double dOrtXZ = m_vtVersX * m_vtVersZ ;
|
||||
if ( dOrtXZ > EPS_ZERO && dOrtXZ < 10 * EPS_ZERO) {
|
||||
m_vtVersX = OrthoCompo( m_vtVersX, m_vtVersZ) ;
|
||||
m_vtVersX.Normalize() ;
|
||||
}
|
||||
double dOrtYX = m_vtVersY * m_vtVersX ;
|
||||
if ( dOrtYX > EPS_ZERO && dOrtYX < 10 * EPS_ZERO) {
|
||||
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersX) ;
|
||||
m_vtVersY.Normalize() ;
|
||||
}
|
||||
double dOrtYZ = m_vtVersY * m_vtVersZ ;
|
||||
if ( dOrtYZ > EPS_ZERO && dOrtYZ < 10 * EPS_ZERO) {
|
||||
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersZ) ;
|
||||
m_vtVersY.Normalize() ;
|
||||
}
|
||||
|
||||
// verifica della ortogonalità dei versori e del senso destrorso
|
||||
if ( ! Verify())
|
||||
return false ;
|
||||
|
||||
+5
-5
@@ -2267,7 +2267,7 @@ bool
|
||||
GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams)
|
||||
{
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// recupero la superficie
|
||||
ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ;
|
||||
@@ -6632,7 +6632,7 @@ GdbExecutor::ExecuteDeselect( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
// deselezione di tutto
|
||||
else if ( sCmd2 == "ALL") {
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// cancello selezione oggetti
|
||||
if ( ! m_pGDB->ClearSelection())
|
||||
@@ -7773,7 +7773,7 @@ bool
|
||||
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
{
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// pulizia e reinizializzazione del DB geometrico
|
||||
m_pGDB->Clear() ;
|
||||
@@ -7946,7 +7946,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
// chiudo il file di uscita Tsc
|
||||
else if ( sCmd2 == "CLOSE") {
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// scrivo terminazioni e chiudo il file
|
||||
return m_OutTsc.Close() ;
|
||||
@@ -7969,7 +7969,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
else if ( sCmd2 == "SETGR") {
|
||||
Frame3d frF ;
|
||||
// nessun parametro
|
||||
if ( vsParams.size() == 0)
|
||||
if ( vsParams.empty())
|
||||
frF.Reset() ;
|
||||
// un parametro ( Id del gruppo)
|
||||
else if ( vsParams.size() == 1) {
|
||||
|
||||
+2
-2
@@ -1254,13 +1254,13 @@ GdbIterator::GetCalcStatus( int& nStat) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbIterator::SetMark( void)
|
||||
GdbIterator::SetMark( int nMark)
|
||||
{
|
||||
if ( m_pGDB == nullptr || m_pCurrObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// imposto la marcatura
|
||||
return m_pCurrObj->SetMark() ;
|
||||
return m_pCurrObj->SetMark( nMark) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ class GdbIterator : public IGdbIterator
|
||||
bool RevertStatus( void) override ;
|
||||
bool GetStatus( int& nStat) const override ;
|
||||
bool GetCalcStatus( int& nStat) const override ;
|
||||
bool SetMark( void) override ;
|
||||
bool SetMark( int nMark = GDB_MK_ON) override ;
|
||||
bool ResetMark( void) override ;
|
||||
bool GetMark( int& nMark) const override ;
|
||||
bool GetCalcMark( int& nMark) const override ;
|
||||
|
||||
+4
-4
@@ -612,14 +612,14 @@ GdbObj::GetCalcStatus( int& nStat, int nLev) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::SetMark( void)
|
||||
GdbObj::SetMark( int nMark)
|
||||
{
|
||||
// verifico esistenza (con eventuale creazione) degli attributi
|
||||
if ( GetSafeAttribs() == nullptr)
|
||||
return false ;
|
||||
|
||||
// assegno la marcatura
|
||||
m_pAttribs->SetMark() ;
|
||||
m_pAttribs->SetMark( nMark) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -659,8 +659,8 @@ GdbObj::GetCalcMark( int& nMark) const
|
||||
nObjMark = m_pAttribs->GetMark() ;
|
||||
|
||||
// se la marcatura è ON, non ho bisogno di sapere altro
|
||||
if ( nObjMark == GDB_MK_ON) {
|
||||
nMark = GDB_MK_ON ;
|
||||
if ( nObjMark == GDB_MK_ON || nObjMark == GDB_MK_ON_2) {
|
||||
nMark = nObjMark ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class GdbObj
|
||||
bool IsSelected( void) const ;
|
||||
bool GetStatus( int& nStat) const ;
|
||||
bool GetCalcStatus( int& nStat, int nLev = 0) const ;
|
||||
bool SetMark( void) ;
|
||||
bool SetMark( int nMark) ;
|
||||
bool ResetMark( void) ;
|
||||
bool GetMark( int& nMark) const ;
|
||||
bool GetCalcMark( int& nMark) const ;
|
||||
|
||||
+2
-2
@@ -2310,7 +2310,7 @@ GeomDB::GetCalcStatus( int nId, int& nStat) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GeomDB::SetMark( int nId)
|
||||
GeomDB::SetMark( int nId, int nMark)
|
||||
{
|
||||
// recupero l'oggetto
|
||||
GdbObj* pGdbObj = GetGdbObj( nId) ;
|
||||
@@ -2318,7 +2318,7 @@ GeomDB::SetMark( int nId)
|
||||
return false ;
|
||||
|
||||
// imposto la marcatura
|
||||
return pGdbObj->SetMark() ;
|
||||
return pGdbObj->SetMark( nMark) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -136,7 +136,7 @@ class GeomDB : public IGeomDB
|
||||
bool RevertStatus( int nId) override ;
|
||||
bool GetStatus( int nId, int& nStat) const override ;
|
||||
bool GetCalcStatus( int nId, int& nStat) const override ;
|
||||
bool SetMark( int nId) override ;
|
||||
bool SetMark( int nId, int nMark = GDB_MK_ON) override ;
|
||||
bool ResetMark( int nId) override ;
|
||||
bool GetMark( int nId, int& nMark) const override ;
|
||||
bool GetCalcMark( int nId, int& nMark) const override ;
|
||||
|
||||
+13
-13
@@ -116,7 +116,7 @@ HashGrid1d::~HashGrid1d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -396,8 +396,10 @@ HashGrid1d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_CellCount *= 2 ;
|
||||
@@ -569,7 +571,7 @@ HashGrids1d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -634,24 +636,22 @@ HashGrids1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -125,7 +125,7 @@ HashGrid2d::~HashGrid2d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -445,8 +445,10 @@ HashGrid2d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_xCellCount *= 2 ;
|
||||
@@ -623,7 +625,7 @@ HashGrids2d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -688,24 +690,22 @@ HashGrids2d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids2d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -132,7 +132,7 @@ HashGrid3d::~HashGrid3d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -486,8 +486,10 @@ HashGrid3d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_xCellCount *= 2 ;
|
||||
@@ -667,7 +669,7 @@ HashGrids3d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -731,7 +733,7 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -739,17 +741,15 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
void
|
||||
HashGrids3d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -17,6 +17,9 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static const double EPS_INTER_ARC = 0.1 * EPS_SMALL ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
{
|
||||
@@ -60,15 +63,15 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
vtDir /= dDist ;
|
||||
|
||||
// cerchi esterni -> nessuna intersezione
|
||||
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_SMALL)
|
||||
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_INTER_ARC)
|
||||
return ;
|
||||
|
||||
// cerchi interni -> nessuna intersezione
|
||||
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_SMALL)
|
||||
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_INTER_ARC)
|
||||
return ;
|
||||
|
||||
// cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi
|
||||
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_SMALL) {
|
||||
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_INTER_ARC) {
|
||||
// coefficiente da parametro dell'arco 1 a lunghezza
|
||||
double dU2L = abs( m_Arc1.GetAngCenter()) * DEGTORAD * m_Arc1.GetRadius() ;
|
||||
// determino se sono equiversi o controversi
|
||||
@@ -236,7 +239,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
double dSqH = m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA ;
|
||||
|
||||
// cerchi tangenti esterni -> una intersezione
|
||||
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) {
|
||||
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_INTER_ARC) {
|
||||
// tolleranza tangenziale sull'intersezione
|
||||
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
|
||||
// calcolo il punto di intersezione
|
||||
@@ -358,7 +361,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
}
|
||||
|
||||
// cerchi tangenti interni -> una intersezione
|
||||
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) {
|
||||
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_INTER_ARC) {
|
||||
// tolleranza tangenziale sull'intersezione
|
||||
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
|
||||
// determino quale dei due contiene l'altro
|
||||
|
||||
@@ -78,6 +78,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
LineCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case CRV_ARC :
|
||||
@@ -91,6 +93,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
ArcCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
@@ -104,8 +108,12 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
CrvCompoCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// per curve approssimate, sistemo...
|
||||
AdjustIntersParams( ( pCalcCrv[0] != m_pCurve[0]), ( pCalcCrv[1] != m_pCurve[1])) ;
|
||||
@@ -245,7 +253,7 @@ bool
|
||||
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
|
||||
{
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.size() == 0)
|
||||
if ( m_Info.empty())
|
||||
return true ;
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
if ( ! bAdjCrvA && ! bAdjCrvB)
|
||||
|
||||
@@ -44,7 +44,7 @@ static void
|
||||
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineCaps.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSphere.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+29
-24
@@ -19,20 +19,18 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Il punto è esterno al FatSegment se dista da questo più di Tol e la sua proiezione sta sul segmento
|
||||
bool
|
||||
IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
|
||||
// Posizione del punto rispetto alla linea (+1=a destra, 0=nella banda di tolleranza, -1=a sinistra)
|
||||
static int
|
||||
GetPointToLineSide( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
|
||||
{
|
||||
// distanza del punto dalla linea del segmento (con compensazione piccolissimi errori)
|
||||
if ( abs( CrossXY( ( ptP - ptS), vtDir)) < ( dTol + EPS_ZERO) * dLenXY)
|
||||
return false ;
|
||||
// distanza con segno della proiezione del punto sul segmento dall'inizio per lunghezza segmento
|
||||
double dDistXY = ScalarXY( ( ptP - ptS), vtDir) ;
|
||||
// se il punto non si proietta sul segmento entro la tolleranza
|
||||
if ( dDistXY < - dTol * dLenXY || dDistXY > ( dLenXY + dTol) * dLenXY)
|
||||
return false ;
|
||||
// altrimenti
|
||||
return true ;
|
||||
double dCross = CrossXY( ( ptP - ptS), vtDir) ;
|
||||
double dFat = ( dTol + EPS_ZERO) * dLenXY ;
|
||||
if ( dCross > dFat)
|
||||
return +1 ;
|
||||
else if ( dCross < - dFat)
|
||||
return -1 ;
|
||||
else
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -44,7 +42,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
|
||||
m_bOverlaps = false ;
|
||||
m_nNumInters = 0 ;
|
||||
|
||||
// verifico validità linee
|
||||
// verifico validità linee
|
||||
if ( ! Line1.IsValid() || ! Line2.IsValid())
|
||||
return ;
|
||||
|
||||
@@ -130,30 +128,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
if ( ! boxL1.OverlapsXY( boxL2))
|
||||
return ;
|
||||
|
||||
// linea 1 : Start, End, Direzione e Lunghezza
|
||||
// segmento 1 : Start, End, Direzione e Lunghezza
|
||||
Point3d ptS1 = Line1.GetStart() ;
|
||||
Point3d ptE1 = Line1.GetEnd() ;
|
||||
Vector3d vtDir1 = ptE1 - ptS1 ;
|
||||
double dLen1XY = vtDir1.LenXY() ;
|
||||
if ( dLen1XY < EPS_SMALL)
|
||||
return ;
|
||||
// linea 2 : Start, Direzione e Lunghezza
|
||||
// segmento 2 : Start, Direzione e Lunghezza
|
||||
Point3d ptS2 = Line2.GetStart() ;
|
||||
Point3d ptE2 = Line2.GetEnd() ;
|
||||
Vector3d vtDir2 = ptE2 - ptS2 ;
|
||||
double dLen2XY = vtDir2.LenXY() ;
|
||||
if ( dLen2XY < EPS_SMALL)
|
||||
return ;
|
||||
// posizioni estremi segmento 1 rispetto a linea 2
|
||||
int nS1Side = GetPointToLineSide( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
|
||||
int nE1Side = GetPointToLineSide( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
|
||||
if ( ( nS1Side == 1 && nE1Side == 1) || ( nS1Side == -1 && nE1Side == -1))
|
||||
return ;
|
||||
// posizioni estremi segmento 2 rispetto a linea 1
|
||||
int nS2Side = GetPointToLineSide( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
|
||||
int nE2Side = GetPointToLineSide( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
|
||||
if ( ( nS2Side == 1 && nE2Side == 1) || ( nS2Side == -1 && nE2Side == -1))
|
||||
return ;
|
||||
// prodotto vettoriale nel piano XY tra le direzioni delle linee
|
||||
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
|
||||
// flag per linee parallele
|
||||
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
|
||||
// flag per segmenti che si allontanano significativamente
|
||||
bool bFarEnds = ( /*( abs( dCrossXY) > SIN_EPS_ANG_SMALL * ( dLen1XY * dLen2XY)) ||*/
|
||||
IsPointOutFatSegment( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL)) ;
|
||||
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
|
||||
|
||||
// se non sono paralleli e si allontanano tra loro abbastanza
|
||||
if ( ! bParallel && bFarEnds) {
|
||||
@@ -168,6 +172,8 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
nPos1 = ICurve::PP_END ; // vicino a fine
|
||||
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
|
||||
nPos1 = ICurve::PP_MID ; // nell'interno
|
||||
else
|
||||
return ;
|
||||
// verifica posizione intersezione su seconda linea
|
||||
int nPos2 = ICurve::PP_NULL ; // fuori
|
||||
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
|
||||
@@ -176,8 +182,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
nPos2 = ICurve::PP_END ; // vicino a fine
|
||||
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
|
||||
nPos2 = ICurve::PP_MID ; // nell'interno
|
||||
// se soluzione non accettata, esco
|
||||
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
|
||||
else
|
||||
return ;
|
||||
// limito i parametri a stare sui segmenti (0...1)
|
||||
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ;
|
||||
@@ -190,7 +195,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
m_Info.IciA[0].nNextTy = ICCT_NULL ;
|
||||
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
|
||||
m_Info.IciB[0].nNextTy = ICCT_NULL ;
|
||||
// si incontrano alle estremità, non si può dire alcunché
|
||||
// si incontrano alle estremità, non si può dire alcunché
|
||||
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
|
||||
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
|
||||
; // rimangono tutti NULL
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "CurveLine.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -83,7 +83,7 @@ static void
|
||||
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
|
||||
@@ -1670,7 +1670,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
|
||||
|
||||
// Studio le soluzioni
|
||||
int nIntType = T_ERROR ;
|
||||
if ( vdPar.size() == 0)
|
||||
if ( vdPar.empty())
|
||||
nIntType = T_NO_INT ;
|
||||
else if ( vdPar.size() == 1) {
|
||||
nIntType = T_ONE_TAN ;
|
||||
|
||||
+109
-22
@@ -23,20 +23,20 @@ using namespace std ;
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
|
||||
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
int nStm, int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, bFinite) ;
|
||||
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
|
||||
double dU = ( ptInt - ptL) * vtDir ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
|
||||
vInfo.emplace_back( nRes, dU, nStm, nT, dCosDN, ptInt) ;
|
||||
}
|
||||
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
|
||||
double dU = ( ptInt - ptL) * vtDir ;
|
||||
double dU2 = ( ptInt2 - ptL) * vtDir ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nStm, nT, dCosDN, ptInt, ptInt2) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,15 @@ static void
|
||||
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinStmInfo& a, const IntLinStmInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
if ( abs( dUa - dUb) < EPS_SMALL)
|
||||
return ( a.dCosDN < b.dCosDN) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
@@ -106,7 +108,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
Triangle3d Tria ;
|
||||
Stm.GetTriangle( nT, Tria) ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ;
|
||||
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, 0, nT, Tria, vInfo, bFinite) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,19 +124,23 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
// Intersezione di molte linee parallele con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfTriMesh& Stm)
|
||||
: m_bOk( false), m_frLines( frLines), m_pSTm( &Stm)
|
||||
: m_bOk( false), m_frLines( frLines), m_vpSTm( {&Stm})
|
||||
{
|
||||
// verifico esistenza superficie
|
||||
if ( m_pSTm == nullptr || ! m_pSTm->IsValid())
|
||||
if ( m_vpSTm[0] == nullptr || ! m_vpSTm[0]->IsValid())
|
||||
return ;
|
||||
|
||||
// creo HashGrid 2d
|
||||
const int LIM_HG_TRIA = 127 ;
|
||||
m_HGrids.SetActivationGrid( m_pSTm->GetTriangleCount() > LIM_HG_TRIA) ;
|
||||
// aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
|
||||
// ( in questo caso la superficie è unica, quindi ho solo due elementi)
|
||||
m_vBaseInd = { 0, m_vpSTm[0]->GetTriangleCount()} ;
|
||||
|
||||
// riempio HashGrid
|
||||
// creo HashGrid 2d ed eventualmente attivo la griglia
|
||||
const int LIM_HG_TRIA = 127 ;
|
||||
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
|
||||
|
||||
// riempio HashGrid
|
||||
Triangle3d Tria ;
|
||||
int nT = Stm.GetFirstTriangle( Tria) ;
|
||||
int nT = m_vpSTm[0]->GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// calcolo il BBox del triangolo nel riferimento scelto
|
||||
Tria.ToLoc( m_frLines) ;
|
||||
@@ -143,10 +149,55 @@ IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfT
|
||||
b3Tria.Add( Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
// inserisco nella griglia
|
||||
if ( ! m_HGrids.Add( nT, b3Tria))
|
||||
if ( ! m_HGrids.Add( nT, b3Tria)) // ( 0 + nT, Tria)
|
||||
return ;
|
||||
// passo al prossimo triangolo
|
||||
nT = Stm.GetNextTriangle( nT, Tria) ;
|
||||
// passo al prossimo triangolo
|
||||
nT = m_vpSTm[0]->GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
// aggiorno
|
||||
m_bOk = m_HGrids.Update() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di molte linee parallele con un vettore di superfici TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const CISURFTMPVECTOR& vStm)
|
||||
: m_bOk( false), m_frLines( frLines), m_vpSTm( vStm), m_vBaseInd( {0})
|
||||
{
|
||||
// verifico esistenza superfici
|
||||
if ( m_vpSTm.empty())
|
||||
return ;
|
||||
for ( const ISurfTriMesh* pStm : m_vpSTm) {
|
||||
if ( pStm == nullptr || ! pStm->IsValid())
|
||||
return ;
|
||||
}
|
||||
|
||||
// aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
|
||||
// NB. dal costruttore è già inizializzato a {0}
|
||||
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i)
|
||||
m_vBaseInd.emplace_back( m_vBaseInd.back() + m_vpSTm[i]->GetTriangleCount()) ;
|
||||
|
||||
// creo HashGrid 2d ed eventualmente attivo la griglia
|
||||
const int LIM_HG_TRIA = 256 ;
|
||||
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
|
||||
|
||||
// riempio HashGrid
|
||||
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i) {
|
||||
Triangle3d Tria ;
|
||||
int nT = m_vpSTm[i]->GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// calcolo il BBox del triangolo nel riferimento scelto
|
||||
Tria.ToLoc( m_frLines) ;
|
||||
BBox3d b3Tria ;
|
||||
b3Tria.Add( Tria.GetP( 0)) ;
|
||||
b3Tria.Add( Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
// inserisco nella griglia ( aggiungo shift per indice del triangolo)
|
||||
if ( ! m_HGrids.Add( m_vBaseInd[i] + nT, b3Tria))
|
||||
return ;
|
||||
// passo al prossimo triangolo
|
||||
nT = m_vpSTm[i]->GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
}
|
||||
// aggiorno
|
||||
m_bOk = m_HGrids.Update() ;
|
||||
@@ -160,7 +211,7 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
if ( &vInfo == nullptr)
|
||||
return false ;
|
||||
vInfo.clear() ;
|
||||
// verifico validità
|
||||
// verifico validità
|
||||
if ( ! m_bOk)
|
||||
return false ;
|
||||
|
||||
@@ -172,15 +223,22 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
Point3d ptLL = ptL ;
|
||||
ptLL.ToGlob( m_frLines) ;
|
||||
|
||||
// recupero indici triangoli che intersecano box in 2d
|
||||
// recupero indici triangoli che intersecano box in 2d
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Line, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nT = vnIds[i] ;
|
||||
// recupero la superficie
|
||||
int nInd = vnIds[i] ;
|
||||
int nSurf = GetSurfInd( nInd) ;
|
||||
if ( nSurf == -1)
|
||||
return false ;
|
||||
// recupero il triangolo
|
||||
int nT = nInd - m_vBaseInd[nSurf] ;
|
||||
Triangle3d Tria ;
|
||||
m_pSTm->GetTriangle( nT, Tria) ;
|
||||
if ( ! m_vpSTm[nSurf]->GetTriangle( nT, Tria))
|
||||
return false ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nT, Tria, vInfo, bFinite) ;
|
||||
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nSurf, nT, Tria, vInfo, bFinite) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +248,35 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersParLinesSurfTm::GetSurfInd( int nT) const
|
||||
{
|
||||
// verifico la presenza di almeno un intervallo
|
||||
if ( m_vBaseInd.size() < 2)
|
||||
return -1 ;
|
||||
// se la superficie è unica, allora non devo cercarla
|
||||
if ( int( m_vBaseInd.size()) == 2)
|
||||
return 0 ;
|
||||
// ricerca binaria dell'intervallo contenente la posizione del triangolo
|
||||
int nS = 0 ;
|
||||
int nE = int( m_vBaseInd.size()) - 1 ;
|
||||
while ( true) {
|
||||
if ( nT < m_vBaseInd[nS] || nT >= m_vBaseInd[nE])
|
||||
return -1 ;
|
||||
if ( nE - nS == 1)
|
||||
return nS ;
|
||||
int nM = ( nS + nE) / 2 ;
|
||||
if ( nT == m_vBaseInd[nM])
|
||||
return nM ;
|
||||
if ( nT < m_vBaseInd[nM])
|
||||
nE = nM ;
|
||||
else
|
||||
nS = nM ;
|
||||
}
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
@@ -215,7 +302,7 @@ FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
#include "CurveLine.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include <array>
|
||||
|
||||
@@ -42,5 +42,5 @@ Inters3Planes( const Plane3d& plPlane1, const Plane3d& plPlane2, const Plane3d&
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES)
|
||||
return IPPT_NO ;
|
||||
// intersezione della linea con il terzo piano
|
||||
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
|
||||
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt, false) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersSurfTmSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersTriaTria.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkLineTgCurvePerpCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkLineTgTwoCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
+155
-33
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -16,20 +16,24 @@
|
||||
#include "CurveArc.h"
|
||||
#include "CurveLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool IsFillet( const ICurve* pCrv, double dDist) ;
|
||||
static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
|
||||
static bool AdjustIntersections( ICRVCOMPOPVECTOR& CrvList) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
|
||||
{
|
||||
// identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets
|
||||
for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) {
|
||||
// recupero la curva
|
||||
PtrOwner<ICurve> pCrv( pCrvCo->GetCurve(i)->Clone()) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
if ( IsFillet( pCrv, dDist))
|
||||
if ( IsFillet( pCrvCo->GetCurve( i), dDist))
|
||||
pCrvCo->SetCurveTempParam( i, 1.0) ;
|
||||
else
|
||||
pCrvCo->SetCurveTempParam( i, 0.0) ;
|
||||
@@ -39,12 +43,14 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsFillet( ICurve* pCrv, double dDist)
|
||||
IsFillet( const ICurve* pCrv, double dDist)
|
||||
{
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// deve essere un arco
|
||||
if ( pCrv->GetType() != CRV_ARC)
|
||||
return false ;
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
// deve avere raggio uguale alla distanza di offset
|
||||
if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL)
|
||||
return false ;
|
||||
@@ -54,36 +60,76 @@ IsFillet( ICurve* pCrv, double dDist)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType)
|
||||
AdjustCurveFillets( ICURVEPOVECTOR& vOffset, double dDist, int nType)
|
||||
{
|
||||
ICURVEPLIST CrvLst ;
|
||||
PtrOwner<ICurve> pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv)) {
|
||||
// se identificato come fillet lo trasformo in smusso o estensione
|
||||
if ( pCrv->GetTempParam() > EPS_SMALL) {
|
||||
CurveComposite ccTemp ;
|
||||
ModifyFillet( pCrv, dDist, nType, ccTemp) ;
|
||||
// metto in lista le curve risultanti
|
||||
if ( ccTemp.GetCurveCount() > 0) {
|
||||
PtrOwner<ICurve> pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
CrvLst.push_back( Release( pCrv2)) ;
|
||||
pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
if ( vOffset.empty())
|
||||
return true ;
|
||||
|
||||
// suddivido le curve di offset individuando i fillet e isolandoli dagli altri tratti
|
||||
ICRVCOMPOPVECTOR vCrvs ;
|
||||
for ( int i = 0 ; i < int( vOffset.size()) ; i ++) {
|
||||
CurveComposite* pCompo = GetBasicCurveComposite( vOffset[i]) ;
|
||||
if ( pCompo == nullptr)
|
||||
return false ;
|
||||
bool bNewCrv = true ;
|
||||
PtrOwner<ICurve> pCrv( pCompo->RemoveFirstOrLastCurve(false)) ;
|
||||
while ( ! IsNull( pCrv)) {
|
||||
if ( pCrv->GetTempParam() > EPS_SMALL) {
|
||||
// se fillet calcolo il nuovo raccordo
|
||||
CurveComposite* ccTemp = CreateBasicCurveComposite() ;
|
||||
ModifyFillet( pCrv, dDist, nType, *ccTemp) ;
|
||||
// assegno temp param per identificarlo nei conti successivi
|
||||
ccTemp->SetTempParam( 1) ;
|
||||
vCrvs.push_back( ccTemp) ;
|
||||
bNewCrv = true ;
|
||||
}
|
||||
else {
|
||||
// aggiungo la curva
|
||||
if ( bNewCrv) {
|
||||
bNewCrv = false ;
|
||||
CurveComposite* pCompo = ConvertCurveToBasicComposite( Release( pCrv)) ;
|
||||
if ( pCompo == nullptr)
|
||||
return false ;
|
||||
vCrvs.push_back( pCompo) ;
|
||||
}
|
||||
else
|
||||
vCrvs.back()->AddCurve( Release( pCrv)) ;
|
||||
}
|
||||
// passo alla curva successiva
|
||||
pCrv.Set( pCompo->RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
// altrimenti salvo in lista
|
||||
else
|
||||
CrvLst.push_back( Release( pCrv)) ;
|
||||
// passo alla curva successiva
|
||||
pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
// rimetto le curve nella composita
|
||||
for ( auto pCrv : CrvLst) {
|
||||
pCrvCo->AddCurve( pCrv) ;
|
||||
vOffset.clear() ;
|
||||
|
||||
// gestione delle intersezioni
|
||||
if ( ! AdjustIntersections( vCrvs))
|
||||
return false ;
|
||||
|
||||
// concateno i tratti ottenuti
|
||||
ChainCurves ChainCrv ;
|
||||
ChainCrv.Init( false, 2 * EPS_SMALL, vCrvs.size()) ;
|
||||
for ( int i = 0 ; i < int( vCrvs.size()); ++ i) {
|
||||
Point3d ptS, ptE ;
|
||||
Vector3d vtS, vtE ;
|
||||
vCrvs[i]->GetStartPoint( ptS) ;
|
||||
vCrvs[i]->GetEndPoint( ptE) ;
|
||||
vCrvs[i]->GetStartDir( vtS) ;
|
||||
vCrvs[i]->GetEndDir( vtE) ;
|
||||
ChainCrv.AddCurve( i + 1, ptS, vtS, ptE, vtE) ;
|
||||
}
|
||||
// recupero i concatenamenti
|
||||
Point3d ptRef ; vCrvs[0]->GetStartPoint( ptRef) ;
|
||||
INTVECTOR vIds ;
|
||||
while ( ChainCrv.GetChainFromNear( ptRef, false, vIds)) {
|
||||
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCompo))
|
||||
return false ;
|
||||
for ( auto i : vIds)
|
||||
pCompo->AddCurve( vCrvs[i-1]) ;
|
||||
pCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
pCompo->GetEndPoint( ptRef) ;
|
||||
vOffset.emplace_back( Release( pCompo)) ;
|
||||
}
|
||||
// unisco tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -177,3 +223,79 @@ ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux)
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustIntersections( ICRVCOMPOPVECTOR& vCrvs)
|
||||
{
|
||||
// sistema le curve nel vettore vCrvs eliminando le parti coinvolte nelle intersezioni
|
||||
|
||||
vector<Intervals> vIntervals( vCrvs.size()) ;
|
||||
INTVECTOR vFillets ;
|
||||
for ( int i = 0 ; i < int( vCrvs.size()) ; i ++) {
|
||||
// salvo i parametri della curva
|
||||
double dParS, dParE ;
|
||||
vCrvs[i]->GetDomain( dParS, dParE) ;
|
||||
vIntervals[i].Set( dParS, dParE) ;
|
||||
// verifico se raccordo
|
||||
if ( vCrvs[i]->GetTempParam() > EPS_SMALL)
|
||||
vFillets.emplace_back( i) ;
|
||||
}
|
||||
|
||||
// verifico se i raccordi intersecano le altre curve
|
||||
bool bInters = false ;
|
||||
for ( int i = 0 ; i < int( vFillets.size()) ; i ++) {
|
||||
int nIdx = vFillets[i] ;
|
||||
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++) {
|
||||
if ( j == nIdx)
|
||||
continue ;
|
||||
|
||||
IntersCurveCurve intCC( *vCrvs[nIdx], *vCrvs[j]) ;
|
||||
int nCnt = intCC.GetIntersCount() ;
|
||||
if ( nCnt > 1) {
|
||||
// aggiorno gli intervalli della curva sottraendo la parte coinvolta dall'intersezione
|
||||
for ( int k = 0 ; k < nCnt - 1 ; k = k+2) {
|
||||
IntCrvCrvInfo iccInfo1, iccInfo2 ;
|
||||
intCC.GetIntCrvCrvInfo( k, iccInfo1) ;
|
||||
// verifico non sia intersezione nell'estremo iniziale o sovrapposizione
|
||||
if ( iccInfo1.IciA[0].dU < EPS_SMALL || iccInfo1.bOverlap) {
|
||||
k-- ;
|
||||
continue ;
|
||||
}
|
||||
intCC.GetIntCrvCrvInfo( k+1, iccInfo2) ;
|
||||
|
||||
vIntervals[nIdx].Subtract( iccInfo1.IciA[0].dU, iccInfo2.IciA[0].dU) ;
|
||||
vIntervals[j].Subtract( iccInfo1.IciB[0].dU, iccInfo2.IciB[0].dU) ;
|
||||
bInters = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bInters)
|
||||
return true ;
|
||||
|
||||
// aggiorno le curve eliminando i tratti coinvolti nelle intersezioni
|
||||
for ( int i = 0 ; i < int( vIntervals.size()) ; i++) {
|
||||
if ( vIntervals[i].GetCount() > 1) {
|
||||
PtrOwner<CurveComposite> pCompo( CloneBasicCurveComposite( vCrvs[i])) ;
|
||||
if ( IsNull( pCompo))
|
||||
return false ;
|
||||
double dParS, dParE ;
|
||||
vIntervals[i].GetFirst( dParS, dParE) ;
|
||||
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
|
||||
while ( vIntervals[i].GetNext( dParS, dParE)) {
|
||||
CurveComposite* pCrv = ConvertCurveToBasicComposite( pCompo->CopyParamRange( dParS, dParE)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
vCrvs.emplace_back( pCrv) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
double dParS, dParE ;
|
||||
vIntervals[i].GetFirst( dParS, dParE) ;
|
||||
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+2
-4
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetAux.h Data : 23.11.23 Versione : 2.5k5
|
||||
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -16,6 +16,4 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
|
||||
bool IsFillet( ICurve* pCrv, double dDist) ;
|
||||
bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ;
|
||||
bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
|
||||
bool AdjustCurveFillets( ICURVEPOVECTOR& vCrvs, double dDist, int nType) ;
|
||||
+84
-28
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
|
||||
}
|
||||
}
|
||||
m_CrvLst.clear() ;
|
||||
m_ptOffs = P_INVALID ;
|
||||
m_vtOut = V_INVALID ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// verifico che la curva esista
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// verifico se la curva è un segmento di retta
|
||||
// verifico se la curva è un segmento di retta
|
||||
bool bIsLine = false ;
|
||||
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
|
||||
if ( pLine != nullptr)
|
||||
@@ -85,7 +87,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( pCompo != nullptr && pCompo->IsALine( m_dLinTol, ptStart, ptEnd))
|
||||
bIsLine = true ;
|
||||
}
|
||||
// verifico che la curva sia piana (per le linee è comunque sempre vero)
|
||||
// verifico che la curva sia piana (per le linee è comunque sempre vero)
|
||||
Plane3d plPlane ;
|
||||
if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL) && ! bIsLine)
|
||||
return false ;
|
||||
@@ -167,7 +169,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// -------------------- OFFSET STANDARD ---------------------------------
|
||||
if ( ! USE_VORONOI) {
|
||||
|
||||
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
|
||||
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
|
||||
if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, ANG_TOL_STD_DEG))
|
||||
return false ;
|
||||
|
||||
@@ -187,11 +189,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( ! ccCopy.MergeCurves( m_dLinTol, ANG_TOL_STD_DEG, bClosed, true))
|
||||
return false ;
|
||||
|
||||
// verifico se il punto iniziale è stato modificato
|
||||
// verifico se il punto iniziale è stato modificato
|
||||
Point3d ptNewStart ; ccCopy.GetStartPoint( ptNewStart) ;
|
||||
bChangeStart = ( ! AreSamePointApprox( ptNewStart, ptStart)) ;
|
||||
|
||||
// calcolo le lunghezze delle diverse entità
|
||||
// calcolo le lunghezze delle diverse entità
|
||||
DBLVECTOR vLens ;
|
||||
{
|
||||
const ICurve* pCrv1 = ccCopy.GetFirstCurve() ;
|
||||
@@ -203,7 +205,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
pCrv1 = ccCopy.GetNextCurve() ;
|
||||
}
|
||||
}
|
||||
// calcolo gli angoli tra le diverse entità
|
||||
// calcolo gli angoli tra le diverse entità
|
||||
DBLVECTOR vAngs ;
|
||||
{
|
||||
vAngs.push_back( 0) ;
|
||||
@@ -230,7 +232,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
vAngs.push_back( 0) ;
|
||||
}
|
||||
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
|
||||
CurveComposite ccCopy2 ;
|
||||
if ( ! ccCopy2.CopyFrom( &ccCopy))
|
||||
return false ;
|
||||
@@ -285,9 +287,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
|
||||
// se originale chiuso, devo confrontare anche ultima e prima curva
|
||||
if ( bClosed && m_CrvLst.size() >= 2) {
|
||||
// la curva precedente è l'ultima dell'offset
|
||||
// la curva precedente è l'ultima dell'offset
|
||||
ICurve* pCrv1 = m_CrvLst.back() ;
|
||||
// la curva successiva ora è la prima dell'offset
|
||||
// la curva successiva ora è la prima dell'offset
|
||||
ICurve* pCrv2 = m_CrvLst.front() ;
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
CurveComposite ccTemp ;
|
||||
@@ -334,7 +336,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
bool bNextInt = NextIsLine( iIter, m_CrvLst, bClosed) &&
|
||||
NextIsLonger( nInd1, vLens, bClosed) &&
|
||||
( ( dDist < 0 && vAngs[nInd1] > 0) || ( dDist > 0 && vAngs[nInd1] < 0)) ;
|
||||
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
|
||||
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
|
||||
double dMaxDist = INFINITO ;
|
||||
if ( bPrevInt && bNextInt) {
|
||||
double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ;
|
||||
@@ -502,7 +504,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
|
||||
// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
|
||||
if ( ! bClosed) {
|
||||
// ciconferenza sull'estremità iniziale
|
||||
// ciconferenza sull'estremità iniziale
|
||||
Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ;
|
||||
PtrOwner<CurveArc> pCircS( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCircS) || ! pCircS->Set( ptStart, Z_AX, abs( dDist)))
|
||||
@@ -551,7 +553,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// passo alla successiva
|
||||
++ iIter ;
|
||||
}
|
||||
// circonferenza sull'estremità finale
|
||||
// circonferenza sull'estremità finale
|
||||
Point3d ptEnd ; ccCopy.GetEndPoint( ptEnd) ;
|
||||
PtrOwner<CurveArc> pCircE( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCircE) || ! pCircE->Set( ptEnd, Z_AX, abs( dDist)))
|
||||
@@ -672,12 +674,20 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
}
|
||||
|
||||
// nono passo : se con smusso o estensione, sostituisco i fillet con questi
|
||||
// NB questa parte non è gestita in modo efficiente perchè dovrebbe essere sempre disabilitata.
|
||||
// Le funzioni sono state ottimizzate per lavorare con voronoi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) {
|
||||
CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ;
|
||||
IdentifyFillets( pCrvCo, dDist) ;
|
||||
AdjustCurveFillets( pCrvCo, dDist, nType) ;
|
||||
}
|
||||
ICURVEPOVECTOR vCrvs ;
|
||||
vCrvs.reserve( m_CrvLst.size()) ;
|
||||
for ( auto pCrv : m_CrvLst) {
|
||||
IdentifyFillets( GetCurveComposite( pCrv), dDist) ;
|
||||
vCrvs.emplace_back( pCrv) ;
|
||||
}
|
||||
if ( ! AdjustCurveFillets( vCrvs, dDist, nType))
|
||||
return false ;
|
||||
m_CrvLst.clear() ;
|
||||
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++)
|
||||
m_CrvLst.emplace_back( Release( vCrvs[j])) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,6 +707,27 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// calcolo offset con Voronoi
|
||||
ICURVEPOVECTOR vOffs ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
|
||||
if ( vOffs.empty()) {
|
||||
// se non ho ottenuto offset e sono circa al valore limite ritento con valore leggermente diverso per le tolleranze di vroni
|
||||
double dMaxOffs ;
|
||||
if ( ! pCrv->IsClosed() || ( voronoiObj->CalcLimitOffset( 0, dDist < 0, dMaxOffs) && abs( dMaxOffs - abs( dDist)) < EPS_SMALL)) {
|
||||
double dCorr = ( dDist > 0 ? - VRONI_OFFS_TOL : VRONI_OFFS_TOL) ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist + dCorr, nType) ;
|
||||
}
|
||||
// se ancora vuoto calcolo i punti speciali di offset ( punti e direzioni sui bisettore alla distanza richiesta)
|
||||
if ( vOffs.empty()) {
|
||||
PNTVECTVECTOR vPntOffs ;
|
||||
voronoiObj->CalcSpecialPointOffset( vPntOffs, dDist) ;
|
||||
// NB al momento vengono gestiti solo i casi in cui vi è un unico punto di offset. Se si ottengono più punti di offset
|
||||
// ( e.g. alcune curve aperte) non se ne restiusce nessuno. Da estendere, se necessario, individuando i punti dal lato
|
||||
// di offset richiesto
|
||||
if ( vPntOffs.size() == 1) {
|
||||
m_ptOffs = vPntOffs[0].first ;
|
||||
m_vtOut = vPntOffs[0].second ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++)
|
||||
m_CrvLst.emplace_back( Release( vOffs[i])) ;
|
||||
|
||||
@@ -724,10 +755,21 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
pCrv->ToGlob( frCopy) ;
|
||||
}
|
||||
if ( m_ptOffs.IsValid()) {
|
||||
m_ptOffs.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
m_ptOffs.ToGlob( frCopy) ;
|
||||
m_vtOut.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
m_vtOut.ToGlob( frCopy) ;
|
||||
}
|
||||
|
||||
}
|
||||
else if ( bNeedRef) {
|
||||
for ( auto pCrv : m_CrvLst)
|
||||
pCrv->ToGlob( frCopy) ;
|
||||
if ( m_ptOffs.IsValid()) {
|
||||
m_ptOffs.ToGlob( frCopy) ;
|
||||
m_vtOut.ToGlob( frCopy) ;
|
||||
}
|
||||
}
|
||||
|
||||
// assegno estrusione e spessore come curva originale e unisco parti allineate
|
||||
@@ -805,6 +847,20 @@ OffsetCurve::GetShorterCurve( void)
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OffsetCurve::GetPointOffset( Point3d& ptOffs, Vector3d& vtOut)
|
||||
{
|
||||
// verifico se valori validi da restituire
|
||||
if ( ! m_ptOffs.IsValid() || ! m_vtOut.IsValid())
|
||||
return false ;
|
||||
|
||||
ptOffs = m_ptOffs ;
|
||||
vtOut = m_vtOut ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool bClosed)
|
||||
@@ -817,7 +873,7 @@ PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bo
|
||||
// se non esiste e curva chiusa prendo l'ultimo
|
||||
if ( iPrev == CrvLst.end() && bClosed)
|
||||
-- iPrev ;
|
||||
// se non esiste o non è una linea, test fallito
|
||||
// se non esiste o non è una linea, test fallito
|
||||
if ( iPrev == CrvLst.end() || (*iPrev)->GetType() != CRV_LINE )
|
||||
return false ;
|
||||
// test superato
|
||||
@@ -830,7 +886,7 @@ PreviousIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
|
||||
{
|
||||
// massimo indice nel vettore
|
||||
int nMax = int( vLens.size()) - 1 ;
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
if ( nInd1 < 1 || nInd1 > nMax + 1)
|
||||
return false ;
|
||||
// indice del precedente nel vettore di lunghezze
|
||||
@@ -854,7 +910,7 @@ NextIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool b
|
||||
// se non esiste e curva chiusa prendo il primo
|
||||
if ( iNext == CrvLst.end() && bClosed)
|
||||
iNext = CrvLst.begin() ;
|
||||
// se non esiste o non è una linea, test fallito
|
||||
// se non esiste o non è una linea, test fallito
|
||||
if ( iNext == CrvLst.end() || (*iNext)->GetType() != CRV_LINE )
|
||||
return false ;
|
||||
// test superato
|
||||
@@ -867,7 +923,7 @@ NextIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
|
||||
{
|
||||
// massimo indice nel vettore
|
||||
int nMax = int( vLens.size()) - 1 ;
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
if ( nInd1 < 1 || nInd1 > nMax + 1)
|
||||
return false ;
|
||||
// indice del successivo nel vettore di lunghezze
|
||||
@@ -946,7 +1002,7 @@ VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
nRes = 4 ;
|
||||
return true ;
|
||||
}
|
||||
// se coincidono esattamente, va bene così
|
||||
// se coincidono esattamente, va bene così
|
||||
if ( AreSamePointExact( ptP1, ptP2)) {
|
||||
nRes = 0 ;
|
||||
return true ;
|
||||
@@ -976,7 +1032,7 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
|
||||
if ( intCC.GetIntersCount() == 0)
|
||||
return false ;
|
||||
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
|
||||
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
|
||||
Point3d ptP1, ptP2 ;
|
||||
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
||||
return false ;
|
||||
@@ -1024,7 +1080,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
vtDir2.Invert() ;
|
||||
}
|
||||
|
||||
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
|
||||
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
|
||||
if ( abs( dAngDeg) < ( ANG_STRAIGHT - 10 * EPS_ANG_ZERO) &&
|
||||
( ( dDist < 0 && dAngDeg > 0) ||
|
||||
( dDist > 0 && dAngDeg < 0)))
|
||||
@@ -1066,7 +1122,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
return false ;
|
||||
ptP1a = ptP1 + vtDir1 * dLen ;
|
||||
ptP2a = ptP2 - vtDir2 * dLen ;
|
||||
// se prima c'è linea posso allungarla
|
||||
// se prima c'è linea posso allungarla
|
||||
if ( pCrv1->GetType() == CRV_LINE)
|
||||
pCrv1->ModifyEnd( ptP1a) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1085,7 +1141,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! ccAux.AddCurve( Release( pCrv)))
|
||||
return false ;
|
||||
}
|
||||
// se dopo c'è linea posso allungarla
|
||||
// se dopo c'è linea posso allungarla
|
||||
if ( pCrv2->GetType() == CRV_LINE)
|
||||
pCrv2->ModifyStart( ptP2a) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1108,7 +1164,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
||||
return false ;
|
||||
ptPc = ptP1 + vtDir1 * dLen ;
|
||||
// se prima c'è linea o angolo molto piccolo posso allungarla
|
||||
// se prima c'è linea o angolo molto piccolo posso allungarla
|
||||
if ( ( pCrv1->GetType() == CRV_LINE) || bAngSmall)
|
||||
pCrv1->ModifyEnd( ptPc) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1119,7 +1175,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! ccAux.AddCurve( Release( pCrv)))
|
||||
return false ;
|
||||
}
|
||||
// se dopo c'è linea o angolo molto piccolo posso allungarla
|
||||
// se dopo c'è linea o angolo molto piccolo posso allungarla
|
||||
if ( ( pCrv2->GetType() == CRV_LINE) || bAngSmall)
|
||||
pCrv2->ModifyStart( ptPc) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
|
||||
+2
-2
@@ -195,7 +195,7 @@ PointGrid3d::Find( const Point3d& ptTest, double dTol, INTVECTOR& vnIds) const
|
||||
}
|
||||
}
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -221,7 +221,7 @@ PointGrid3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
}
|
||||
}
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+41
-31
@@ -14,36 +14,28 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "PointsPCA.h"
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PointsPCA::PointsPCA( void)
|
||||
{
|
||||
// azzero numero punti
|
||||
m_dTotW = 0 ;
|
||||
// azzero il baricentro
|
||||
m_ptCen.Set( 0, 0, 0) ;
|
||||
// azzero matrice di covarianza
|
||||
m_CovMat.setZero() ;
|
||||
// inizializzo il rank ad un valore assurdo
|
||||
m_nRank = - 1 ;
|
||||
// inizializzo baricentro
|
||||
m_ptCen.Set( 0, 0, 0) ;
|
||||
// inizializzo il peso totale
|
||||
m_dTotW = 0 ;
|
||||
// riservo memoria per la matrice di punti e pesi
|
||||
m_vPntW.reserve( 128) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
PointsPCA::AddPoint( const Point3d& ptP, double dW)
|
||||
{
|
||||
// incremento numero punti
|
||||
m_dTotW += dW ;
|
||||
// aggiorno il baricentro
|
||||
m_ptCen += dW * ptP ;
|
||||
// aggiorno la matrice di covarianza (solo triangolo superiore perchč simmetrica)
|
||||
m_CovMat(0,0) += dW * ( ptP.x * ptP.x) ;
|
||||
m_CovMat(1,1) += dW * ( ptP.y * ptP.y) ;
|
||||
m_CovMat(2,2) += dW * ( ptP.z * ptP.z) ;
|
||||
m_CovMat(0,1) += dW * ( ptP.x * ptP.y) ;
|
||||
m_CovMat(0,2) += dW * ( ptP.x * ptP.z) ;
|
||||
m_CovMat(1,2) += dW * ( ptP.y * ptP.z) ;
|
||||
// salvo i dati
|
||||
m_vPntW.emplace_back( ptP, dW) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -58,29 +50,47 @@ PointsPCA::Finalize( void)
|
||||
m_nRank = 0 ;
|
||||
|
||||
// se non sono stati assegnati punti, esco
|
||||
if ( m_dTotW < EPS_ZERO)
|
||||
if ( m_vPntW.empty())
|
||||
return false ;
|
||||
|
||||
// fattore di scala per numero di punti
|
||||
// calcolo del peso totale
|
||||
for ( const auto& PntW : m_vPntW)
|
||||
m_dTotW += PntW.second ;
|
||||
if ( m_dTotW < EPS_ZERO)
|
||||
return false ;
|
||||
// fattore di scala
|
||||
double dScale = 1 / m_dTotW ;
|
||||
|
||||
// calcolo del baricentro
|
||||
for ( const auto& PntW : m_vPntW)
|
||||
m_ptCen += PntW.second * PntW.first ;
|
||||
m_ptCen *= dScale ;
|
||||
|
||||
// completo la matrice di covarianza
|
||||
m_CovMat(0,0) = m_CovMat(0,0) * dScale - m_ptCen.x * m_ptCen.x ;
|
||||
m_CovMat(1,1) = m_CovMat(1,1) * dScale - m_ptCen.y * m_ptCen.y ;
|
||||
m_CovMat(2,2) = m_CovMat(2,2) * dScale - m_ptCen.z * m_ptCen.z ;
|
||||
m_CovMat(0,1) = m_CovMat(0,1) * dScale - m_ptCen.x * m_ptCen.y ;
|
||||
m_CovMat(0,2) = m_CovMat(0,2) * dScale - m_ptCen.x * m_ptCen.z ;
|
||||
m_CovMat(1,2) = m_CovMat(1,2) * dScale - m_ptCen.y * m_ptCen.z ;
|
||||
m_CovMat(1,0) = m_CovMat(0,1) ;
|
||||
m_CovMat(2,0) = m_CovMat(0,2) ;
|
||||
m_CovMat(2,1) = m_CovMat(1,2) ;
|
||||
// matrice di covarianza
|
||||
Eigen::Matrix3d CovMat ;
|
||||
CovMat.setZero() ;
|
||||
for ( const auto& PntW : m_vPntW) {
|
||||
Point3d ptP( PntW.first.x - m_ptCen.x, PntW.first.y - m_ptCen.y, PntW.first.z - m_ptCen.z) ;
|
||||
CovMat(0,0) += PntW.second * ( ptP.x * ptP.x) ;
|
||||
CovMat(1,1) += PntW.second * ( ptP.y * ptP.y) ;
|
||||
CovMat(2,2) += PntW.second * ( ptP.z * ptP.z) ;
|
||||
CovMat(0,1) += PntW.second * ( ptP.x * ptP.y) ;
|
||||
CovMat(0,2) += PntW.second * ( ptP.x * ptP.z) ;
|
||||
CovMat(1,2) += PntW.second * ( ptP.y * ptP.z) ;
|
||||
}
|
||||
CovMat(0,0) = CovMat(0,0) * dScale ;
|
||||
CovMat(1,1) = CovMat(1,1) * dScale ;
|
||||
CovMat(2,2) = CovMat(2,2) * dScale ;
|
||||
CovMat(0,1) = CovMat(0,1) * dScale ;
|
||||
CovMat(0,2) = CovMat(0,2) * dScale ;
|
||||
CovMat(1,2) = CovMat(1,2) * dScale ;
|
||||
CovMat(1,0) = CovMat(0,1) ;
|
||||
CovMat(2,0) = CovMat(0,2) ;
|
||||
CovMat(2,1) = CovMat(1,2) ;
|
||||
|
||||
// calcolo gli autovalori e autovettori (essendo matrice 3x3 uso metodo diretto)
|
||||
// calcolo gli autovalori e autovettori
|
||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es ;
|
||||
es.compute( m_CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
|
||||
es.compute( CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
|
||||
if ( es.info() == Eigen::NoConvergence)
|
||||
return false ;
|
||||
|
||||
|
||||
+3
-4
@@ -13,8 +13,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class PointsPCA
|
||||
@@ -33,9 +32,9 @@ class PointsPCA
|
||||
static const int MAX_RANK = 3 ;
|
||||
|
||||
private :
|
||||
double m_dTotW ; // peso totale (se pesi tutti unitari, allora è numero punti)
|
||||
PNTUVECTOR m_vPntW ; // vettore dei punti con i loro pesi
|
||||
Point3d m_ptCen ; // baricentro
|
||||
Eigen::Matrix3d m_CovMat ; // matrice di covarianza
|
||||
double m_dTotW ; // peso totale
|
||||
int m_nRank ; // numero delle componenti principali (MAX_RANK = 3)
|
||||
Vector3d m_vtPC[MAX_RANK] ; // direzioni delle componenti principali
|
||||
} ;
|
||||
+4
-4
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveArc.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyArc.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include <algorithm>
|
||||
@@ -62,7 +62,7 @@ bool
|
||||
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
|
||||
{
|
||||
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
|
||||
if ( m_lUPointBs.size() > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
||||
if ( ! m_lUPointBs.empty() && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
||||
// assegno parametro e bulge
|
||||
m_lUPointBs.back().dU = dPar ;
|
||||
m_lUPointBs.back().dB = dBulge ;
|
||||
@@ -285,10 +285,10 @@ bool
|
||||
PolyArc::Join( PolyArc& PA, double dOffsetPar)
|
||||
{
|
||||
// se l'altro poliarco non contiene alcunchè, esco con ok
|
||||
if ( PA.m_lUPointBs.size() == 0)
|
||||
if ( PA.m_lUPointBs.empty())
|
||||
return true ;
|
||||
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
|
||||
if ( m_lUPointBs.size() > 0 && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
|
||||
if ( ! m_lUPointBs.empty() && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
|
||||
return false ;
|
||||
// cancello l'ultimo di questo
|
||||
EraseLastUPoint() ;
|
||||
|
||||
+119
-79
@@ -1,4 +1,4 @@
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : PolyLine.cpp Data : 22.12.13 Versione : 1.4l3
|
||||
@@ -14,13 +14,13 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "PointsPCA.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
|
||||
@@ -53,8 +53,8 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
{
|
||||
// se da aggiungere in coda
|
||||
if ( bEndOrStart) {
|
||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -68,8 +68,8 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
}
|
||||
// altrimenti si aggiunge in testa
|
||||
else {
|
||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ PolyLine::Close( void)
|
||||
// ci devono essere almeno 2 punti
|
||||
if ( m_lUPoints.size() < 2)
|
||||
return false ;
|
||||
// verifico non sia già chiuso
|
||||
// verifico non sia già chiuso
|
||||
if ( AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first))
|
||||
return false ;
|
||||
// aggiungo un punto uguale al primo in coda
|
||||
@@ -219,7 +219,7 @@ PolyLine::ToLoc( const Frame3d& frRef)
|
||||
bool
|
||||
PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
{
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
// ciclo sui punti
|
||||
@@ -233,11 +233,11 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
bool
|
||||
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
||||
{
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
if ( PL.m_lUPoints.size() == 0)
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
if ( PL.m_lUPoints.empty())
|
||||
return true ;
|
||||
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
|
||||
if ( m_lUPoints.size() > 0 && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
|
||||
if ( ! m_lUPoints.empty() && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
|
||||
return false ;
|
||||
// cancello l'ultimo di questa
|
||||
EraseLastUPoint() ;
|
||||
@@ -385,7 +385,7 @@ PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP, bool bNotFirst) const
|
||||
bool
|
||||
PolyLine::GetCurrUPoint( double* pdPar, Point3d* pptP) const
|
||||
{
|
||||
// verifico validità punto corrente
|
||||
// verifico validità punto corrente
|
||||
if ( m_iter == m_lUPoints.end())
|
||||
return false ;
|
||||
|
||||
@@ -426,7 +426,7 @@ PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
|
||||
bool
|
||||
PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const
|
||||
{
|
||||
// parametro e punto iniziali (è il precedente finale)
|
||||
// parametro e punto iniziali (è il precedente finale)
|
||||
if ( m_iter == m_lUPoints.end())
|
||||
return false ;
|
||||
if ( pdIni != nullptr)
|
||||
@@ -510,19 +510,19 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
|
||||
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
|
||||
// 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
|
||||
if ( nRank == 0)
|
||||
return ptsPCA.GetCenter( ptCen) ;
|
||||
// se dimensione 1, allora i punti sono distribuiti su una linea
|
||||
if ( nRank == 1) {
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
ptsPCA.GetPrincipalComponent( 0, vtDir) ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
|
||||
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
|
||||
// Center and normal vector
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
Vector3d vtX, vtY ;
|
||||
@@ -530,9 +530,9 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
|
||||
ptsPCA.GetPrincipalComponent( 1, vtY) ;
|
||||
vtDir = vtX ^ vtY ;
|
||||
if ( ! vtDir.Normalize()) {
|
||||
// riduco la dimensionalità a lineare
|
||||
// riduco la dimensionalità a lineare
|
||||
nRank = 1 ;
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
vtDir = vtX ;
|
||||
return true ;
|
||||
@@ -561,12 +561,12 @@ PolyLine::IsFlat( Plane3d& plPlane, double dToler) const
|
||||
plPlane.Reset() ;
|
||||
return false ;
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
// recupero dati sulla planarità della polilinea
|
||||
int nRank ;
|
||||
Point3d ptCen ;
|
||||
Vector3d vtDir ;
|
||||
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
|
||||
// imposto il piano a seconda della dimensionalità
|
||||
// imposto il piano a seconda della dimensionalità
|
||||
switch ( nRank) {
|
||||
case 0 : // punto
|
||||
plPlane.Set( ptCen, Z_AX) ;
|
||||
@@ -587,18 +587,29 @@ PolyLine::IsClosedAndFlat( Plane3d& plPlane, double& dArea, double dToler) const
|
||||
// Test if closed
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// Compute a representative plane for the polygon
|
||||
Point3d ptP ;
|
||||
// Calcolo il centro (per minimizzare gli errori nelle successive operazioni)
|
||||
Point3d ptCen = ORIG ;
|
||||
int nCount = 0 ;
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
|
||||
ptCen += ptP ;
|
||||
++ nCount ;
|
||||
}
|
||||
ptCen /= nCount ;
|
||||
Vector3d vtMove = ptCen - ORIG ;
|
||||
// Compute a representative plane for the polygon (faccio il calcolo nel centro e poi traslo al contrario il piano)
|
||||
PolygonPlane PolyPlane ;
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
|
||||
PolyPlane.AddPoint( ptP) ;
|
||||
PolyPlane.AddPoint( ptP - vtMove) ;
|
||||
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea)) {
|
||||
dArea = 0 ;
|
||||
return IsFlat( plPlane, dToler) ;
|
||||
}
|
||||
plPlane.Translate( vtMove) ;
|
||||
// Sistemo il piano per l'offset utilizzato
|
||||
// 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() ;
|
||||
double dDist = DistPointPlane( ptP, plPlane) ;
|
||||
if ( abs( dDist) > dToler)
|
||||
return false ;
|
||||
}
|
||||
@@ -639,13 +650,13 @@ PolyLine::GetAreaXY( double& dArea) const
|
||||
// verifico sia chiusa
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// calcolo l'area considerando solo XY (è la Z di Newell)
|
||||
// calcolo l'area considerando solo XY (è la Z di Newell)
|
||||
dArea = 0 ;
|
||||
Point3d ptIni, ptFin ;
|
||||
for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
|
||||
dArea += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
|
||||
}
|
||||
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
|
||||
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
|
||||
// significativa anche se sono coincidenti per le nostre tolleranze
|
||||
ptIni = ptFin ;
|
||||
GetFirstPoint( ptFin) ;
|
||||
@@ -746,7 +757,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
|
||||
}
|
||||
}
|
||||
|
||||
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
||||
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
||||
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
|
||||
if ( dMaxSqDist > dSqTol) {
|
||||
// inserisco il punto
|
||||
@@ -789,7 +800,7 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
}
|
||||
// altrimenti chiusa
|
||||
else {
|
||||
// cerco il punto più distante dal primo
|
||||
// cerco il punto più distante dal primo
|
||||
double dMaxDist = 0. ;
|
||||
int nMaxInd = 0 ;
|
||||
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
|
||||
@@ -812,6 +823,14 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
// ordino in senso crescente
|
||||
sort( vInd.begin(), vInd.end()) ;
|
||||
|
||||
// se chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[vInd.size()-2]].first).IsEpsilon( dToler)) {
|
||||
vInd.erase( vInd.begin()) ;
|
||||
vInd.back() = vInd.front() ;
|
||||
}
|
||||
}
|
||||
|
||||
// rimetto in lista i soli punti rimasti
|
||||
m_lUPoints.clear() ;
|
||||
for ( auto Ind : vInd)
|
||||
@@ -958,7 +977,7 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
|
||||
}
|
||||
}
|
||||
}
|
||||
// non è stato eliminato alcunché
|
||||
// non è stato eliminato alcunché
|
||||
// ripristino la tolleranza corrente
|
||||
dCurrToler = dToler ;
|
||||
// avanzo il terzetto di uno step
|
||||
@@ -999,7 +1018,7 @@ PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
bool
|
||||
PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
{
|
||||
// ciclo i controlli finchè non ci sono rimozioni
|
||||
// ciclo i controlli finchè non ci sono rimozioni
|
||||
bool bRemoved = true ;
|
||||
while ( bRemoved) {
|
||||
bRemoved = false ;
|
||||
@@ -1027,7 +1046,7 @@ PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
bRemoved = true ;
|
||||
continue ;
|
||||
}
|
||||
// non è stato eliminato alcunché : avanzo il terzetto di uno step
|
||||
// non è stato eliminato alcunché : avanzo il terzetto di uno step
|
||||
precP = currP ;
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
@@ -1054,7 +1073,7 @@ PolyLine::Invert( bool bInvertU)
|
||||
m_lUPoints.reverse() ;
|
||||
// se richiesto, inverto anche il parametro U
|
||||
if ( bInvertU) {
|
||||
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
|
||||
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
|
||||
double dUfin = m_lUPoints.front().second ;
|
||||
// ciclo su tutti gli elementi
|
||||
for ( auto& UPoint : m_lUPoints) {
|
||||
@@ -1064,6 +1083,35 @@ PolyLine::Invert( bool bInvertU)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::MyRemoveSamePoints( double dToler)
|
||||
{
|
||||
// elimino i punti consecutivi diventati coincidenti (almeno 2)
|
||||
if ( m_lUPoints.size() < 2)
|
||||
return true ;
|
||||
// punto precedente
|
||||
auto precP = m_lUPoints.begin() ;
|
||||
// punto corrente
|
||||
auto currP = next( precP) ;
|
||||
// mentre esiste un corrente
|
||||
while ( currP != m_lUPoints.end()) {
|
||||
// se coincidono
|
||||
if ( AreSamePointEpsilon( precP->first, currP->first, dToler)) {
|
||||
// elimino il punto corrente
|
||||
currP = m_lUPoints.erase( currP) ;
|
||||
// il precedente rimane inalterato
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo la coppia di uno step
|
||||
precP = currP ;
|
||||
++ currP ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::Flatten( double dZ)
|
||||
@@ -1072,31 +1120,39 @@ PolyLine::Flatten( double dZ)
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// ciclo su tutti gli elementi per portarli alla Z indicata
|
||||
for ( auto& UPoint : m_lUPoints) {
|
||||
for ( auto& UPoint : m_lUPoints)
|
||||
UPoint.first.z = dZ ;
|
||||
}
|
||||
// elimino i punti consecutivi diventati coincidenti (almeno 2)
|
||||
if ( m_lUPoints.size() < 2)
|
||||
// elimino i punti consecutivi diventati coincidenti
|
||||
MyRemoveSamePoints() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::FlattenInAutoPlane( double dToler)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// punto precedente
|
||||
auto precP = m_lUPoints.begin() ;
|
||||
// punto corrente
|
||||
auto currP = next( precP) ;
|
||||
// mentre esiste un corrente
|
||||
while ( currP != m_lUPoints.end()) {
|
||||
// se coincidono
|
||||
if ( AreSamePointApprox( precP->first, currP->first)) {
|
||||
// elimino il punto corrente
|
||||
currP = m_lUPoints.erase( currP) ;
|
||||
// il precedente rimane inalterato
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo la coppia di uno step
|
||||
precP = currP ;
|
||||
++ currP ;
|
||||
}
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
int nRank ;
|
||||
Point3d ptCen ;
|
||||
Vector3d vtDir ;
|
||||
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
|
||||
// se non planare entro la tolleranza, esco
|
||||
if ( ! bFlat)
|
||||
return false ;
|
||||
// se punto o linea, non devo fare alcunché
|
||||
if ( nRank == 0 || nRank == 1)
|
||||
return true ;
|
||||
// assegno il piano medio
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptCen, vtDir) ;
|
||||
// proietto i punti su questo piano
|
||||
for ( auto& UPoint : m_lUPoints)
|
||||
UPoint.first = ProjectPointOnPlane( UPoint.first, plPlane) ;
|
||||
// elimino i punti consecutivi diventati coincidenti
|
||||
MyRemoveSamePoints() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1269,8 +1325,8 @@ PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, d
|
||||
bool
|
||||
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||
{
|
||||
// se vuota non faccio alcunché
|
||||
if ( m_lUPoints.size() == 0)
|
||||
// se vuota non faccio alcunché
|
||||
if ( m_lUPoints.empty())
|
||||
return false ;
|
||||
|
||||
// determino le intersezioni dei lati con il piano
|
||||
@@ -1371,7 +1427,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& List = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
Point3d ptMinDist ;
|
||||
auto itMinDistEnd = List.end() ;
|
||||
@@ -1460,7 +1516,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol
|
||||
// assegno nuovo inizio
|
||||
ptStart = ptEnd ;
|
||||
}
|
||||
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
|
||||
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
|
||||
return ( dMinSqDist < dToler * dToler) ;
|
||||
}
|
||||
|
||||
@@ -1473,7 +1529,7 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
auto itStart = LoopList.begin() ;
|
||||
@@ -1517,7 +1573,7 @@ SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler,
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
const PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
auto itStart = LoopList.begin() ;
|
||||
@@ -1581,10 +1637,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
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 ;
|
||||
@@ -1593,7 +1645,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// 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) {
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += j - 1 ;
|
||||
@@ -1601,14 +1653,10 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
}
|
||||
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
|
||||
// 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 ;
|
||||
|
||||
@@ -1619,9 +1667,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// 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) {
|
||||
|
||||
@@ -1631,8 +1676,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// 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) {
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += i - 1 ;
|
||||
@@ -1640,10 +1684,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
}
|
||||
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 ;
|
||||
|
||||
|
||||
@@ -150,12 +150,18 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
Vector3d vtN = pgFacet.GetVersN() ;
|
||||
PolyLine PL = pgFacet.GetPolyLine() ;
|
||||
|
||||
// calcolo elevazione massima del contorno della faccia
|
||||
// calcolo elevazione massima del contorno della faccia e nel suo centro
|
||||
const double RAY_LEN = 100000 ;
|
||||
dElev = 0 ;
|
||||
PNTVECTOR vptP ; vptP.reserve( PL.GetPointNbr()) ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstPoint( ptP) ;
|
||||
while ( bFound) {
|
||||
vptP.push_back( ptP) ;
|
||||
bFound = PL.GetNextPoint( ptP, true) ;
|
||||
}
|
||||
vptP.push_back( ptCen) ;
|
||||
for ( const Point3d& ptP : vptP) {
|
||||
ILSIVECTOR vInters ;
|
||||
IntersLineSurfTm( ptP, vtN, RAY_LEN, CldStm, vInters, true) ;
|
||||
for ( int i = 0 ; i < int( vInters.size()) ; ++ i) {
|
||||
@@ -171,7 +177,6 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
dElev = max( dElev, Inters.dU2) ;
|
||||
}
|
||||
bFound = PL.GetNextPoint( ptP, true) ;
|
||||
}
|
||||
// calcolo elevazione massima degli eventuali spigoli (e vertici) della superficie chiusa dalla parte positiva della faccia e che cadono in essa
|
||||
int nEdgeCnt = CldStm.GetEdgeCount() ;
|
||||
|
||||
+5
-5
@@ -19,10 +19,10 @@
|
||||
void
|
||||
PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
{
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
if ( m_nPntNbr == -1) {
|
||||
// inizializzazioni
|
||||
m_dLenN = 0 ;
|
||||
m_dLenN = -1 ;
|
||||
m_vtN = V_NULL ;
|
||||
m_ptMid = ORIG ;
|
||||
m_dSXy = 0 ; m_dSXz = 0 ;
|
||||
@@ -60,16 +60,16 @@ PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
bool
|
||||
PolygonPlane::Finalize( void)
|
||||
{
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
if ( m_nPntNbr + 1 < 3)
|
||||
return false ;
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
if ( ! AreSamePointExact( m_ptFirst, m_ptLast)) {
|
||||
// aggiungo il primo punto per far eseguire i conti sul lato di chiusura
|
||||
AddPoint( m_ptFirst) ;
|
||||
}
|
||||
// se non effettuato, eseguo il calcolo finale
|
||||
if ( m_dLenN < EPS_SMALL) {
|
||||
if ( m_dLenN < 0) {
|
||||
// lunghezza della normale (doppio dell'area del poligono)
|
||||
m_dLenN = m_vtN.Len() ;
|
||||
if ( m_dLenN < SQ_EPS_SMALL)
|
||||
|
||||
@@ -0,0 +1,892 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2023
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 31.08.23 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurf.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
|
||||
const double COS_ANG_LIM = 0.0175 ;
|
||||
// Angolo massimo tra normali per effettuare bisezione su spigolo
|
||||
const double COS_ANG_MAX_CORNER = 0.8660 ;
|
||||
// Tipologia di punto
|
||||
const int P5AX_TO_DELETE = -1 ; // da cancellare
|
||||
const int P5AX_OUT = 0 ; // aggiunto prima di inizio o dopo fine
|
||||
const int P5AX_STD = 1 ; // standard
|
||||
const int P5AX_CVEX = 2 ; // su angolo convesso
|
||||
const int P5AX_CONC = 3 ; // in angolo concavo
|
||||
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
{
|
||||
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
|
||||
{
|
||||
// Parametri di riferimento
|
||||
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
|
||||
double dSqTol = dLinTol * dLinTol ;
|
||||
const double LENREF = 200 ;
|
||||
double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ;
|
||||
// Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo
|
||||
int nInd = 0 ;
|
||||
while ( nInd < int( vPt5ax.size())) {
|
||||
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
|
||||
// analizzo i punti appena precedenti
|
||||
int nIpv = nInd - 1 ;
|
||||
while ( nIpv >= 0) {
|
||||
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nIpv].ptP) ;
|
||||
if ( dSqLen < dSqMaxLen)
|
||||
vPt5ax[nIpv].nFlag = P5AX_TO_DELETE ;
|
||||
else {
|
||||
vPt5ax[nIpv].nFlag = P5AX_BEFORE_CONC ;
|
||||
break ;
|
||||
}
|
||||
-- nIpv ;
|
||||
}
|
||||
// analizzo i punti appena successivi
|
||||
int nInx = nInd + 1 ;
|
||||
while ( nInx < int( vPt5ax.size())) {
|
||||
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
|
||||
if ( dSqLen < dSqMaxLen)
|
||||
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
|
||||
else {
|
||||
vPt5ax[nInx].nFlag = P5AX_AFTER_CONC ;
|
||||
break ;
|
||||
}
|
||||
++ nInx ;
|
||||
}
|
||||
}
|
||||
++ nInd ;
|
||||
}
|
||||
// Rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
int nCnt = 0 ;
|
||||
int nPrec = 0 ;
|
||||
int nCurr = 1 ;
|
||||
int nNext = 2 ;
|
||||
while ( nNext < int( vPt5ax.size())) {
|
||||
bool bRemove = false ;
|
||||
// lunghezza del segmento che unisce gli adiacenti
|
||||
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
|
||||
// se rimovibile (Flag standard) e lunghezza inferiore al massimo, passo agli altri controlli
|
||||
if ( vPt5ax[nCurr].nFlag == P5AX_STD && dSqLen <= dSqMaxLen) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( vPt5ax[nCurr].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
|
||||
double dSqDist ;
|
||||
// se distanza inferiore a tolleranza lineare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vPt5ax, nPrec, nCurr, nNext, dSqTol)) {
|
||||
// verifico se errore angolare inferiore a limite
|
||||
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
|
||||
if ( bTestDir) {
|
||||
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir1, vPt5ax[nNext].vtDir1, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir1 > dCosAngLim)
|
||||
bRemove = true ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir2, vPt5ax[nNext].vtDir2, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir2 > dCosAngLim)
|
||||
bRemove = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se da eliminare
|
||||
if ( bRemove) {
|
||||
// dichiaro da eliminare il punto
|
||||
vPt5ax[nCurr].nFlag = P5AX_TO_DELETE ;
|
||||
// avanzo con corrente e successivo
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo il terzetto di uno step
|
||||
nPrec = nCurr ;
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
// incremento contatore dei punti conservati
|
||||
++ nCnt ;
|
||||
}
|
||||
}
|
||||
|
||||
// Copio i punti da conservare in un vettore temporaneo
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( nCnt) ;
|
||||
for ( const auto& Pt5ax : vPt5ax) {
|
||||
if ( Pt5ax.nFlag != P5AX_TO_DELETE)
|
||||
vMyPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
// scambio i due vettori
|
||||
vPt5ax.swap( vMyPt5ax) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ; // vettore di oggetti intersezione massiva rette parallele SurfTM
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
|
||||
double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = frRefLine.VersZ() ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
// approssimo la curva con una polilinea alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Oggetti per calcolo massivo intersezioni tra linee di proiezione e superfici
|
||||
Frame3d frRefLine ;
|
||||
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||
return false ;
|
||||
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
|
||||
for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) {
|
||||
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
|
||||
if ( pIntPLSTM == nullptr) {
|
||||
for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j)
|
||||
delete vpIntPLSTM[j] ;
|
||||
return false ;
|
||||
}
|
||||
vpIntPLSTM.emplace_back( pIntPLSTM) ;
|
||||
}
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// Libero oggetti per calcolo massivo
|
||||
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i)
|
||||
delete vpIntPLSTM[i] ;
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, ( vPt5ax[i].ptP - vPt5ax[j].ptP) ^ vtDir) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
|
||||
Pt5ax.vtDir2 = vtDir ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
// intersezione della retta di minima distanza con le superfici
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// punto medio
|
||||
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
|
||||
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptMid, vpSurfTm, gpRef, dMid, Pt5ax)) {
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
Point3d ptMin ;
|
||||
int nFlag ;
|
||||
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
|
||||
// intersezione della retta di minima distanza con le superfici
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// assegno il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// Sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// Controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// Approssimo la curva con una polilinea alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir2 ^ vPt5ax[j].vtDir2) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, stmRef) ;
|
||||
Point3d ptMin ;
|
||||
int nTriaMin ;
|
||||
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
|
||||
// recupero direzione della retta di minima distanza, altrimenti normale alla superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL)
|
||||
vtLine /= dLineLen ;
|
||||
else {
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
if ( ! CalcNormal( ptMin, trGuide, vtLine))
|
||||
vtLine = trGuide.GetN() ;
|
||||
dLineLen = 100 ;
|
||||
}
|
||||
// intersezione della retta con le superfici (conservo l'intersezione più alta)
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptMin, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
Vector3d vtN2 ;
|
||||
if ( ! CalcNormal( ptMin, trGuide, vtN2))
|
||||
vtN2 = trGuide.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtN2 ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// sistemazioni per tipo di superficie di riferimento
|
||||
const SurfTriMesh* pRefTm = nullptr ;
|
||||
switch ( sfRef.GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pRefTm = GetBasicSurfTriMesh( &sfRef) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurf() ;
|
||||
break ;
|
||||
case SRF_FLATRGN :
|
||||
pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pRefTm == nullptr)
|
||||
return false ;
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges) {
|
||||
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// punto medio
|
||||
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
|
||||
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptMid, vpSurfTm, *pRefTm, dMid, Pt5ax)) {
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1,393 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2023
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 31.08.23 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
{
|
||||
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen)
|
||||
{
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
|
||||
double dSqTol = dLinTol * dLinTol ;
|
||||
int nPrec = 0 ;
|
||||
int nCurr = 1 ;
|
||||
int nNext = 2 ;
|
||||
while ( nNext < int( vMyPt5ax.size())) {
|
||||
bool bRemove = false ;
|
||||
// lunghezza del segmento che unisce gli adiacenti
|
||||
double dSqLen = SqDist( vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
|
||||
// se lunghezza inferiore al massimo, passo agli altri controlli
|
||||
if ( dSqLen <= dSqMaxLen) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
|
||||
double dSqDist ;
|
||||
// se distanza inferiore a tolleranza lineare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) {
|
||||
// verifico se errore angolare inferiore a limite
|
||||
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
|
||||
Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD))
|
||||
bRemove = true ;
|
||||
}
|
||||
}
|
||||
// se da eliminare
|
||||
if ( bRemove) {
|
||||
// dichiaro da eliminare il punto
|
||||
vMyPt5ax[nCurr].nFlag = -1 ;
|
||||
// avanzo con corrente e successivo
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo il terzetto di uno step
|
||||
nPrec = nCurr ;
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
|
||||
PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
|
||||
Frame3d frRefLine ;
|
||||
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||
return false ;
|
||||
IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
|
||||
if ( ! vIntRes.empty()) {
|
||||
// calcolo il punto
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, dPar, 1) ;
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
if ( vIntRes.size() > 0) {
|
||||
// calcolo il punto
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto sulla curva a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
Point3d ptMin ;
|
||||
int nFlag ;
|
||||
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
if ( vIntRes.size() > 0) {
|
||||
// calcolo il punto
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ISurfTriMesh& tmRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, tmRef) ;
|
||||
Point3d ptMin ;
|
||||
int nTriaMin ;
|
||||
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
if ( vIntRes.size() > 0) {
|
||||
// calcolo il punto
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! tmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
Vector3d vtN2 ;
|
||||
double dU2, dV2, dW2 ;
|
||||
if ( BarycentricCoord( ptMin, trGuide, dU2, dV2, dW2))
|
||||
vtN2 = dU2 * trGuide.GetVertexNorm( 0) + dV2 * trGuide.GetVertexNorm( 1) + dW2 * trGuide.GetVertexNorm( 2) ;
|
||||
if ( ! vtN2.Normalize())
|
||||
vtN2 = trGuide.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@@ -0,0 +1,772 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 20024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SbzFromCurves.cpp Data : 07.05.24 Versione : 2.6e2
|
||||
// Contenuto : Implementazione di funzioni per creazione di superfici Sbz
|
||||
// a partire da curve, con diversi metodi.
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.05.24 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkSbzFromCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <future>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr)
|
||||
return nullptr ;
|
||||
// calcolo la polilinea che approssima la curva
|
||||
PolyLine PL ;
|
||||
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return nullptr ;
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( &vpCurve == nullptr || vpCurve.empty())
|
||||
return nullptr ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat,vbInvert))
|
||||
return nullptr ;
|
||||
POLYLINEVECTOR vPLOrd ;
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ;
|
||||
if( vbInvert[vnPLIndMat[i][j]])
|
||||
vPLOrd.back().Invert() ;
|
||||
}
|
||||
}
|
||||
// creo e setto la superficie di bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByRegion( vPLOrd))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
|
||||
bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &vtExtr == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ;
|
||||
// creo e setto la superficie di Bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfCompo*
|
||||
//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) ///// RICHIEDE LE SURF COMPO/////////////////
|
||||
//{
|
||||
// // verifica parametri
|
||||
// if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr)
|
||||
// return nullptr ;
|
||||
// // se una sola curva, uso la funzione precedente
|
||||
// if ( vpCurve.size() == 1 )
|
||||
// return GetSurfBezierByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
|
||||
// // calcolo le polilinee che approssimano le curve della regione
|
||||
// POLYLINEVECTOR vPL ;
|
||||
// Vector3d vtN ;
|
||||
// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
// return nullptr ;
|
||||
// // verifico la direzione di estrusione
|
||||
// double dOrthoExtr = vtN * vtExtr ;
|
||||
// if ( ( abs( dOrthoExtr) < EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// // se componente estrusione negativa, inverto tutti i percorsi
|
||||
// if ( dOrthoExtr < 0) {
|
||||
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
|
||||
// vPL[i].Invert() ;
|
||||
// }
|
||||
// // creo la prima superficie di estremità
|
||||
// PtrOwner<SurfBezier> pSbz1( CreateBasicSurfBezier()) ;
|
||||
// if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL))
|
||||
// return nullptr ;
|
||||
// // creo la seconda superficie come copia della prima e poi inverto la prima
|
||||
// PtrOwner<ISurfBezier> pSbz2( pSbz1->Clone()) ;
|
||||
// pSbz1->Invert() ;
|
||||
//
|
||||
// // creo e unisco le diverse superfici di estrusione
|
||||
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// // estrusione
|
||||
// SurfBezier SbzLat ;
|
||||
// if ( ! SbzLat.CreateByExtrusion( vPL[i], vtExtr)) // qui mi serve la curva e non la polyline della curva. vuol dire che dalla CalcRegionPolyLines devo farmi restituire anche le curve ordinate
|
||||
// return nullptr ;
|
||||
// }
|
||||
// // restituisco la superficie
|
||||
// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica
|
||||
//}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
bool bCapEnds, double dLinTol) // con l'aggiunta delle SURFCOMPO posso gestire anche i cap e curve che attraversano l'asse
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, ANG_FULL, 0))
|
||||
return nullptr ;
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSbz->GetVolume( dVol) && dVol < 0)
|
||||
pSbz->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
|
||||
// creo e setto la superficie bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
|
||||
return nullptr ;
|
||||
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSbz->GetVolume( dVol) && dVol < 0)
|
||||
pSbz->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// riferimento all'inizio della linea guida
|
||||
Frame3d frStart ;
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch ( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
bGuideIsPolyLine = true ;
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
|
||||
const ICurve* pCrv = pCC->GetCurve( i) ;
|
||||
if( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
}
|
||||
else
|
||||
bGuideIsPolyLine = false ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
}
|
||||
case CRV_LINE :
|
||||
bGuideIsPolyLine = true ;
|
||||
break ;
|
||||
case CRV_BEZIER : {
|
||||
// controllo se i punti di controllo sono allineati
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
break ;
|
||||
}
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
||||
bool bRat = false ;
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine ) {
|
||||
if( pGuide->GetType() == CRV_LINE)
|
||||
nSpanV = 1 ;
|
||||
else if ( pGuide->GetType() == CRV_COMPO)
|
||||
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
|
||||
}
|
||||
else {
|
||||
//converto in bezier la guida ( grado 3, non razionale)
|
||||
if ( pGuide->GetType() != CRV_BEZIER)
|
||||
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
|
||||
if( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
|
||||
return nullptr ;
|
||||
nSpanV = pCrvV->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
|
||||
if ( pSect->GetType() != CRV_BEZIER)
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
|
||||
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
|
||||
return nullptr ;
|
||||
int nSpanU = int( pCrvU->GetCurveCount()) ;
|
||||
|
||||
int nDegV = 3 ;
|
||||
if ( bGuideIsPolyLine)
|
||||
nDegV = 1 ;
|
||||
|
||||
int nDegU = 3 ;
|
||||
// superficie swept
|
||||
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
// la guida è una linea spezzata, quindi posso lavorare con gli offset
|
||||
ICRVCOMPOPOVECTOR vCC ;
|
||||
INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ;
|
||||
int nMaxSpanV = nSpanV ;
|
||||
for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
// faccio l'offset della guida nel punto di controllo della sezione
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
vCC.emplace_back() ;
|
||||
vCC.back()->AddCurve(OffsCrv.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvV))
|
||||
return nullptr ;
|
||||
vCC.back()->Translate( ptCtrl.y * frStart.VersY()) ;
|
||||
//mRep[ i * nDegU + j].resize(vCC.back()->GetCurveCount()) ;
|
||||
nMaxSpanV = max ( nMaxSpanV, vCC.back()->GetCurveCount()) ;
|
||||
}
|
||||
}
|
||||
|
||||
// devo capire quante span in V devo creare e a quale span appartengono i tratti degli offset
|
||||
for ( int k = 0 ; k < int( vCC.size()) ; ++k) {
|
||||
const ICurveComposite* pCC = vCC[k] ;
|
||||
mRep[k].resize( nMaxSpanV) ;
|
||||
for ( int z = 0 ; z < int( mRep[k].size()) ; ++z) {
|
||||
int nProp = - 1 ; pCC->GetCurveTempProp( z, nProp) ;
|
||||
if ( nProp == 0) {
|
||||
// ho trovato almeno una curva di offset che ha un tratto non derivante direttamente dalla curva originale
|
||||
// tutte le altre curve che hanno curve di offeset che non hanno questo tratto bonus dovranno ripetere il punto di controllo
|
||||
for ( int w = 0 ; w < int( vCC.size()) ; ++w) {
|
||||
const ICurveComposite* pCCOther = vCC[w] ;
|
||||
int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ;
|
||||
if( nPropCheck != 0)
|
||||
mRep[w][z] = 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// conto in quante colonne di mRep la somma degli elementi è != 0
|
||||
// questo numero va aggiunto all'attuale nSpanV
|
||||
int nSpanPlus = 0 ;
|
||||
for( int z = 0 ; z < nMaxSpanV ; ++z) {
|
||||
int nPosTot = 0 ;
|
||||
for ( int k = 0 ; k < int( mRep.size()) ; ++k )
|
||||
nPosTot += mRep[k][z] ;
|
||||
if( nPosTot != 0)
|
||||
nSpanPlus += 1 ;
|
||||
}
|
||||
nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ;
|
||||
nSpanV = nMaxSpanV ;
|
||||
|
||||
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
|
||||
//// aggiungo i punti di controllo alla superficie
|
||||
//for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO
|
||||
//for( int i = 0 ; i < int( vCC.size()) ; ++i) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
else {
|
||||
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
|
||||
|
||||
// VERSIONE con le copie della sezione ( superficie skinned)
|
||||
|
||||
// creo delle copie della curva e faccio la skinned
|
||||
// per ogni sottocurva della guida ( che sarà composta da curve di bezier di grado 3)
|
||||
// posiziono una copia della curva di sezione per ogni punto di controllo
|
||||
frStart.Set( ptStart, vtStart) ;
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
ICURVEPOVECTOR vCrvSet ;
|
||||
CICURVEPVECTOR vpCrv ;
|
||||
RotationMinimizingFrame rmfGuide ; rmfGuide.Set( pCrvV, frStart) ;
|
||||
//double dStep = 0.25 ;
|
||||
FRAME3DVECTOR vFrame ;
|
||||
int nSpanV = pCrvV->GetCurveCount() ;
|
||||
int nSplit = 8 * nSpanV ;
|
||||
rmfGuide.GetFramesBySplit( nSplit, vFrame) ;
|
||||
|
||||
for ( int i = 0 ; i < nSpanV ; ++i) {
|
||||
for ( int j = i==0 ? 0 : 1 ; j < nSplit + 1 ; ++j) {
|
||||
ICurve* pNewSect = pCrvU->Clone() ;
|
||||
pNewSect->ToGlob( vFrame[j]) ; // da sistemare se ho più curve ( la pGuide è una compo) e in base allo step di divisione!!!!!!!!! ///////
|
||||
vpCrv.push_back( pNewSect) ;
|
||||
vCrvSet.emplace_back( pNewSect) ;
|
||||
}
|
||||
}
|
||||
|
||||
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
|
||||
|
||||
|
||||
|
||||
//////VERSIONE con l'offset dei punti di controllo // richiede l'interpolazione dei punti
|
||||
//
|
||||
//// faccio l'offset della guida e poi riconverto i risultati in curve di bezier tramite interpolazione
|
||||
//
|
||||
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
//// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
//pCrvU->ToLoc( frStart) ;
|
||||
//for( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
// // faccio l'offset della guida nel punto di controllo della sezione
|
||||
// OffsetCurve OffsCrv ;
|
||||
// if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
// pCrvV->AddCurve( OffsCrv.GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvV))
|
||||
// return nullptr ;
|
||||
// pCrvV->Translate( ptCtrl.y * frStart.VersY()) ;
|
||||
// PNTVECTOR vPnt ;
|
||||
// int nOffCrvs = pCrvV->GetCurveCount() ;
|
||||
// for ( int z = 0 ; z < nOffCrvs ; ++z) {
|
||||
// Point3d ptCtrl ;
|
||||
// if ( z == 0) {
|
||||
// pCrvV->GetCurve(z)->GetStartPoint( ptCtrl) ;
|
||||
// vPnt.push_back( ptCtrl) ;
|
||||
// }
|
||||
// pCrvV->GetCurve(z)->GetEndPoint( ptCtrl) ;
|
||||
// vPnt.push_back( ptCtrl) ;
|
||||
// }
|
||||
// pCrvV.Set( CreateCurveComposite()) ;
|
||||
// pCrvV->AddCurve( InterpolatePointSetWithBezier( vPnt, dLinTol)) ;
|
||||
//
|
||||
//
|
||||
// nSpanV = pCrvV->GetCurveCount() ;
|
||||
// pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; /// NON POSSO REINIZIALIZZARE LA SURF QUI!
|
||||
// /// QUANDO INIZIO A INSERIRE I PUNTI DI CONTROLLO DEVO AVER DEFINITO nSpanV
|
||||
//
|
||||
//
|
||||
// // aggiungo i punti di controllo alla superficie
|
||||
// for ( int z = 0 ; z < nSpanV ; ++z) {
|
||||
// const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ;
|
||||
// if( pCrvBez == nullptr)
|
||||
// return nullptr ;
|
||||
// for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) {
|
||||
// Point3d ptCtrl = pCrvBez->GetControlPoint( k) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z * nDegV + k, ptCtrl) ;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////// se richiesti caps e sezione chiusa e guida aperta /// in attesa della SurfCompo, al momento viene fatto nell'executor
|
||||
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// // verifico che le due estremità siano chiuse e piatte
|
||||
|
||||
//}
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSurfBez) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
{
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
bool bRMF = vtAx.IsSmall() ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
Frame3d frStart ;
|
||||
if ( bRMF) {
|
||||
if ( ! frStart.Set( ptStart, vtStart))
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtAxX = vtAx ^ vtStart ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = FromUprightOrtho( vtAx) ;
|
||||
vtAxX.Rotate( vtAx, 0, 1) ;
|
||||
}
|
||||
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
bGuideIsPolyLine = true ;
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
|
||||
const ICurve* pCrv = pCC->GetCurve( i) ;
|
||||
if ( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
}
|
||||
else
|
||||
bGuideIsPolyLine = false ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
}
|
||||
case CRV_LINE :
|
||||
bGuideIsPolyLine = true ;
|
||||
break ;
|
||||
case CRV_BEZIER : {
|
||||
// controllo se i punti di controllo sono allineati
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
break ;
|
||||
}
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
||||
bool bRat = false ;
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( pGuide->GetType() == CRV_LINE)
|
||||
nSpanV = 1 ;
|
||||
else if ( pGuide->GetType() == CRV_COMPO)
|
||||
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
|
||||
}
|
||||
else {
|
||||
// converto in bezier la guida ( grado 3, non razionale)
|
||||
if ( pGuide->GetType() != CRV_BEZIER)
|
||||
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
|
||||
if ( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
|
||||
return nullptr ;
|
||||
nSpanV = pCrvV->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
|
||||
if ( pSect->GetType() != CRV_BEZIER)
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
|
||||
if( ! pSectBez->IsRational())
|
||||
pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
else
|
||||
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
FRAME3DVECTOR vFrames ;
|
||||
if ( bRMF) {
|
||||
RotationMinimizingFrame RMF ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RotationXplaneFrame RXF ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
|
||||
int nSpanU = int( pCrvU->GetCurveCount()) ;
|
||||
int nDegU = 9 ; // debug
|
||||
int nDegV = 3 ;
|
||||
if ( bGuideIsPolyLine){
|
||||
nDegV = 1 ;
|
||||
// superficie swept
|
||||
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
|
||||
pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
|
||||
PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ;
|
||||
pNewSect->ToGlob( vFrames[f]) ;
|
||||
for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
const ICurveBezier* pSubCrvBez = GetCurveBezier( pNewSect->GetCurve( i)) ;
|
||||
for ( int j = 0 ; j < nDegU + 1 ; ++j) {
|
||||
Point3d ptCtrl = pSubCrvBez->GetControlPoint( j) ;
|
||||
pSurfBez->SetControlPoint( i * nDegU + j, f, ptCtrl) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Release( pSurfBez) ;
|
||||
}
|
||||
else {
|
||||
// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
ICURVEPOVECTOR vCrvSet ;
|
||||
CICURVEPVECTOR vpCrv ;
|
||||
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
|
||||
ICurve* pNewSect = pCrvU->Clone() ;
|
||||
// porto la curva nel frame corrente
|
||||
pNewSect->ToGlob( vFrames[f]) ;
|
||||
vpCrv.push_back( pNewSect) ;
|
||||
vCrvSet.emplace_back( pNewSect) ;
|
||||
}
|
||||
|
||||
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
|
||||
}
|
||||
|
||||
//// se richiesti caps e sezione chiusa e guida aperta
|
||||
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
|
||||
// // aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSci->ToGlob( vFrames.front()) ;
|
||||
// // aggiungo
|
||||
// StmFts.AddSurfTriMesh( *pSci) ;
|
||||
|
||||
// // aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSce->ToGlob( vFrames.back()) ;
|
||||
// // inverto
|
||||
// pSce->Invert() ;
|
||||
// // aggiungo
|
||||
// StmFts.AddSurfTriMesh( *pSce) ;
|
||||
//}
|
||||
|
||||
//// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
//double dVol ;
|
||||
//if ( pSTM->GetVolume( dVol) && dVol < 0)
|
||||
// pSTM->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( &ptP == nullptr || pCurve == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, true, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, true, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifico che le curve siano valide
|
||||
for ( int i = 0 ; i < int( vCrv.size()) ; ++i) {
|
||||
if( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// se ho solo due curve allora faccio la rigata
|
||||
if( vCrv.size() == 2)
|
||||
return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ;
|
||||
|
||||
//trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
ICURVEPOVECTOR vCrvBez ;
|
||||
for( int c = 0 ; c < int( vCrv.size()) ; ++c){
|
||||
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
|
||||
if ( vCrv[c]->GetType() != CRV_BEZIER )
|
||||
pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ;
|
||||
else
|
||||
pCC->AddCurve( vCrv[c]->Clone()) ;
|
||||
if ( IsNull( pCC) || ! pCC->IsValid())
|
||||
return nullptr ;
|
||||
vCrvBez.emplace_back( Release( pCC)) ;
|
||||
}
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateBySetOfCurves( vCrvBez, true))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
+34
-1
@@ -17,12 +17,13 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkSbzStandard.h"
|
||||
#include "/EgtDev/Include/EGkSbzFromCurves.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
CreateBezierSphere( const Point3d& ptCenter, double dR)
|
||||
GetSurfBezierSphere( const Point3d& ptCenter, double dR)
|
||||
{
|
||||
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
|
||||
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
|
||||
@@ -78,3 +79,35 @@ CreateBezierSphere( const Point3d& ptCenter, double dR)
|
||||
|
||||
return Release( pSrfBez) ;
|
||||
}
|
||||
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfBezierCone( const Point3d& ptCenter, double dRadius, const Vector3d& dHeight)
|
||||
//{
|
||||
// // le dimensioni devono essere significative
|
||||
// if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
||||
// return nullptr ;
|
||||
// // creo la circonferenza di base
|
||||
// CurveArc cArc ;
|
||||
// cArc.Set( ORIG, Z_AX, dRadius) ;
|
||||
// if ( dHeight < 0)
|
||||
// cArc.Invert() ;
|
||||
// // punto di vertice
|
||||
// Point3d ptTip( 0, 0, dHeight) ;
|
||||
// // creo la superficie laterale del cono
|
||||
// PtrOwner<ISurfBezier> pSbz( GetSurfBezierRuled( ptTip, &cArc)) ;
|
||||
// if ( IsNull( pSbz))
|
||||
// return nullptr ;
|
||||
//
|
||||
// //// creo la superficie di base e la inverto
|
||||
// //PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ;
|
||||
// //if ( IsNull( pSTM1))
|
||||
// // return nullptr ;
|
||||
// //pSTM1->Invert() ;
|
||||
// //// la unisco alla superficie del fianco
|
||||
// //if ( ! pSTM->DoSewing( *pSTM1))
|
||||
// // return nullptr ;
|
||||
//
|
||||
// // restituisco la superficie
|
||||
// return Release( pSbz) ;
|
||||
//}
|
||||
|
||||
+3
-1
@@ -88,6 +88,8 @@ SelfIntersCurve::SelfIntersCurve( const ICurve& Curve)
|
||||
}
|
||||
}
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// per curva approssimata, sistemo...
|
||||
AdjustIntersParams( ( pCalcCrv != m_pCurve), pCalcCrv, vTmpPar) ;
|
||||
@@ -133,7 +135,7 @@ bool
|
||||
SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
|
||||
{
|
||||
// se la curva originale non è stata approssimata o non ci sono auto-intersezioni, non va fatto alcunché
|
||||
if ( ! bAdjCrv || m_Info.size() == 0)
|
||||
if ( ! bAdjCrv || m_Info.empty())
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
for ( auto& aInfo : m_Info) {
|
||||
|
||||
+144
-32
@@ -115,7 +115,8 @@ GetSurfFlatRegionDisk( double dRadius)
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfFlatRegion*
|
||||
GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol)
|
||||
GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol,
|
||||
bool bMergeOnlySameProps)
|
||||
{
|
||||
// metodo di calcolo impostato da USE_VORONOI
|
||||
|
||||
@@ -330,7 +331,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
else {
|
||||
// calcolo la fat curve con Voronoi
|
||||
ICURVEPOVECTOR vFatCurves ;
|
||||
if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids))
|
||||
if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids, bMergeOnlySameProps))
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie a partire dalle curve
|
||||
@@ -367,25 +368,14 @@ GetSurfFlatRegionFromTriangle( const Triangle3d& Tria)
|
||||
ISurfFlatRegion*
|
||||
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
|
||||
{
|
||||
// Creo la regione.
|
||||
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr))
|
||||
return nullptr ;
|
||||
// Creo curva composita.
|
||||
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pLoop))
|
||||
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( ContourPolyLine))
|
||||
return nullptr ;
|
||||
// Creo la regione.
|
||||
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
Point3d ptSt, ptEn ;
|
||||
bool bContinue = ContourPolyLine.GetFirstPoint( ptSt) &&
|
||||
ContourPolyLine.GetNextPoint( ptEn) ;
|
||||
while ( bContinue) {
|
||||
CurveLine cvLine ;
|
||||
cvLine.Set( ptSt, ptEn) ;
|
||||
pLoop->AddCurve( cvLine) ;
|
||||
ptSt = ptEn ;
|
||||
bContinue = ContourPolyLine.GetNextPoint( ptEn) ;
|
||||
}
|
||||
pSfr->AddExtLoop( Release( pLoop)) ;
|
||||
return Release( pSfr) ;
|
||||
}
|
||||
|
||||
@@ -401,25 +391,17 @@ GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
|
||||
for ( int nL = 0 ; nL < int( vContoursPolyLineVec.size()) ; ++ nL) {
|
||||
// Creo curva composita.
|
||||
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pLoop))
|
||||
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( vContoursPolyLineVec[nL]))
|
||||
return nullptr ;
|
||||
Point3d ptSt, ptEn ;
|
||||
bool bContinue = vContoursPolyLineVec[nL].GetFirstPoint( ptSt) &&
|
||||
vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
|
||||
while ( bContinue) {
|
||||
CurveLine cvLine ;
|
||||
cvLine.Set( ptSt, ptEn) ;
|
||||
pLoop->AddCurve( cvLine) ;
|
||||
ptSt = ptEn ;
|
||||
bContinue = vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
|
||||
}
|
||||
// Loop esterno
|
||||
if ( nL == 0) {
|
||||
pSfr->AddExtLoop( Release( pLoop)) ;
|
||||
if ( ! pSfr->AddExtLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
}
|
||||
// Loop interno
|
||||
else {
|
||||
pSfr->AddIntLoop( Release( pLoop)) ;
|
||||
if ( ! pSfr->AddIntLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
return Release( pSfr) ;
|
||||
@@ -590,4 +572,134 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
|
||||
vId.push_back( pCrv->GetTempProp()) ;
|
||||
}
|
||||
return ( ! vId.empty()) ;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool
|
||||
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
|
||||
{
|
||||
// vnPLIndMat : ogni riga corrisponde ad un chunk, in posizione 0 c'è il loop esterno e nelle successive i loop interni
|
||||
// vbInvert : riferito al vettore delle polyline, riporta true se la polyline è stata invertita
|
||||
|
||||
// ricavo versore normale
|
||||
Plane3d plPlane ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
return false ;
|
||||
vtN = plPlane.GetVersN() ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
VCT3DVECTOR vvtN ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
||||
return false ;
|
||||
// salvo la normale
|
||||
vvtN.push_back( plPlane.GetVersN()) ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
// restituisco la normale del loop più grande
|
||||
bool bInvertAll = vvtN[m_vArea[0].first] * vtN < 0 ;
|
||||
vtN = vvtN[m_vArea[0].first] ;
|
||||
|
||||
//// vettore di indici per ordinare le PolyLine
|
||||
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
|
||||
vPL_IndOrder[i] = m_vArea[i].first ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
vbInvert.resize( vPL.size()) ;
|
||||
fill( vbInvert.begin(), vbInvert.end(), false) ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
vbInvert[j] = true ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vCrvCompo[j]->Invert() ;
|
||||
vbInvert[j] = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
if ( bInvertAll) {
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
|
||||
vbInvert[i] = ! vbInvert[i] ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+433
-239
@@ -31,10 +31,6 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
|
||||
POLYLINEVECTOR& vPL, Vector3d& vtN) ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol)
|
||||
@@ -65,12 +61,25 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
return nullptr ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
if( vbInvert[vnPLIndMat[i][j]])
|
||||
vPL[vnPLIndMat[i][j]].Invert() ;
|
||||
}
|
||||
}
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// salvo tolleranza lineare usata
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
@@ -145,9 +154,20 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
|
||||
if( vbInvert[i])
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
// verifico la direzione di estrusione
|
||||
double dOrthoExtr = vtN * vtExtr ;
|
||||
if ( ( abs( dOrthoExtr) < EPS_SMALL))
|
||||
@@ -159,7 +179,8 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
}
|
||||
// creo la prima superficie di estremità
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
|
||||
// alla funzione CreateByRegion passo anche la matrice che contiene la struttura dei chunk. Le polyline hanno già il verso giusto
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// creo la seconda superficie e la unisco alla prima
|
||||
{ // copio la prima superficie
|
||||
@@ -330,9 +351,11 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
|
||||
{
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ;
|
||||
if ( vtNorm.IsSmall())
|
||||
vtNorm = Z_AX ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// curve di offset
|
||||
@@ -355,7 +378,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
|
||||
PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
|
||||
if ( IsNull( pSrfBot))
|
||||
return nullptr ;
|
||||
pSrfBot->Translate( -dDimV * vtNorm) ;
|
||||
pSrfBot->Translate( - dDimV * vtNorm) ;
|
||||
pSrfBot->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ;
|
||||
if ( IsNull( pSrfRgt))
|
||||
@@ -365,74 +388,188 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
|
||||
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) ;
|
||||
int nBuckets = max( 2 * ( pSrfRgt->GetVertexSize() + pSrfLft->GetVertexSize()), 1000) ;
|
||||
StmFromTriangleSoup stmSoup ;
|
||||
if ( ! stmSoup.Start( nBuckets))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pSrfTop) ;
|
||||
stmSoup.AddSurfTriMesh( *pSrfRgt) ;
|
||||
stmSoup.AddSurfTriMesh( *pSrfLft) ;
|
||||
stmSoup.AddSurfTriMesh( *pSrfBot) ;
|
||||
PtrOwner<ISurfTriMesh> pSTM ;
|
||||
// se guida aperta e tappi piatti
|
||||
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
|
||||
// completo unione e recupero la superficie risultante
|
||||
if ( ! stmSoup.End())
|
||||
return nullptr ;
|
||||
pSTM.Set( stmSoup.GetSurf()) ;
|
||||
// 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))
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// aggiungo il cap sull'inizio
|
||||
// calcolo il cap sull'inizio
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
// calcolo il cap sulla fine
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
// cucio i tappi all'estrusione
|
||||
if ( ! pSTM->DoSewing( *pSci) || ! pSTM->DoSewing( *pSce))
|
||||
return nullptr ;
|
||||
}
|
||||
// se altrimenti guida aperta e tappi arrotondati
|
||||
if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
|
||||
// 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<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
// se l'offset interno alla guida è chiuso
|
||||
if ( pCrvL->IsClosed()) {
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ;
|
||||
Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ;
|
||||
Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ;
|
||||
Point3d ptCenter = Media( ptRight, ptLeft) ;
|
||||
Vector3d vtRight = ptRight - ptCenter ;
|
||||
Vector3d vtLeft = ptLeft - ptCenter ;
|
||||
double dAng = ANG_STRAIGHT ;
|
||||
vtRight.GetAngle( vtLeft, dAng) ;
|
||||
vtRight.Normalize() ;
|
||||
PolyLine plLoop ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptRight) ; // primo punto
|
||||
double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptRight ;
|
||||
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso
|
||||
plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa
|
||||
// superificie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop) ;
|
||||
// superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom( CloneSurfTriMesh( pStmTop)) ;
|
||||
pStmBottom->Translate( - dDimV * vtNorm) ;
|
||||
pStmBottom->Invert() ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom) ;
|
||||
// superificie perpendicolare
|
||||
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset
|
||||
PtrOwner<ISurfTriMesh> pStmPerp( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp) || ! pStmPerp->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
|
||||
! pStmPerp->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp) ;
|
||||
}
|
||||
// se l'offset interno della guida è aperto...
|
||||
else {
|
||||
// aggiungo il cap sull'inizio
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ;
|
||||
Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ;
|
||||
Vector3d vtLeft = ptSLeft - ptStart ;
|
||||
Vector3d vtRight = ptSRight - ptStart ;
|
||||
double dAng = ANG_STRAIGHT ;
|
||||
vtLeft.GetAngle( vtRight, dAng) ;
|
||||
vtLeft.Normalize() ;
|
||||
PolyLine plLoop ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptSLeft) ; // primo punto
|
||||
double dAngStep = ceil( dAng / dStepRotDeg) ;
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSLeft ;
|
||||
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa
|
||||
// creo la superficie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop_start) ;
|
||||
// superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ;
|
||||
pStmBottom_start->Translate( - dDimV * vtNorm) ;
|
||||
pStmBottom_start->Invert() ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom_start) ;
|
||||
// superificie perpendicolare
|
||||
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
PtrOwner<ISurfTriMesh> pStmPerp_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp_start) || ! pStmPerp_start->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
|
||||
! pStmPerp_start->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp_start) ;
|
||||
// aggiungo il cap sulla fine
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
pCrvL->GetEndPoint( ptSLeft) ;
|
||||
pCrvR->GetEndPoint( ptSRight) ;
|
||||
vtLeft = ptSLeft - ptEnd ;
|
||||
vtRight = ptSRight - ptEnd ;
|
||||
dAng = ANG_STRAIGHT ;
|
||||
vtRight.GetAngle( vtLeft, dAng) ;
|
||||
vtRight.Normalize() ;
|
||||
plLoop.Clear() ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptSRight) ;
|
||||
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSRight ;
|
||||
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa
|
||||
// creo la superficie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop_end) ;
|
||||
// creo la superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom_end( CloneSurfTriMesh( pStmTop_end)) ;
|
||||
pStmBottom_end->Translate( - dDimV * vtNorm) ;
|
||||
pStmBottom_end->Invert() ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom_end) ;
|
||||
// creo la superificie perpendicolare alla guida
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
PtrOwner<ISurfTriMesh> pStmPerp_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp_end) || ! pStmPerp_end->CreateByExtrusion( plLoop, - vtNorm * dDimV) ||
|
||||
! pStmPerp_end->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp_end) ;
|
||||
}
|
||||
// completo unione e recupero la superficie risultante
|
||||
if ( ! stmSoup.End())
|
||||
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<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
pSTM.Set( stmSoup.GetSurf()) ;
|
||||
}
|
||||
else {
|
||||
// completo unione e recupero la superficie risultante
|
||||
if ( ! stmSoup.End())
|
||||
return nullptr ;
|
||||
pSTM.Set( stmSoup.GetSurf()) ;
|
||||
}
|
||||
// salvo tolleranza lineare usata e imposto angolo per smooth
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
pSTM->SetSmoothAngle( 20) ;
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
@@ -445,13 +582,13 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// assegno la normale del piano
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ;
|
||||
if ( vtNorm.IsSmall())
|
||||
vtNorm = Z_AX ;
|
||||
// determino il punto centrale della sezione
|
||||
Point3d ptCen ;
|
||||
pGuide->GetStartPoint( ptCen) ;
|
||||
Point3d ptCen ; pGuide->GetStartPoint( ptCen) ;
|
||||
ptCen -= dDimV / 2 * vtNorm ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
@@ -480,7 +617,6 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
|
||||
bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
|
||||
}
|
||||
|
||||
if ( ! bOk ||
|
||||
vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 ||
|
||||
vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0)
|
||||
@@ -549,10 +685,6 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
if ( ! stmSoup.End())
|
||||
return nullptr ;
|
||||
pSTM.Set( stmSoup.GetSurf()) ;
|
||||
// preparo seconda zuppa di triangoli per inserire i tappi
|
||||
StmFromTriangleSoup stmCapSoup ;
|
||||
if ( ! stmCapSoup.Start( nBuckets))
|
||||
return nullptr ;
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
@@ -580,42 +712,236 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
|
||||
// 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<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
// se l'offset interno della guida è chiuso...
|
||||
if ( pCrvL->IsClosed()) {
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ;
|
||||
Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ;
|
||||
Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ;
|
||||
Point3d ptCenter = Media( ptRight, ptLeft) ;
|
||||
Vector3d vtRight = ptRight - ptCenter ;
|
||||
Vector3d vtLeft = ptLeft - ptCenter ;
|
||||
double dAng = ANG_STRAIGHT ;
|
||||
vtRight.GetAngle( vtLeft, dAng) ;
|
||||
vtRight.Normalize() ;
|
||||
PolyLine plLoop ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptRight) ; // primo punto
|
||||
double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptRight ;
|
||||
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso
|
||||
plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa
|
||||
// superificie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop) ;
|
||||
// superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom( CloneSurfTriMesh( pStmTop)) ;
|
||||
if ( IsNull( pStmBottom) || ! pStmBottom->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom) ;
|
||||
// calcolo l'angolo di rotazione per la faccia Top del bevel
|
||||
// NB. Questo angolo va ricalcolato, il bevel è inclinato rispetto alla normale della guida
|
||||
ptCenter.Translate( - dBevelV * vtNorm) ;
|
||||
Point3d ptbRight ; pCrvRb->GetEndPoint( ptbRight) ;
|
||||
Point3d ptbLeft ; pCrvRb->GetStartPoint( ptbLeft) ;
|
||||
Vector3d vtbLeft = ptbLeft - ptCenter ;
|
||||
Vector3d vtbRight = ptbRight - ptCenter ;
|
||||
dAng = ANG_STRAIGHT ;
|
||||
vtbRight.GetAngle( vtbLeft, dAng) ;
|
||||
vtbRight.Normalize() ;
|
||||
// la PolyLine che utilizzo la posso ricavare da quella calcolata sopra
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset
|
||||
// creo il loop defininendo i punti
|
||||
PolyLine plLoopB ;
|
||||
plLoopB.AddUPoint( 0, ptbRight) ;
|
||||
dAngStep = ceil( dAng / dStepRotDeg) ;
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptbRight ;
|
||||
ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoopB.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoopB.AddUPoint( dAngStep, ptbLeft) ;
|
||||
// creo la superficie Top Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbTop_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmbTop_start) ||
|
||||
! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmbTop_start->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbTop_start) ;
|
||||
// creo la superificie Bottom Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ;
|
||||
if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbBottom_start) ;
|
||||
// creo la superficie perpendicolare alla guida
|
||||
PolyLine plLoopB1 = plLoopB ;
|
||||
plLoopB1.Mirror( ptCen, vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pStmPerp( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp) ||
|
||||
! pStmPerp->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmPerp->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp) ;
|
||||
}
|
||||
// se l'offset interno della guida è aperto...
|
||||
else {
|
||||
// aggiungo il cap sull'inizio
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ;
|
||||
Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ;
|
||||
Vector3d vtLeft = ptSLeft - ptStart ;
|
||||
Vector3d vtRight = ptSRight - ptStart ;
|
||||
double dAng = ANG_STRAIGHT ;
|
||||
vtLeft.GetAngle( vtRight, dAng) ;
|
||||
vtLeft.Normalize() ;
|
||||
PolyLine plLoop ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptSLeft) ; // primo punto
|
||||
double dAngStep = ceil( dAng / dStepRotDeg) ;
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSLeft ;
|
||||
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa
|
||||
// creo la superficie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop_start) ;
|
||||
// creo la superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ;
|
||||
if ( IsNull( pStmBottom_start) || ! pStmBottom_start->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom_start) ;
|
||||
// calcolo l'angolo di rotazione per la faccia Top del bevel
|
||||
ptStart.Translate( - dBevelV * vtNorm) ;
|
||||
Point3d ptSbLeft ; pCrvLb->GetStartPoint( ptSbLeft) ;
|
||||
Point3d ptSbRight ; pCrvRb->GetStartPoint( ptSbRight) ;
|
||||
Vector3d vtbLeft = ptSbLeft - ptStart ;
|
||||
Vector3d vtbRight = ptSbRight - ptStart ;
|
||||
dAng = ANG_STRAIGHT ;
|
||||
vtbLeft.GetAngle( vtbRight, dAng) ;
|
||||
vtbLeft.Normalize() ;
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
// creo il loop defininendo i punti
|
||||
PolyLine plLoopB ;
|
||||
plLoopB.AddUPoint( 0, ptSbLeft) ;
|
||||
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSbLeft ;
|
||||
ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoopB.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoopB.AddUPoint( dAngStep, ptSbRight) ; // ultimo punto
|
||||
// creo la superficie Top Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbTop_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmbTop_start) ||
|
||||
! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmbTop_start->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbTop_start) ;
|
||||
// creo la superificie Bottom Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ;
|
||||
if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbBottom_start) ;
|
||||
// creo la superficie perpendicolare alla guida
|
||||
PolyLine plLoopB1 = plLoopB ;
|
||||
plLoopB1.Mirror( ptCen, vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pStmPerp_start( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp_start) ||
|
||||
! pStmPerp_start->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmPerp_start->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp_start) ;
|
||||
// aggiungo il cap sulla fine
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
// calcolo l'angolo di rotazione per screwing faccia Top e Bottom
|
||||
pCrvL->GetEndPoint( ptSLeft) ;
|
||||
pCrvR->GetEndPoint( ptSRight) ;
|
||||
vtLeft = ptSLeft - ptEnd ;
|
||||
vtRight = ptSRight - ptEnd ;
|
||||
dAng = ANG_STRAIGHT ;
|
||||
vtRight.GetAngle( vtLeft, dAng) ;
|
||||
vtRight.Normalize() ;
|
||||
plLoop.Clear() ;
|
||||
// creo il loop defininendo i punti
|
||||
plLoop.AddUPoint( 0, ptSRight) ;
|
||||
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSRight ;
|
||||
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoop.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto
|
||||
plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa
|
||||
// creo la superficie Top
|
||||
PtrOwner<ISurfTriMesh> pStmTop_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmTop_end) ;
|
||||
// creo la superificie Bottom
|
||||
PtrOwner<ISurfTriMesh> pStmBottom_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmBottom_end) ||
|
||||
! pStmBottom_end->CopyFrom( pStmTop_end) ||
|
||||
! pStmBottom_end->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmBottom_end) ;
|
||||
// calcolo l'angolo di rotazione per la faccia Top del bevel
|
||||
ptEnd.Translate( - dBevelV * vtNorm) ;
|
||||
pCrvLb->GetEndPoint( ptSbLeft) ;
|
||||
pCrvRb->GetEndPoint( ptSbRight) ;
|
||||
vtbLeft = ptSbLeft - ptEnd ;
|
||||
vtbRight = ptSbRight - ptEnd ;
|
||||
dAng = ANG_STRAIGHT ;
|
||||
vtbRight.GetAngle( vtbLeft, dAng) ;
|
||||
vtbRight.Normalize() ;
|
||||
plLoop.EraseLastUPoint() ; // apro il loop
|
||||
// creo il loop defininendo i punti
|
||||
plLoopB.Clear() ;
|
||||
plLoopB.AddUPoint( 0, ptSbRight) ;
|
||||
dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto
|
||||
for ( int i = 1 ; i < dAngStep ; ++ i) {
|
||||
Point3d ptRot = ptSbRight ;
|
||||
ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ;
|
||||
plLoopB.AddUPoint( i, ptRot) ;
|
||||
}
|
||||
plLoopB.AddUPoint( dAngStep, ptSbLeft) ; // ultimo punto
|
||||
// creo la superficie Top Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbTop_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmbTop_end) ||
|
||||
! pStmbTop_end->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmbTop_end->Invert())
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbTop_end) ;
|
||||
// creo la superificie Bottom Bevel
|
||||
PtrOwner<ISurfTriMesh> pStmbBottom_end( CloneSurfTriMesh( pStmbTop_end)) ;
|
||||
if ( IsNull( pStmbBottom_end) || ! pStmbBottom_end->Mirror( ptCen, vtNorm))
|
||||
return nullptr ;
|
||||
stmSoup.AddSurfTriMesh( *pStmbBottom_end) ;
|
||||
// creo la superficie perpendicolare alla guida
|
||||
plLoopB1 = plLoopB ;
|
||||
plLoopB1.Mirror( ptCen, vtNorm) ;
|
||||
PtrOwner<ISurfTriMesh> pStmPerp_end( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmPerp_end) ||
|
||||
! pStmPerp_end->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) ||
|
||||
! pStmPerp_end->Invert())
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
stmSoup.AddSurfTriMesh( *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<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
stmSoup.AddSurfTriMesh( *pSce) ;
|
||||
stmSoup.AddSurfTriMesh( *pStmPerp_end) ;
|
||||
}
|
||||
// completo unione e recupero la superficie risultante
|
||||
if ( ! stmSoup.End())
|
||||
return nullptr ;
|
||||
@@ -634,6 +960,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol)
|
||||
@@ -973,8 +1300,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
|
||||
}
|
||||
}
|
||||
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( ! pSci->CreateByRegion( vPLi))
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
|
||||
return nullptr ;
|
||||
pStmSwept->DoSewing( *pSci) ;
|
||||
// recupero i loops alla fine
|
||||
@@ -982,8 +1310,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
|
||||
if ( ! pStmSwept->GetLoops( vPLe))
|
||||
return nullptr ;
|
||||
// creo la superficie alla fine e la attacco
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( ! pSce->CreateByRegion( vPLe))
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
vnPLIndMat.clear() ;
|
||||
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// attacco la superficie finale alla swept
|
||||
pSce->Invert() ;
|
||||
@@ -1127,138 +1456,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool
|
||||
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
|
||||
POLYLINEVECTOR& vPL, Vector3d& vtN)
|
||||
{
|
||||
// se non ho curve, non faccio nulla
|
||||
if ( int( vpCurve.size()) == 0)
|
||||
return true ;
|
||||
|
||||
// calcolo le polilinee che approssimano le curve
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// ricavo versore normale
|
||||
Plane3d plPlane ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
return false ;
|
||||
vtN = plPlane.GetVersN() ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
||||
return false ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
|
||||
// successive i loop interni
|
||||
INTMATRIX vnPLIndMat ;
|
||||
|
||||
// vettore di indici per ordinare le PolyLine
|
||||
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
|
||||
vPL_IndOrder[i] = m_vArea[i].first ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
// ordino le PolyLine per area
|
||||
POLYLINEVECTOR vPL_tmp ;
|
||||
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
|
||||
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
|
||||
swap( vPL, vPL_tmp) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+123
-6
@@ -22,6 +22,18 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshEmpty( void)
|
||||
{
|
||||
// creo oggetto con superficie vuota
|
||||
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStm) || ! pStm->AdjustTopology())
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pStm) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static SurfTriMesh*
|
||||
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
||||
@@ -160,15 +172,15 @@ GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight)
|
||||
return nullptr ;
|
||||
// creo la polilinea del contorno della base
|
||||
PolyLine PL ;
|
||||
PL.AddUPoint( 0, ORIG) ;
|
||||
PL.AddUPoint( 1, Point3d( dDimX, 0, 0)) ;
|
||||
PL.AddUPoint( 2, Point3d( dDimX, dDimY, 0)) ;
|
||||
PL.AddUPoint( 3, Point3d( 0, dDimY, 0)) ;
|
||||
PL.AddUPoint( 4, ORIG) ;
|
||||
PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||
if ( dHeight < 0)
|
||||
PL.Invert() ;
|
||||
// punto di vertice
|
||||
Point3d ptTip( 0.5 * dDimX, 0.5 * dDimY, dHeight) ;
|
||||
Point3d ptTip( 0, 0, dHeight) ;
|
||||
// creo e setto la superficie trimesh laterale
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
|
||||
@@ -245,6 +257,111 @@ GetSurfTriMeshSphere( double dRadius, double dLinTol)
|
||||
return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, dLinTol) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshPyramidFrustum( double dBaseDimX, double dBaseDimY, double dTopDimX, double dTopDimY, double dHeight)
|
||||
{
|
||||
// le dimensioni devono essere significative
|
||||
if ( ( min( dBaseDimX, dBaseDimY) < EPS_SMALL && min( dTopDimX, dTopDimY) < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
||||
return nullptr ;
|
||||
// se piramide
|
||||
if ( min( dTopDimX, dTopDimY) < EPS_SMALL)
|
||||
return GetSurfTriMeshPyramid( dBaseDimX, dBaseDimY, dHeight) ;
|
||||
// se piramide inversa
|
||||
if ( min( dBaseDimX, dBaseDimY) < EPS_SMALL)
|
||||
return GetSurfTriMeshPyramid( dTopDimX, dTopDimY, -dHeight) ;
|
||||
// se parallelepipedo
|
||||
// continuo qui per avere l'origine in centro e non sullo spigolo in basso a sinistra
|
||||
// creo la polilinea del contorno della base
|
||||
PolyLine PL1 ;
|
||||
PL1.AddUPoint( 0, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 1, Point3d( dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 2, Point3d( dBaseDimX / 2 , dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 3, Point3d( -dBaseDimX / 2, dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 4, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
if ( dHeight < 0)
|
||||
PL1.Invert() ;
|
||||
// creo la polilinea del contorno di sopra
|
||||
PolyLine PL2 ;
|
||||
PL2.AddUPoint( 0, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 1, Point3d( dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 2, Point3d( dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 3, Point3d( -dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 4, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
if ( dHeight < 0)
|
||||
PL2.Invert() ;
|
||||
// creo e setto la superficie trimesh laterale
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH))
|
||||
return nullptr ;
|
||||
// creo la superficie di base e ne inverto la normale
|
||||
SurfTriMesh STM1 ;
|
||||
if ( ! STM1.CreateByFlatContour( PL1))
|
||||
return nullptr ;
|
||||
STM1.Invert() ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( STM1))
|
||||
return nullptr ;
|
||||
// creo la superficie sopra
|
||||
SurfTriMesh STM2 ;
|
||||
if ( ! STM2.CreateByFlatContour( PL2))
|
||||
return nullptr ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( STM2))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshConeFrustum( double dBaseRad, double dTopRad, double dHeight, double dLinTol)
|
||||
{
|
||||
// le dimensioni devono essere significative
|
||||
if ( ( dBaseRad < EPS_SMALL && dTopRad < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
||||
return nullptr ;
|
||||
// se cono
|
||||
if ( dTopRad < EPS_SMALL)
|
||||
return GetSurfTriMeshCone( dBaseRad, dHeight, dLinTol) ;
|
||||
// se cono rovescio
|
||||
if ( dBaseRad < EPS_SMALL)
|
||||
return GetSurfTriMeshCone( dTopRad, -dHeight, dLinTol) ;
|
||||
// se cilindro
|
||||
if ( abs( dTopRad - dBaseRad) < EPS_SMALL)
|
||||
return GetSurfTriMeshCylinder( dBaseRad, dHeight, dLinTol) ;
|
||||
// creo la circonferenza sotto
|
||||
CurveArc cArc1 ;
|
||||
cArc1.Set( ORIG, Z_AX, dBaseRad) ;
|
||||
if ( dHeight < 0)
|
||||
cArc1.Invert() ;
|
||||
// creo la circonferenza sopra
|
||||
CurveArc cArc2 ;
|
||||
cArc2.Set( Point3d( 0, 0, dHeight), Z_AX, dTopRad) ;
|
||||
if ( dHeight < 0)
|
||||
cArc2.Invert() ;
|
||||
// creo la superficie laterale del cono
|
||||
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
// creo la superficie sotto e la inverto
|
||||
PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc1, dLinTol)) ;
|
||||
if ( IsNull( pSTM1))
|
||||
return nullptr ;
|
||||
pSTM1->Invert() ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( *pSTM1))
|
||||
return nullptr ;
|
||||
// creo la superficie sopra
|
||||
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMeshByFlatContour( &cArc2, dLinTol)) ;
|
||||
if ( IsNull( pSTM2))
|
||||
return nullptr ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( *pSTM2))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
|
||||
|
||||
+41
-12
@@ -45,6 +45,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
for( int j = 0 ; j < snData.nCPV ; ++j) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
nuCurve.nDeg = snData.nDegU ;
|
||||
nuCurve.vU = vU ;
|
||||
// vettore dei punti di controllo
|
||||
@@ -62,13 +63,24 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vCP = vPtCtrl ;
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
NurbsCurveCanonicalize( nuCurve) ;
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
|
||||
if ( snData.mCP.size() != nuCurve.vCP.size() ) {
|
||||
snData.mCP.resize( nuCurve.vCP.size()) ;
|
||||
if( snData.bRat)
|
||||
snData.mW.resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
if( snData.bRat) {
|
||||
snData.mW[i][j] = nuCurve.vW[i] ;
|
||||
snData.mCP[i][j] *= nuCurve.vW[i] ;
|
||||
}
|
||||
}
|
||||
snData.vU = nuCurve.vU ;
|
||||
}
|
||||
snData.vU = nuCurve.vU ;
|
||||
}
|
||||
snData.bPeriodicU = false ;
|
||||
snData.nCPU = int( snData.mCP.size()) ;
|
||||
}
|
||||
if ( snData.bPeriodicV || ! snData.bClampedV) {
|
||||
bool bIsRational = snData.bRat ;
|
||||
@@ -82,6 +94,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
for( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
nuCurve.nDeg = snData.nDegV ;
|
||||
nuCurve.vU = vV ;
|
||||
// vettore dei punti di controllo
|
||||
@@ -99,15 +112,29 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vCP = vPtCtrl ;
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
NurbsCurveCanonicalize( nuCurve) ;
|
||||
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[j] ;
|
||||
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
|
||||
if ( snData.mCP[i].size() != nuCurve.vCP.size()){
|
||||
snData.mCP[i].clear() ;
|
||||
snData.mCP[i].resize( nuCurve.vCP.size()) ;
|
||||
if ( snData.bRat ) {
|
||||
snData.mW[i].clear() ;
|
||||
snData.mW[i].resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
}
|
||||
for ( int j = 0 ; j < int( nuCurve.vCP.size()) ; ++j ) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[j] ;
|
||||
if ( snData.bRat ) {
|
||||
snData.mW[i][j] = nuCurve.vW[j] ;
|
||||
snData.mCP[i][j] *= nuCurve.vW[j] ;
|
||||
}
|
||||
}
|
||||
snData.vV = nuCurve.vU ;
|
||||
}
|
||||
snData.vV = nuCurve.vU ;
|
||||
}
|
||||
snData.bPeriodicV = false ;
|
||||
snData.nCPV = int( snData.mCP[0].size()) ;
|
||||
}
|
||||
return true;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -604,7 +631,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
pSfr_copy->Translate( vtJoin) ;
|
||||
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
|
||||
if ( bRetry)
|
||||
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_FILLET) ; // OFFSET
|
||||
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
|
||||
if ( pRescaledSfr->IsValid()) {
|
||||
if ( ! pRescaledSfr->Add( *pSfr_copy))
|
||||
return false ;
|
||||
@@ -617,7 +644,8 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
|
||||
if ( pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_FILLET) ; //contro OFFSET
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
}
|
||||
}
|
||||
@@ -628,7 +656,8 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
|
||||
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_FILLET) ; // contro OFFSET
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
}
|
||||
|
||||
|
||||
+2714
-512
File diff suppressed because it is too large
Load Diff
+68
-34
@@ -22,9 +22,16 @@
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
using namespace std ;
|
||||
class Tree ;
|
||||
|
||||
struct PairHashIntInt {
|
||||
std::size_t operator()(const std::pair<int, int>& key) const {
|
||||
std::size_t h1 = std::hash<int>{}(key.first);
|
||||
std::size_t h2 = std::hash<int>{}(key.second);
|
||||
return h1 ^ (h2 << 1); // Combine hashes
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
{
|
||||
@@ -69,13 +76,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
public : // ISurf
|
||||
bool IsSimple( void) const override
|
||||
{ return true ; }
|
||||
bool IsClosed( void) const override
|
||||
{ return false ; }
|
||||
bool IsClosed( void) const override ;
|
||||
bool GetArea( double& dArea) const override ;
|
||||
bool GetVolume( double& dVolume) const override
|
||||
{ if ( &dVolume == nullptr)
|
||||
return false ;
|
||||
if ( m_pSTM == nullptr)
|
||||
GetAuxSurf() ;
|
||||
dVolume = 0 ;
|
||||
if ( m_pSTM != nullptr)
|
||||
m_pSTM->GetVolume( dVolume) ;
|
||||
return true ; }
|
||||
bool GetCentroid( Point3d& ptCen) const override ;
|
||||
bool Invert( void) override ;
|
||||
@@ -99,6 +109,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
{ return GetControlWeight( GetInd( nIndU, nIndV), pbOk) ; }
|
||||
double GetControlWeight( int nInd, bool* pbOk) const override ;
|
||||
bool IsAPoint( void) const override ;
|
||||
bool GetPoint( double dU, double dV, Side nUs, Side nVs, Point3d& ptPos) const override ;
|
||||
bool GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
|
||||
Point3d& ptPos,
|
||||
Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr,
|
||||
@@ -109,35 +120,43 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ;
|
||||
CurveComposite* GetCurveOnU( double dV) const override ;
|
||||
CurveComposite* GetCurveOnV( double dU) const override ;
|
||||
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
|
||||
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
|
||||
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
|
||||
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
const SurfTriMesh* GetAuxSurfRefined( void) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL) const override ;
|
||||
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
|
||||
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
|
||||
// a nIL si può passare 5 come valore di default
|
||||
// a nIL si può passare 5 come valore di default
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
|
||||
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
|
||||
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
|
||||
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
|
||||
bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ;
|
||||
// funzione che calcola se gli edge sono collassati in poli. DEVE ESSERE STATA CHIAMATA PRIMA DI UN CUT
|
||||
bool CalcPoles( void) override ;
|
||||
// funzioni per incrementare le coordinate restando dentro lo spazio parametrico
|
||||
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
|
||||
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
|
||||
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
|
||||
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
|
||||
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; // se la superficie non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
|
||||
bool IsPlanar( void) const override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
|
||||
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
|
||||
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
|
||||
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
|
||||
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -149,7 +168,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
|
||||
public :
|
||||
SurfBezier( void) ;
|
||||
SurfBezier( const SurfBezier& sbSrc)
|
||||
SurfBezier( const SurfBezier& sbSrc) : m_pSTM( nullptr), m_pSTMRefined( nullptr), m_pTrimReg(nullptr)
|
||||
{ if ( ! CopyFrom( sbSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "SurfBezier : copy constructor error") }
|
||||
SurfBezier& operator =( const SurfBezier& sbSrc)
|
||||
@@ -160,7 +179,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum ParDir { ON_U = 1, ON_V = 2} ;
|
||||
static const int MAXDEG = 11 ;
|
||||
static const int MAXDEG = 21 ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const SurfBezier& sbSrc) ;
|
||||
@@ -190,30 +209,45 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
double GetCurveOnVApproxLen( double dU) const ;
|
||||
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
|
||||
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
|
||||
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||
bool UpdateEdgesFromTree( Tree& tr) const ;
|
||||
// funzione che calcola se gli edge sono collassati in poli
|
||||
bool CalcPoles( void) const ;
|
||||
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
|
||||
bool ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
|
||||
bool ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
|
||||
bool GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria
|
||||
Status m_nStatus ; // stato
|
||||
int m_nDegU ; // grado in U
|
||||
int m_nDegV ; // grado in V
|
||||
int m_nSpanU ; // numero di pezze in U
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria per la visualizzazione
|
||||
mutable SurfTriMesh* m_pSTMRefined ; // superficie trimesh ausiliaria raffinata per i calcoli
|
||||
Status m_nStatus ; // stato
|
||||
int m_nDegU ; // grado in U
|
||||
int m_nDegV ; // grado in V
|
||||
int m_nSpanU ; // numero di pezze in U
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable std::vector<ICRVCOMPOPOVECTOR> m_mCCEdge ; // vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
|
||||
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
|
||||
mutable DBLVECTOR m_vBernU ;
|
||||
mutable PNTVECTOR m_ptTemp ;
|
||||
mutable DBLVECTOR m_vBernV ;
|
||||
mutable PNTVECTOR m_ptTempW ;
|
||||
mutable DBLVECTOR m_dTempW ;
|
||||
mutable PNTVECTOR m_vPtWCtrlLoc ;
|
||||
mutable DBLVECTOR m_vWeCtrlLoc ;
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+298
-28
@@ -109,18 +109,25 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
||||
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
||||
return false ;
|
||||
// aggiungo le singole curve
|
||||
int nExtAdded = 0 ;
|
||||
bool bOk = true ;
|
||||
for ( auto& pSingCrv : CrvLst) {
|
||||
if ( ! AddSimpleExtLoop( pSingCrv))
|
||||
bool bAdded = false ;
|
||||
if ( AddSimpleExtLoop( pSingCrv, bAdded))
|
||||
++ nExtAdded ;
|
||||
else
|
||||
bOk = false ;
|
||||
|
||||
}
|
||||
return bOk ;
|
||||
return ( bOk && nExtAdded > 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
{
|
||||
// default
|
||||
bAdded = false ;
|
||||
// acquisisco la curva
|
||||
PtrOwner<ICurve> pMyCrv( pCrv) ;
|
||||
if ( IsNull( pMyCrv))
|
||||
@@ -133,8 +140,10 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
Plane3d plPlane ;
|
||||
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
||||
return false ;
|
||||
if ( dArea < SQ_EPS_SMALL)
|
||||
return true ;
|
||||
// se sto costruendo il primo chunk
|
||||
if ( m_vExtInd.size() == 0) {
|
||||
if ( m_vExtInd.empty()) {
|
||||
// assegno il riferimento intrinseco
|
||||
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
|
||||
return false ;
|
||||
@@ -198,6 +207,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
bAdded = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -547,7 +557,7 @@ SurfFlatRegion::Load( NgeReader& ngeIn)
|
||||
string sName ;
|
||||
int j ;
|
||||
bool bOk = ngeIn.ReadString( sName, ";") &&
|
||||
FromString( sName.substr(2), j) && i == j ;
|
||||
FromString( sName.substr( 2), j) && i == j ;
|
||||
int nChunk = 0, nLoop = 0 ;
|
||||
bOk = ngeIn.ReadInt( nChunk, ",") &&
|
||||
ngeIn.ReadInt( nLoop, ";", true) ;
|
||||
@@ -912,9 +922,6 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
bool
|
||||
SurfFlatRegion::GetArea( double& dArea) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// inizio con area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
@@ -937,9 +944,6 @@ SurfFlatRegion::GetArea( double& dArea) const
|
||||
bool
|
||||
SurfFlatRegion::GetGrossArea( double& dArea) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// inizio con area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
@@ -963,9 +967,6 @@ SurfFlatRegion::GetGrossArea( double& dArea) const
|
||||
bool
|
||||
SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &ptCen == nullptr)
|
||||
return false ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
@@ -991,13 +992,20 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetChunkCount( void) const
|
||||
{
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return 0 ;
|
||||
return int( m_vExtInd.size()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &ptCen == nullptr)
|
||||
return false ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
@@ -1011,13 +1019,53 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetChunkCount( void) const
|
||||
bool
|
||||
SurfFlatRegion::GetChunkArea( int nChunk, double& dArea) const
|
||||
{
|
||||
// default, area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return 0 ;
|
||||
return int( m_vExtInd.size()) ;
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// calcolo l'area
|
||||
bool bOk = true ;
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
||||
double dLoopArea ;
|
||||
if ( pLoop != nullptr && pLoop->GetAreaXY( dLoopArea))
|
||||
dArea += dLoopArea ;
|
||||
else
|
||||
bOk = false ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkPerimeter( int nChunk, double& dLen) const
|
||||
{
|
||||
// default, perimetro nullo
|
||||
dLen = 0 ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// calcolo il perimetro
|
||||
bool bOk = true ;
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
||||
double dLoopLen ;
|
||||
if ( pLoop != nullptr && pLoop->GetLength( dLoopLen))
|
||||
dLen += dLoopLen ;
|
||||
else
|
||||
bOk = false ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1118,6 +1166,19 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetLoopCurveCount( int nChunk, int nLoop) const
|
||||
{
|
||||
// recupero il loop nel riferimento intrinseco
|
||||
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pMyCrv == nullptr)
|
||||
return 0 ;
|
||||
// restituisco il numero di curve di cui è composto
|
||||
const ICurveComposite* pMyCompo = GetCurveComposite( pMyCrv) ;
|
||||
return ( pMyCompo == nullptr ? 1 : pMyCompo->GetCurveCount()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const
|
||||
@@ -1149,21 +1210,26 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
||||
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
||||
// calcolo le polilinee che approssimano i loop
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( GetLoopCount( i)) ;
|
||||
vPL.reserve( GetLoopCount( i)) ;
|
||||
int j = 0 ;
|
||||
ICurve* pLoop = GetMyLoop( i, j) ;
|
||||
ICurve* pLoop = GetMyLoop( i, j) ;
|
||||
while ( pLoop != nullptr) {
|
||||
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
|
||||
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL[j]))
|
||||
vPL.emplace_back( PolyLine()) ;
|
||||
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL.back()))
|
||||
return nullptr ;
|
||||
double dLoopArea ;
|
||||
if ( ! vPL.back().GetAreaXY( dLoopArea) || abs( dLoopArea) <= 25 * SQ_EPS_SMALL)
|
||||
vPL.pop_back() ;
|
||||
pLoop = GetMyLoop( i, ++j) ;
|
||||
}
|
||||
// se chunk abbastanza grande, creo la superficie trimesh relativa
|
||||
double dArea ;
|
||||
if ( vPL[0].GetAreaXY( dArea) && dArea > 100 * SQ_EPS_SMALL) {
|
||||
if ( ! vPL.empty() && vPL[0].GetAreaXY( dArea) && dArea > 25 * SQ_EPS_SMALL) {
|
||||
// creo, setto la superficie trimesh ed elimino punti ripetuti
|
||||
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL) || ! pChSTM->DoCompacting())
|
||||
INTMATRIX vnPLIndMat ;
|
||||
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL, vnPLIndMat) || ! pChSTM->DoCompacting())
|
||||
return nullptr ;
|
||||
// porto la trimesh in globale al riferimento intrinseco
|
||||
pChSTM->ToGlob( m_frF) ;
|
||||
@@ -1171,7 +1237,10 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
||||
pSTM->DoSewing( *pChSTM) ;
|
||||
}
|
||||
}
|
||||
// la restituisco
|
||||
// se vuota
|
||||
if ( pSTM->IsEmpty())
|
||||
pSTM->AdjustTopology() ;
|
||||
// la restituisco
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
@@ -1226,6 +1295,56 @@ SurfFlatRegion::CloneChunk( int nChunk) const
|
||||
return Release( pSfr) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::EraseChunk(int nChunk)
|
||||
{
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// se un solo chunk, resetto la regione
|
||||
if ( GetChunkCount() == 1) {
|
||||
Clear() ;
|
||||
return true ;
|
||||
}
|
||||
// se ultimo chunk
|
||||
if ( nChunk == m_vExtInd.size() - 1) {
|
||||
// elimino i loop
|
||||
for ( int i = m_vExtInd[nChunk] ; i < int( m_vpLoop.size()) ; ++ i) {
|
||||
delete m_vpLoop[i] ;
|
||||
m_vpLoop[i] = nullptr ;
|
||||
}
|
||||
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.end()) ;
|
||||
// elimino indice di loop esterno
|
||||
m_vExtInd.pop_back() ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
// numero di loop da eliminare
|
||||
int nLoopCnt = m_vExtInd[nChunk+1] - m_vExtInd[nChunk] ;
|
||||
// elimino i loop
|
||||
for ( int i = m_vExtInd[nChunk] ; i < m_vExtInd[nChunk+1] ; ++ i) {
|
||||
delete m_vpLoop[i] ;
|
||||
m_vpLoop[i] = nullptr ;
|
||||
}
|
||||
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.begin() + m_vExtInd[nChunk+1]) ;
|
||||
// elimino indice di loop esterno
|
||||
m_vExtInd.erase( m_vExtInd.begin() + nChunk) ;
|
||||
// aggiorno indice inizio chunk successivi
|
||||
for ( int i = nChunk ; i < int( m_vExtInd.size()) ; ++i)
|
||||
m_vExtInd[i] -= nLoopCnt ;
|
||||
}
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetAuxSurf() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
|
||||
@@ -1480,3 +1599,154 @@ SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
|
||||
|
||||
return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkMaxOffset( int nChunk, double& dOffs) const
|
||||
{
|
||||
// verifico se è stato calcolato Voronoi
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
if ( ! CalcVoronoiObject())
|
||||
return false ;
|
||||
|
||||
// il massimo offset per il chunk è il massimo offset del suo loop esterno
|
||||
// ( il diagramma di Voronoi tiene già conto della limitazione con i loop interni)
|
||||
int nInd = GetIndFromChunkLoop( nChunk, 0) ;
|
||||
return m_pVoronoiObj->CalcLimitOffset( nInd, true, dOffs) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetMaxOffset( double& dOffs) const
|
||||
{
|
||||
int nChunks = GetChunkCount() ;
|
||||
if ( nChunks == 0)
|
||||
return false ;
|
||||
|
||||
// calcolo il massimo fra gli offset limite di tutti i suoi chunks
|
||||
if ( ! GetChunkMaxOffset( 0, dOffs))
|
||||
return false ;
|
||||
for ( int i = 1 ; i < nChunks ; i++) {
|
||||
double dCurrOffs ;
|
||||
if ( ! GetChunkMaxOffset( i, dCurrOffs))
|
||||
return false ;
|
||||
if ( dCurrOffs > dOffs)
|
||||
dOffs = dCurrOffs ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd)
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
pLoop->SetTempProp( nProp, nPropInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->SetCurveTempProp( nCrv, nProp, nPropInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd) const
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
nProp = pLoop->GetTempProp( nPropInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->GetCurveTempProp( nCrv, nProp, nPropInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ResetAllCurveTempProps( void)
|
||||
{
|
||||
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
||||
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
||||
if ( pLoop != nullptr) {
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
pLoop->SetTempProp( 0, 0) ;
|
||||
pLoop->SetTempProp( 0, 1) ;
|
||||
}
|
||||
else {
|
||||
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
||||
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
||||
pCompoLoop->SetCurveTempProp( nI, 0, 0) ;
|
||||
pCompoLoop->SetCurveTempProp( nI, 0, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd)
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
pLoop->SetTempParam( dParam, nParamInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->SetCurveTempParam( nCrv, dParam, nParamInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd) const
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
dParam = pLoop->GetTempParam( nParamInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->GetCurveTempParam( nCrv, dParam, nParamInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ResetAllCurveTempParams( void)
|
||||
{
|
||||
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
||||
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
||||
if ( pLoop != nullptr) {
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
pLoop->SetTempParam( 0, 0) ;
|
||||
pLoop->SetTempParam( 0, 1) ;
|
||||
}
|
||||
else {
|
||||
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
||||
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
||||
pCompoLoop->SetCurveTempParam( nI, 0, 0) ;
|
||||
pCompoLoop->SetCurveTempParam( nI, 0, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+21
-9
@@ -94,18 +94,30 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
{ return m_frF.Orig() ; }
|
||||
const Vector3d& GetNormVersor( void) const override
|
||||
{ return m_frF.VersZ() ; }
|
||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
|
||||
void ResetVoronoiObject( void) const override ;
|
||||
bool GetMaxOffset( double& dOffs) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
|
||||
int GetChunkCount( void) const override ;
|
||||
SurfFlatRegion* CloneChunk( int nChunk) const override ;
|
||||
bool EraseChunk(int nChunk) override ;
|
||||
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
|
||||
bool GetChunkArea( int nChunk, double& dArea) const override ;
|
||||
bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
|
||||
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
SurfFlatRegion* CloneChunk( int nChunk) const override ;
|
||||
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 CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
void ResetVoronoiObject( void) const override ;
|
||||
bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ;
|
||||
bool GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd = 0) const override ;
|
||||
bool ResetAllCurveTempProps( void) override ;
|
||||
bool SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool ResetAllCurveTempParams( void) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -136,7 +148,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
|
||||
private :
|
||||
bool CopyFrom( const SurfFlatRegion& clSrc) ;
|
||||
bool AddSimpleExtLoop( ICurve* pCrv) ;
|
||||
bool AddSimpleExtLoop( ICurve* pCrv, bool& bAdded) ;
|
||||
bool MyAddExtLoop( ICurve* pCrv) ;
|
||||
bool AddSimpleIntLoop( ICurve* pCrv) ;
|
||||
bool MyAddIntLoop( ICurve* pCrv, int nChunk) ;
|
||||
|
||||
@@ -168,7 +168,7 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
||||
|
||||
// creo una nuova regione a partire da questi loop
|
||||
PtrOwner<SurfFlatRegion> pSfr ;
|
||||
if ( vpLoop.size() == 0)
|
||||
if ( vpLoop.empty())
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
@@ -258,7 +258,7 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other)
|
||||
|
||||
// creo una nuova regione a partire da questi loop
|
||||
PtrOwner<SurfFlatRegion> pSfr ;
|
||||
if ( vpLoop.size() == 0)
|
||||
if ( vpLoop.empty())
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
|
||||
@@ -148,7 +148,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie
|
||||
if ( vOffs.size() > 0) {
|
||||
if ( ! vOffs.empty()) {
|
||||
PCRV_DEQUE vLoops ;
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
||||
vOffs[i]->ToLoc( m_frF) ;
|
||||
@@ -162,7 +162,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
}
|
||||
|
||||
// verifico di avere ancora dei loops
|
||||
if ( vLoops.size() > 0) {
|
||||
if ( ! vLoops.empty()) {
|
||||
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vLoops) ;
|
||||
|
||||
+868
-91
File diff suppressed because it is too large
Load Diff
+64
-21
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2023
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMesh.h Data : 09.12.23 Versione : 2.5l2
|
||||
// File : SurfTriMesh.h Data : 28.03.25 Versione : 2.7c4
|
||||
// Contenuto : Dichiarazione della classe Superficie TriMesh.
|
||||
//
|
||||
//
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GeoObjRW.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
#include <deque>
|
||||
#include <set>
|
||||
|
||||
@@ -52,16 +53,16 @@ class StmTria
|
||||
public :
|
||||
StmTria( void)
|
||||
: nIdVert{ SVT_NULL, SVT_NULL, SVT_NULL}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
|
||||
StmTria( const int nIdV[3])
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
|
||||
StmTria( const int nIdV[3], int nTF)
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
|
||||
StmTria( const int nIdV[3], const int nIdA[3], const Vector3d& vtV, int nTF, int nEF)
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ nIdA[0], nIdA[1], nIdA[2]}, nETempFlag{ 0, 0, 0},
|
||||
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nShell( SVT_NULL), nTemp( 0), nTempShell{ 0} {}
|
||||
public :
|
||||
int nIdVert[3] ;
|
||||
int nIdAdjac[3] ;
|
||||
@@ -70,9 +71,25 @@ class StmTria
|
||||
int nIdFacet ;
|
||||
int nTFlag ;
|
||||
int nEFlag ;
|
||||
mutable int nPart ;
|
||||
mutable int nShell ;
|
||||
mutable int nTemp ;
|
||||
mutable int nTempPart ;
|
||||
mutable int nTempShell ;
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Classe Part
|
||||
class StmPart
|
||||
{
|
||||
public :
|
||||
StmPart( void)
|
||||
: bClosed( false) {}
|
||||
StmPart( bool bClo, const INTVECTOR& vSh)
|
||||
: bClosed( bClo), vShell( vSh) {}
|
||||
int GetShellCount( void)
|
||||
{ return ( vShell.empty() ? 0 : int( vShell.size()) - ( vShell[0] == -1 ? 1 : 0)) ; }
|
||||
public :
|
||||
bool bClosed ;
|
||||
INTVECTOR vShell ;
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -235,7 +252,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool RemoveTriangle( int nId) override ;
|
||||
bool AdjustTopology( void) override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) override ;
|
||||
bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ;
|
||||
bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;
|
||||
@@ -279,6 +296,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
SurfTriMesh* CloneTriangle( int nT) const override ;
|
||||
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||
bool GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||
int GetFacetCount( void) const override ;
|
||||
int GetFacetSize( void) const override
|
||||
{ return int( m_vFacet.size()) ; }
|
||||
@@ -310,14 +328,25 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool Intersect( const ISurfTriMesh& Other) override ;
|
||||
bool Subtract( const ISurfTriMesh& Other) override ;
|
||||
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
|
||||
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
|
||||
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 ;
|
||||
int GetShellCount( void) const override ;
|
||||
bool GetShellArea( int nShell, double& dArea) const override ;
|
||||
bool RemoveShell( int nShell) override ;
|
||||
SurfTriMesh* CloneShell( int nShell) const override ;
|
||||
bool GetPartLocalBBox( int nP, BBox3d& b3Loc) const override ;
|
||||
bool GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const override ;
|
||||
int GetPartCount( void) const override ;
|
||||
bool RemovePart( int nPart) override ;
|
||||
bool GetPartArea( int nPart, double& dArea) const override ;
|
||||
bool GetPartVolume( int nPart, double& dVolume) const override ;
|
||||
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
|
||||
SurfTriMesh* ClonePart( int nPart) const override ;
|
||||
bool SetTFlag( int nId, int nTFlag) override ;
|
||||
bool GetTFlag( int nId, int& nFlag) const override ;
|
||||
int GetMaxTFlag( void) const override
|
||||
{ return m_nMaxTFlag ; }
|
||||
bool ResetTFlags( void) override ;
|
||||
@@ -340,18 +369,20 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
|
||||
return *this ; }
|
||||
bool Clear( void) ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat) ;
|
||||
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 GetTFlag( int nId, int& nFlag) const ;
|
||||
bool GetTempInt( int nId, int& nTempInt) const ;
|
||||
bool ResetTempInts( void) const ;
|
||||
bool SetTFlag( int nId, int nTFlag) ;
|
||||
bool SetTempInt( int nId, int nTempInt) const ;
|
||||
bool AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol = 2 * EPS_SMALL) ;
|
||||
bool AdjustTopologyFromZMap( void) ;
|
||||
|
||||
private :
|
||||
typedef std::vector<StmVert> VERTVECTOR ;
|
||||
typedef std::vector<StmTria> TRIAVECTOR ;
|
||||
typedef std::vector<StmPart> PARTVECTOR ;
|
||||
typedef std::vector<StmFacEdge> FACEDGEVECTOR ;
|
||||
typedef std::deque<Stm3Int> TRINTDEQUE ;
|
||||
|
||||
@@ -362,7 +393,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool CopyFrom( const SurfTriMesh& clSrc) ;
|
||||
bool Validate( bool bCorrect = false) ;
|
||||
bool AdjustVertices( void) ;
|
||||
bool AdjustAdjacencies( void) ;
|
||||
bool AdjustAdjacencies( bool AdjustVert = true) ;
|
||||
bool AdjustOrientations( void) ;
|
||||
bool AdjustTriaOrientation( TRINTDEQUE& S3iQ) ;
|
||||
bool TestSealing( void) ;
|
||||
@@ -396,23 +427,27 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool UpdateFacetEdging( void) ;
|
||||
void ResetHashGrids3d( void) const ;
|
||||
bool VerifyHashGrids3d( void) const ;
|
||||
bool VerifyConnection( void) const ;
|
||||
bool VerifyConnection( bool bShellsAndParts = true) const ;
|
||||
bool IsShellClosed( int nShell) const ;
|
||||
bool IsPartClosed( int nPart) const ;
|
||||
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
|
||||
bool CutByTriangles( 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) ;
|
||||
bool IdentifyParts( void) const ;
|
||||
bool IdentifyShells( void) const ;
|
||||
bool RemoveDoubleTriangles( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified, double dMinSqDist = SQ_EPS_TRIA_H) ;
|
||||
bool FlipTriangles( int nTA, int nTB) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true, double dTolAlign = 50 * EPS_SMALL) ;
|
||||
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) ;
|
||||
|
||||
bool AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const ;
|
||||
bool RemoveInvalidTriangles( const INTVECTOR& vIds) ;
|
||||
bool FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const ;
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
@@ -434,9 +469,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli
|
||||
mutable int m_nParts ; // numero di parti connesse (-1 se da calcolare)
|
||||
mutable int m_nShells ; // numero di gusci connessi (-1 se da calcolare)
|
||||
mutable PARTVECTOR m_vPart ; // vettore delle parti (flag chiusura e elenco shell, prima sempre esterna o infinita)
|
||||
mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento
|
||||
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
|
||||
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -454,3 +490,10 @@ inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj)
|
||||
{ if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH)
|
||||
return nullptr ;
|
||||
return ( static_cast<SurfTriMesh*>( pGObj)) ; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Raccolte di puntatori a SurfTriMesh
|
||||
typedef std::vector<const SurfTriMesh*> CISRFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
|
||||
typedef std::vector<SurfTriMesh*> ISRFTMPVECTOR ; // vettore di puntatori a SurfTriMesh
|
||||
typedef std::list<SurfTriMesh*> ISRFTMPLIST ; // lista di puntatori a SurfTriMesh
|
||||
typedef std::vector<PtrOwner<SurfTriMesh>> ISRFTMPOVECTOR ; // vettore di puntatori esclusivi a SurfTriMesh
|
||||
|
||||
+286
-389
File diff suppressed because it is too large
Load Diff
+9
-9
@@ -15,10 +15,10 @@
|
||||
#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/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
|
||||
@@ -79,7 +79,7 @@ SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModi
|
||||
if ( m_vVert[i].nIdTria == SVT_DEL)
|
||||
continue ;
|
||||
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
if ( abs( dDist) < 1.1 * EPS_SMALL)
|
||||
m_vVert[i].nTemp = 0 ;
|
||||
else if ( dDist > 0)
|
||||
m_vVert[i].nTemp = +1 ;
|
||||
@@ -613,7 +613,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
++ it ;
|
||||
}
|
||||
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
|
||||
if ( cvClosedChain.size() > 1 || ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > 0)) {
|
||||
if ( cvClosedChain.size() > 1 || ( ! cvClosedChain.empty() && ! cvOpenChain.empty())) {
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
return false ;
|
||||
}
|
||||
@@ -676,7 +676,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
}
|
||||
|
||||
// Loop aperti, devo chiuderli
|
||||
else if ( cvOpenChain.size() > 0) {
|
||||
else if ( ! cvOpenChain.empty()) {
|
||||
// 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
|
||||
@@ -691,7 +691,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
BOOLVECTOR vbInOut ;
|
||||
vbInOut.push_back( true) ;
|
||||
// Divido il loop di partenza in sotto-loop
|
||||
while ( cvOpenChain.size() > 0) {
|
||||
while ( ! cvOpenChain.empty()) {
|
||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
|
||||
// Estremi del loop aperto
|
||||
@@ -781,14 +781,14 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
}
|
||||
}
|
||||
|
||||
// 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())
|
||||
if ( ! SimplifyFacets( CUT_SCALE * MAX_EDGE_LEN_STD))
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::GeneralizedCut")
|
||||
}
|
||||
|
||||
// Ripristino scala originale
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
|
||||
{
|
||||
// recupero i loop della faccia
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||
return false ;
|
||||
// calcolo il centro del loop esterno (è il primo)
|
||||
PolygonPlane PolyPlane ;
|
||||
@@ -682,7 +682,7 @@ SurfTriMesh::GetFacetArea( int nF, double& dArea) const
|
||||
{
|
||||
// recupero i loop della faccia
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||
return false ;
|
||||
// sommo le aree dei diversi loop (quelli interni hanno area negativa)
|
||||
dArea = 0 ;
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
|
||||
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.25 RE Creazione modulo.
|
||||
// 10.06.25 RE Offset di superfici chiuse.
|
||||
// 04.07.25 RE Thickening Offset di superfici generiche.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static ISurfTriMesh*
|
||||
SumStm( const CISURFTMPVECTOR& vStm)
|
||||
{
|
||||
// se vettore vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// definisco la superficie somma tra tutte ( la prima deve essere valida)
|
||||
PtrOwner<ISurfTriMesh> pStmAdd( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmAdd))
|
||||
return nullptr ;
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* pStm : vStm) {
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || pStm->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
if ( ! pStmAdd->IsValid() || pStmAdd->GetTriangleCount() == 0) {
|
||||
if ( ! pStmAdd->CopyFrom( pStm))
|
||||
return nullptr ;
|
||||
}
|
||||
else
|
||||
pStmAdd->Add( *pStm) ;
|
||||
}
|
||||
// restituisco la superficie ottenuta
|
||||
return ( Release( pStmAdd)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea il Fat Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//* Funzione che crea il Fat Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user