Compare commits
197 Commits
| 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 |
+678
-67
@@ -16,11 +16,43 @@
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveArc.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
// Test di Debug per disegnare le posizioni dei punti per la ricostruzione degli spigoli vivi
|
||||
#define ENABLE_SHARPED_EDGES_DEBUG 0
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
string Sharped_Edges_Debug_File_Name = "C:\\Temp\\SharpedEdges.nge" ;
|
||||
#endif
|
||||
// Test di Debug per disegnare le quote dove sono trovate le intersesioni tra il tool e le trimesh
|
||||
#define ENABLE_COLORED_GRID_DEBUG 0
|
||||
#if ENABLE_COLORED_GRID_DEBUG
|
||||
string Colored_Grid_Debug_File_Name = "C:\\Temp\\ColoredGrid.nge" ;
|
||||
#endif
|
||||
// Test di Debug per disegnare i segmenti ricavati dal marchingSquares
|
||||
#define ENABLE_PROCESS_SQUARE_DEBUG 0
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG
|
||||
string Process_Square_Debug_File_Name = "C:\\Temp\\ProcessSquares.nge" ;
|
||||
#endif
|
||||
// Test di Debug per disegnare i punti ricavati con il metodo di Bisezione
|
||||
#define ENABLE_BISECTION_DEBUG 0
|
||||
#if ENABLE_BISECTION_DEBUG
|
||||
string Bisection_Debug_File_Name = "C:\\Temp\\Bisection.nge" ;
|
||||
#endif
|
||||
// Inclusione file per salvataggio
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG || ENABLE_COLORED_GRID_DEBUG || ENABLE_PROCESS_SQUARE_DEBUG || ENABLE_BISECTION_DEBUG
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzioni locali per calcolo isolinee con metodo Marching Squares
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -36,14 +68,19 @@ using namespace std ;
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// tipo di punto della PolyLinea
|
||||
enum PointType {
|
||||
VALID = 0 , // punto valido da conservare
|
||||
INVALID = -1, // punto da scartare
|
||||
SHARPED_EXT = 1, // punto per spigolo vivo (con angolo esterno)
|
||||
SHARPED_INT = 2, // punto per spigolo vivo (con angolo interno)
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static Point3d
|
||||
CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel,
|
||||
CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel, double dOffsR,
|
||||
const ICAvToolSurfTm& cavTstm, const Frame3d &frGrid)
|
||||
{
|
||||
// Distanza tra gli estremi iniziali
|
||||
double dDist = max( abs( ptS.x - ptE.x), abs( ptS.y - ptE.y)) ;
|
||||
|
||||
// Ricerca con metodo di bisezione (si arresta quando il medio è allineato agli estremi)
|
||||
const int MAX_ITER = 10 ;
|
||||
int nCount = 0 ;
|
||||
@@ -53,13 +90,15 @@ CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel,
|
||||
while ( nCount < MAX_ITER) {
|
||||
// verifica del punto medio
|
||||
ptMid.z = 0 ;
|
||||
Point3d ptTest = GetToGlob( ptMid + cavTstm.GetToolHeight() * Z_AX, frGrid) ;
|
||||
Point3d ptTest = GetToGlob( ptMid + ( cavTstm.GetToolHeight() - dOffsR) * Z_AX, frGrid) ;
|
||||
double dMove ;
|
||||
cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dMove) ;
|
||||
ptMid.z = dMove ;
|
||||
// se sta sulla linea che unisce gli estremi, basta interpolazione lineare
|
||||
if ( abs( ptMid.z - ( ptP1.z + ptP2.z) / 2) < EPS_SMALL / 2)
|
||||
return Media( ptP1, ptP2, ( ptP1.z - dLevel) / ( ptP1.z - ptP2.z)) ;
|
||||
// se estremi coincidenti, allora mi fermo
|
||||
if ( SqDistXY( ptP1, ptP2) < 4 * SQ_EPS_SMALL) {
|
||||
ptMid.z = dLevel ;
|
||||
return ptMid ;
|
||||
}
|
||||
// altrimenti nuova suddivisione della parte con estremi da parte opposta rispetto al livello
|
||||
bool b1On = ( ptP1.z > dLevel) ;
|
||||
bool bMidOn = ( ptMid.z > dLevel) ;
|
||||
@@ -76,24 +115,29 @@ CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
ProcessSquare( int nFlag, int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
||||
ProcessSquare( int nFlag, double dLevel, double dQPt0, double dQpt1, double dQpt2, double dQpt3,
|
||||
int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
||||
{
|
||||
static int LineTable[16][5] = { { 0, -1, -1, -1, -1},
|
||||
{ 1, 0, 3, -1, -1},
|
||||
{ 1, 1, 0, -1, -1},
|
||||
{ 1, 1, 3, -1, -1},
|
||||
{ 1, 2, 1, -1, -1},
|
||||
{ 2, 0, 1, 2, 3},
|
||||
{ 1, 2, 0, -1, -1},
|
||||
{ 1, 2, 3, -1, -1},
|
||||
{ 1, 3, 2, -1, -1},
|
||||
{ 1, 0, 2, -1, -1},
|
||||
{ 2, 1, 2, 3, 0},
|
||||
{ 1, 1, 2, -1, -1},
|
||||
{ 1, 3, 1, -1, -1},
|
||||
{ 1, 0, 1, -1, -1},
|
||||
{ 1, 3, 0, -1, -1},
|
||||
{ 0, -1, -1, -1, -1}} ;
|
||||
static int LineTable[16][5] = { { 0, -1, -1, -1, -1}, // ( 0)
|
||||
{ 1, 0, 3, -1, -1}, // ( 1)
|
||||
{ 1, 1, 0, -1, -1}, // ( 2)
|
||||
{ 1, 1, 3, -1, -1}, // ( 3)
|
||||
{ 1, 2, 1, -1, -1}, // ( 4)
|
||||
{ 2, 0, 1, 2, 3}, // ( 5.0) -> primo caso ambiguo
|
||||
{ 1, 2, 0, -1, -1}, // ( 6)
|
||||
{ 1, 2, 3, -1, -1}, // ( 7)
|
||||
{ 1, 3, 2, -1, -1}, // ( 8)
|
||||
{ 1, 0, 2, -1, -1}, // ( 9)
|
||||
{ 2, 1, 2, 3, 0}, // ( 10.0) -> primo caso ambiguo
|
||||
{ 1, 1, 2, -1, -1}, // ( 11)
|
||||
{ 1, 3, 1, -1, -1}, // ( 12)
|
||||
{ 1, 0, 1, -1, -1}, // ( 13)
|
||||
{ 1, 3, 0, -1, -1}, // ( 14)
|
||||
{ 0, -1, -1, -1, -1}} ; // ( 15)
|
||||
|
||||
static int LineTableAmbiguos[2][5] = { { 2, 0, 3, 2, 1}, // ( 5.1) -> secondo caso ambiguo
|
||||
{ 2, 1, 0, 3, 2}} ; // ( 10.1) -> secondo caso ambiguo
|
||||
|
||||
// flag fuori dai limiti
|
||||
if ( nFlag < 0 || nFlag > 15)
|
||||
return -1 ;
|
||||
@@ -108,12 +152,42 @@ ProcessSquare( int nFlag, int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
||||
}
|
||||
// due linee
|
||||
else if ( LineTable[nFlag][0] == 2) {
|
||||
nI1s = LineTable[nFlag][1] ;
|
||||
nI1e = LineTable[nFlag][2] ;
|
||||
nI2s = LineTable[nFlag][3] ;
|
||||
nI2e = LineTable[nFlag][4] ;
|
||||
// controllo in quale caso sono
|
||||
if ( nFlag == 5) {
|
||||
// caso 5.0
|
||||
if ( ( dQPt0 - dLevel) * ( dQpt2 - dLevel) > ( dQpt1 - dLevel) * ( dQpt3 - dLevel)) {
|
||||
nI1s = LineTable[nFlag][1] ;
|
||||
nI1e = LineTable[nFlag][2] ;
|
||||
nI2s = LineTable[nFlag][3] ;
|
||||
nI2e = LineTable[nFlag][4] ;
|
||||
}
|
||||
// caso 5.1
|
||||
else {
|
||||
nI1s = LineTableAmbiguos[0][1] ;
|
||||
nI1e = LineTableAmbiguos[0][2] ;
|
||||
nI2s = LineTableAmbiguos[0][3] ;
|
||||
nI2e = LineTableAmbiguos[0][4] ;
|
||||
}
|
||||
}
|
||||
else if ( nFlag == 10) {
|
||||
// caso 10.0
|
||||
if ( ( dQPt0 - dLevel) * ( dQpt2 - dLevel) < ( dQpt1 - dLevel) * ( dQpt3 - dLevel)) {
|
||||
nI1s = LineTable[nFlag][1] ;
|
||||
nI1e = LineTable[nFlag][2] ;
|
||||
nI2s = LineTable[nFlag][3] ;
|
||||
nI2e = LineTable[nFlag][4] ;
|
||||
}
|
||||
// caso 10.1
|
||||
else {
|
||||
nI1s = LineTableAmbiguos[1][1] ;
|
||||
nI1e = LineTableAmbiguos[1][2] ;
|
||||
nI2s = LineTableAmbiguos[1][3] ;
|
||||
nI2e = LineTableAmbiguos[1][4] ;
|
||||
}
|
||||
}
|
||||
return 2 ;
|
||||
}
|
||||
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
@@ -121,7 +195,7 @@ ProcessSquare( int nFlag, int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
||||
static bool
|
||||
TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd, int nFirst, int nLast,
|
||||
const DBLVECTOR& vdGrid, int nStepX, double dStep,
|
||||
double dLevel, const ICAvToolSurfTm& cavTstm, const Frame3d &frGrid)
|
||||
double dLevel, double dOffsR, const ICAvToolSurfTm& cavTstm, const Frame3d &frGrid)
|
||||
{
|
||||
for ( int k = nFirst ; k <= nLast ; ++ k) {
|
||||
// recupero i differenti indici
|
||||
@@ -134,7 +208,7 @@ TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd,
|
||||
Point3d ptS{ i * dStep, j * dStep, vdGrid[nInd]} ;
|
||||
Point3d ptE{ ptS.x + ( bOnX ? dStep : 0), ptS.y + ( bOnX ? 0 : dStep), vdGrid[nInd + ( bOnX ? 1 : nStepX + 1)]} ;
|
||||
// calcolo il punto
|
||||
Point3d ptQ = CalcPoint( ptS, ptE, dLevel, cavTstm, frGrid) ;
|
||||
Point3d ptQ = CalcPoint( ptS, ptE, dLevel, dOffsR, cavTstm, frGrid) ;
|
||||
umEdgePnt[ nKey] = ptQ ;
|
||||
}
|
||||
return true ;
|
||||
@@ -142,9 +216,351 @@ TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, double dRad,
|
||||
double dLevel, const ICAvToolSurfTm& cavTstm, const Frame3d &frGrid, POLYLINEVECTOR& vPL)
|
||||
ModifyPolyLineToSharped( PNTIVECTOR& vAdvPt, const CAvToolSurfTm& cavTstm, const Frame3d& frGrid,
|
||||
double dAngTol, double dStep, double dSegLen)
|
||||
{
|
||||
// dichiaro i versori tangenti consecutivi per il percorso della PolyLinea
|
||||
Vector3d vtTanPrev, vtTan, vtTanAfter ;
|
||||
// ciclo i punti successivi
|
||||
for ( int i = 2 ; i < int( vAdvPt.size()) - 1 ; ++ i) {
|
||||
// calcolo il versore tangente del segmento prececente
|
||||
vtTanPrev = vAdvPt[i-1].first - vAdvPt[i-2].first ;
|
||||
vtTanPrev.Normalize() ;
|
||||
// calcolo versore tangente attuale
|
||||
vtTan = ( vAdvPt[i].first - vAdvPt[i-1].first) ;
|
||||
vtTan.Normalize() ;
|
||||
// recupero l'angolo con segno tra la direzione precedente e la direzione attuale
|
||||
double dAngDeg ;
|
||||
if ( ! vtTanPrev.GetAngleXY( vtTan, dAngDeg))
|
||||
continue ;
|
||||
// potrei modificare il punto i-esimo nei seguenti casi :
|
||||
// 1) l'angolo tra i versori supera la tolleranza
|
||||
// 2) la distana tra il punto i-esimo e il primo non valido è compresa in due quadrati adiacenti
|
||||
bool bModifyPoint = ( ( abs( dAngDeg) > dAngTol)) ;
|
||||
if ( bModifyPoint) {
|
||||
for ( int j = i - 1 ; j >= max( 0, i - 2) && bModifyPoint ; -- j) {
|
||||
if ( vAdvPt[j].second == PointType::INVALID) {
|
||||
bModifyPoint = ( SqDist( vAdvPt[i].first, vAdvPt[j].first) < 8 * dStep * dStep) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bModifyPoint) {
|
||||
// recupero la direzione successiva
|
||||
vtTanAfter = ( vAdvPt[i+1].first - vAdvPt[i].first) ;
|
||||
vtTanAfter.Normalize() ;
|
||||
// definisco i segmenti di raccordo, lunghi quanto la diagonale principale della griglia
|
||||
PtrOwner<ICurveLine> pSegPrev( CreateCurveLine()) ;
|
||||
if ( IsNull( pSegPrev) || ! pSegPrev->Set( vAdvPt[i-1].first, vAdvPt[i-1].first + vtTanPrev * dSegLen))
|
||||
return false ;
|
||||
PtrOwner<ICurveLine> pSegAft( CreateCurveLine()) ;
|
||||
if ( IsNull( pSegAft) || ! pSegAft->Set( vAdvPt[i].first, vAdvPt[i].first - vtTanAfter * dSegLen))
|
||||
return false ;
|
||||
// cerco l'intersezione tra i due segmenti
|
||||
IntersCurveCurve ICC( *pSegPrev, *pSegAft) ;
|
||||
bModifyPoint = ( ICC.GetIntersCount() > 0) ;
|
||||
if ( bModifyPoint) {
|
||||
IntCrvCrvInfo aInfo ;
|
||||
if ( ! ICC.GetIntCrvCrvInfo( 0, aInfo))
|
||||
return false ;
|
||||
// recupero il punto di intersezione
|
||||
Point3d ptInters = aInfo.IciA->ptI ;
|
||||
// controllo la distanza con tale punto di intersezione e i punti precedenti.
|
||||
// Questa deve essere contenuta in 5 quadrati della griglia
|
||||
bModifyPoint = ( SqDist( ptInters, vAdvPt[i-1].first) < 50 * dStep * dStep &&
|
||||
SqDist( ptInters, vAdvPt[i].first) < 50 * dStep * dStep) ;
|
||||
if ( bModifyPoint) {
|
||||
// determino versore di movimento
|
||||
Vector3d vtMove = ( vtTanPrev - vtTanAfter) ;
|
||||
vtMove.Normalize() ;
|
||||
// stabilisco se l'angolo attuale è esterno o interno
|
||||
bool bIsExternalAngle = ( dAngDeg > 0.) ;
|
||||
// dal punto di intersezione mi allontano leggermente dal materiale (1/16 del passo griglia)
|
||||
if ( bIsExternalAngle)
|
||||
vtMove *= ( dStep / 16.) ;
|
||||
else
|
||||
vtMove *= - ( dStep / 16.) ;
|
||||
// definisco il punto di test
|
||||
Point3d ptTest = ptInters + vtMove ;
|
||||
// verifico se l'utensile tocca il materiale se posizionato in ptTest
|
||||
double dToTDist = 0. ;
|
||||
ptTest.z += cavTstm.GetToolHeight() ;
|
||||
ptTest.ToGlob( frGrid) ;
|
||||
if ( ! cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dToTDist))
|
||||
return false ;
|
||||
// modifico se non ho intersezione con TriMesh, allora aggiungo il punto
|
||||
bModifyPoint = ( dToTDist < EPS_SMALL) ;
|
||||
if ( bModifyPoint) {
|
||||
// il punto i-esimo diventa il punto di intersezione ( quindi di tipo Sharped)
|
||||
vAdvPt[i].first = ptInters ;
|
||||
vAdvPt[i].second = ( bIsExternalAngle ? PointType::SHARPED_EXT : PointType::SHARPED_INT) ;
|
||||
// il punto (i-1)-esimo essendo in tangenza diventa invalido
|
||||
vAdvPt[i-1].second = PointType::INVALID ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int nStepX, int nStepY,
|
||||
const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol,
|
||||
bool bAdvCorners)
|
||||
{
|
||||
// se non ho polylinee, allora esco
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
dAngTol = max( dAngTol, ANG_TOL_STD_DEG / 5.) ;
|
||||
double dSegLen = 50 * dStep ;
|
||||
|
||||
// cerco la PolyLine di area maggiore, determinerà il verso di percorrenza
|
||||
double dMaxArea = 0. ;
|
||||
int nIndMaxArea = 0 ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// semplifico rimuovendo i punti allineati
|
||||
vPL[i].RemoveAlignedPoints( 10 * EPS_SMALL) ;
|
||||
// calcolo l'area
|
||||
double dMyArea ;
|
||||
if ( vPL[i].GetAreaXY( dMyArea) && dMyArea > dMaxArea) {
|
||||
dMaxArea = dMyArea ;
|
||||
nIndMaxArea = i ;
|
||||
}
|
||||
}
|
||||
if ( nIndMaxArea > 0)
|
||||
swap( vPL[0], vPL[nIndMaxArea]) ;
|
||||
|
||||
// ordino le PolyLines cercando loop interni ed esterni (gli interni vengono invertiti)
|
||||
INTMATRIX mIndMat ;
|
||||
BOOLVECTOR vbInv ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv))
|
||||
return false ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
|
||||
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
|
||||
// ombra del tool
|
||||
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
|
||||
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
|
||||
// 1° gruppo, griglia di punti
|
||||
for ( int j = 0 ; j <= nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= nStepX ; ++ i) {
|
||||
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
|
||||
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
|
||||
myPtGrid->Set( ptP) ;
|
||||
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
|
||||
vvCol[0].emplace_back( BLUE) ;
|
||||
}
|
||||
}
|
||||
// 2° gruppo, superfici
|
||||
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
|
||||
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
|
||||
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
|
||||
if ( ! IsNull( pMyStm)) {
|
||||
pMyStm->ToLoc( frGrid) ;
|
||||
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
|
||||
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// vettore delle polyline visitate ( viste però come curve composite)
|
||||
ICRVCOMPOPOVECTOR vPL_AsCompo ; vPL_AsCompo.reserve( vPL.size()) ;
|
||||
|
||||
// scorro i Chunk della matrice di interi, quindi le righe
|
||||
for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) {
|
||||
// scorro le PolyLinee presenti nel Chunk
|
||||
for ( int nLoop = 0 ; nLoop < int( mIndMat[nChunk].size()) ; ++ nLoop) {
|
||||
// recupero l'indice della PolyLine di riferimento
|
||||
int nPol = mIndMat[nChunk][nLoop] ;
|
||||
if ( nPol < 0 || nPol >= int( vPL.size()))
|
||||
return false ;
|
||||
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla
|
||||
int nPts = vPL[nPol].GetPointNbr() ;
|
||||
if ( nPts < 4)
|
||||
continue ;
|
||||
// creo un vettore contenente tutti i punti ( cerco nel mentre il segmento più lungo)
|
||||
PNTVECTOR vPt ; vPt.reserve( nPts) ;
|
||||
int nLongEdge = -1 ;
|
||||
double dMaxSqLen = 0. ;
|
||||
Point3d myPt ;
|
||||
if ( ! vPL[nPol].GetFirstPoint( myPt))
|
||||
return false ;
|
||||
vPt.emplace_back( myPt) ;
|
||||
while ( vPL[nPol].GetNextPoint( myPt)) {
|
||||
double dCurrSqDist = SqDist( vPt.back(), myPt) ;
|
||||
if ( dCurrSqDist > dMaxSqLen) {
|
||||
dMaxSqLen = dCurrSqDist ;
|
||||
nLongEdge = int( vPt.size()) - 1 ;
|
||||
}
|
||||
vPt.emplace_back( myPt) ;
|
||||
}
|
||||
if ( nLongEdge < 0 || nLongEdge > nPts - 2)
|
||||
return false ;
|
||||
// calcolo il punto iniziale come punto medio del segmento più lungo
|
||||
Point3d ptStart = Media( vPt[nLongEdge], vPt[nLongEdge + 1]) ;
|
||||
ChangePolyLineStart( vPL[nPol], ptStart, 10 * EPS_SMALL) ;
|
||||
nPts = vPL[nPol].GetPointNbr() ;
|
||||
|
||||
// creazione vettore di punti avanzati ( tutti validi)
|
||||
PNTIVECTOR vAdvPt ; vAdvPt.reserve( nPts) ;
|
||||
vPL[nPol].GetFirstPoint( myPt) ;
|
||||
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
|
||||
while ( vPL[nPol].GetNextPoint( myPt))
|
||||
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 3° gruppo, punti della PolyLine
|
||||
for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) {
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
myPt->Set( vAdvPt[i].first) ;
|
||||
vvpGObj[2].emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
vvCol[2].emplace_back( BLACK) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// modifico la posizione dei punti
|
||||
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
|
||||
return false ;
|
||||
|
||||
// ricostrusico la polyLine a partire da una vuota
|
||||
PolyLine PL_New ;
|
||||
double dPar = -1 ;
|
||||
for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) {
|
||||
// se punto valido o sharped di angolo interno, lo aggiungo
|
||||
if ( j == 0 || j == int( vAdvPt.size() - 1) ||
|
||||
vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT)
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
// se è un punto sharped di un angolo esterno
|
||||
else if ( vAdvPt[j].second == PointType::SHARPED_EXT) {
|
||||
// se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto
|
||||
if ( ! bAdvCorners)
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
else {
|
||||
// ricavo il punto a minima distanza dal materiale mediante metodo di bisezione
|
||||
Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ;
|
||||
vtPrev.Normalize() ;
|
||||
Vector3d vtAfter = ( vAdvPt[j+1].first - vAdvPt[j].first) ;
|
||||
vtAfter.Normalize() ;
|
||||
Vector3d vtMove = ( vtPrev + vtAfter) ;
|
||||
vtMove.Normalize() ;
|
||||
Point3d ptTest = vAdvPt[j].first + ( 2 * dStep * vtMove) ; // doppio dello step griglia
|
||||
const int MAX_ITER = 20 ;
|
||||
int nCount = 0 ;
|
||||
while ( nCount < MAX_ITER) {
|
||||
double dMove ;
|
||||
ptTest.z += cavTstm.GetToolHeight() ;
|
||||
ptTest.ToGlob( frGrid) ;
|
||||
cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dMove) ;
|
||||
ptTest.ToLoc( frGrid) ;
|
||||
ptTest.z -= cavTstm.GetToolHeight() ;
|
||||
if ( dMove > EPS_SMALL)
|
||||
ptTest = Media( ptTest, vAdvPt[j].first) ;
|
||||
else
|
||||
break ;
|
||||
++ nCount ;
|
||||
}
|
||||
// ricavo i punti a minima distanza tra i due segmenti
|
||||
Point3d ptMinDistA, ptMinDistB ;
|
||||
DistPointLine distPtLPrev( ptTest, vAdvPt[j-1].first, vAdvPt[j].first) ;
|
||||
DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ;
|
||||
distPtLPrev.GetMinDistPoint( ptMinDistA) ;
|
||||
distPtLSucc.GetMinDistPoint( ptMinDistB) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistA) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptTest) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistB) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 5° gruppo, punti minDist A e B e ptMid
|
||||
PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
|
||||
myPtA->Set( ptMinDistA) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
|
||||
myPtB->Set( ptMinDistB) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
|
||||
myPtMid->Set( ptTest) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla
|
||||
// trimesh rischio di evere Chunk distinti uniti in un unico Chunk
|
||||
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCompo))
|
||||
return false ;
|
||||
pCompo->FromPolyLine( vPL[nPol]) ;
|
||||
SelfIntersCurve SIC( *pCompo) ;
|
||||
bool bDiscard = ( SIC.GetCrossOrOverlapIntersCount() > 0) ;
|
||||
if ( ! bDiscard) {
|
||||
// se la polyLine interseca una delle PolyLine precedenti, non la modifico
|
||||
for ( auto& pCompoPL_Prev : vPL_AsCompo) {
|
||||
IntersCurveCurve ICC( *pCompo, *pCompoPL_Prev) ;
|
||||
if ( ICC.GetCrossOrOverlapIntersCount() > 0) {
|
||||
bDiscard = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se nuova approssimazione da conservare, memorizzo i risultati
|
||||
if ( ! bDiscard) {
|
||||
vPL[nPol] = PL_New ;
|
||||
vPL_AsCompo.emplace_back( Release( pCompo)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
// 6° gruppo, curve composita derivante dalla polyline
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||
vvCol[5].emplace_back( RED) ;
|
||||
vpCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
}
|
||||
// 7° gruppo, controOffset
|
||||
ICURVEPOVECTOR vCrvCompoOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vCrvCompoOffs, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND)) {
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
return false ;
|
||||
}
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
for ( const auto& pCvrOffs : vCrvCompoOffs) {
|
||||
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCvrOffs))) ;
|
||||
vvCol[6].emplace_back( WHITE) ;
|
||||
}
|
||||
string myName = Sharped_Edges_Debug_File_Name +
|
||||
to_string( dLevel) + "_" +
|
||||
to_string( dAngTol) + ".nge" ;
|
||||
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, double dRad,
|
||||
double dOffsR, double dLevel, const CAvToolSurfTm& cavTstm, const Frame3d &frGrid,
|
||||
double dDimZ, double dCalcLevel, bool bTool, POLYLINEVECTOR& vPL)
|
||||
{
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG || ENABLE_BISECTION_DEBUG
|
||||
vector<IGeoObj*> VT_GO ;
|
||||
vector<Color> VT_CO ;
|
||||
#endif
|
||||
|
||||
// Analizzo gli edge da cui passano le curve cercate
|
||||
unordered_map<int, Point3d> umEdgePnt( 4 * ( nStepX + nStepY)) ;
|
||||
INTVECTOR vEdgeInd ;
|
||||
@@ -161,9 +577,49 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
bool bUp1 = ( vdGrid[nInd1] > dLevel) ;
|
||||
bool bUp2 = ( vdGrid[nInd2] > dLevel) ;
|
||||
bool bUp3 = ( vdGrid[nInd3] > dLevel) ;
|
||||
|
||||
#if ENABLE_BISECTION_DEBUG
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( i * dStep, j * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp0 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ( i + 1) * dStep, j * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp1 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ( i + 1) * dStep, ( j + 1) * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp2 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( i * dStep, ( j + 1) * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp3 ? BLUE : RED) ;
|
||||
#endif
|
||||
|
||||
// se tutti uguali, passo al successivo
|
||||
if ( bUp0 == bUp1 && bUp0 == bUp2 && bUp0 == bUp3)
|
||||
continue ;
|
||||
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( i * dStep, j * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp0 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ( i + 1) * dStep, j * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp1 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ( i + 1) * dStep, ( j + 1) * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp2 ? BLUE : RED) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( i * dStep, ( j + 1) * dStep, dDimZ)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( bUp3 ? BLUE : RED) ;
|
||||
#endif
|
||||
|
||||
// verifico quali calcolare
|
||||
if ( bUp0 != bUp1) {
|
||||
int nKey = 2 * nInd0 ;
|
||||
@@ -202,7 +658,7 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || nEdgeCnt < 50) {
|
||||
TestSubEdges( umEdgePnt, vEdgeInd, 0, nEdgeCnt - 1, vdGrid, nStepX, dStep, dLevel, cavTstm, frGrid) ;
|
||||
TestSubEdges( umEdgePnt, vEdgeInd, 0, nEdgeCnt - 1, vdGrid, nStepX, dStep, dLevel, dOffsR, cavTstm, frGrid) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
@@ -219,7 +675,7 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &TestSubEdges, ref( umEdgePnt), cref( vEdgeInd), vFstLst[i].first, vFstLst[i].second,
|
||||
cref( vdGrid), nStepX, dStep, dLevel, cref( cavTstm), cref( frGrid)) ;
|
||||
cref( vdGrid), nStepX, dStep, dLevel, dOffsR, cref( cavTstm), cref( frGrid)) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
@@ -257,15 +713,37 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
int vKey[4] = { 2 * nInd0, 2 * nInd1 + 1, 2 * nInd3, 2 * nInd0 + 1} ;
|
||||
// calcolo segmenti da inserire
|
||||
int nI1s, nI1e, nI2s, nI2e ;
|
||||
int nSegCnt = ProcessSquare( nFlag, nI1s, nI1e, nI2s, nI2e) ;
|
||||
int nSegCnt = ProcessSquare( nFlag, dLevel, vdGrid[nInd0], vdGrid[nInd1], vdGrid[nInd2],
|
||||
vdGrid[nInd3], nI1s, nI1e, nI2s, nI2e) ;
|
||||
if ( nSegCnt == -1)
|
||||
return false ;
|
||||
else if ( nSegCnt == 1) {
|
||||
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
||||
Point3d ptL1e = umEdgePnt.find( vKey[nI1e])->second ;
|
||||
|
||||
#if ENABLE_BISECTION_DEBUG
|
||||
if ( SqDist( Point3d( i * dStep, j * dStep, dDimZ), Point3d( 445, 190, dDimZ)) < 10) {
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ptL1s + frGrid.VersZ() * 10)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( WHITE) ;
|
||||
myPt.Set( CreateGeoPoint3d()) ;
|
||||
myPt->Set( Point3d( ptL1e + frGrid.VersZ() * 10)) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( WHITE) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
vBiPnt.emplace_back( ptL1s, ptL1e) ;
|
||||
Vector3d vtDir1 = ptL1e - ptL1s ; vtDir1.Normalize() ;
|
||||
chainC.AddCurve( int( vBiPnt.size()), ptL1s, vtDir1, ptL1e, vtDir1) ;
|
||||
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG
|
||||
PtrOwner<ICurveLine> pMyLine( CreateCurveLine()) ;
|
||||
pMyLine->Set( ptL1s, ptL1e) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( pMyLine))) ;
|
||||
VT_CO.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ;
|
||||
#endif
|
||||
}
|
||||
else if ( nSegCnt == 2) {
|
||||
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
||||
@@ -278,10 +756,33 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
vBiPnt.emplace_back( ptL2s, ptL2e) ;
|
||||
Vector3d vtDir2 = ptL2e - ptL2s ; vtDir2.Normalize() ;
|
||||
chainC.AddCurve( int( vBiPnt.size()), ptL2s, vtDir2, ptL2e, vtDir2) ;
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG
|
||||
PtrOwner<ICurveLine> pMyLine( CreateCurveLine()) ;
|
||||
pMyLine->Set( ptL1s, ptL1e) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( pMyLine))) ;
|
||||
VT_CO.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ;
|
||||
pMyLine.Set( CreateCurveLine()) ;
|
||||
pMyLine->Set( ptL2s, ptL2e) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( pMyLine))) ;
|
||||
VT_CO.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_PROCESS_SQUARE_DEBUG
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( cavTstm.GetvStm()[0]->Clone())) ;
|
||||
VT_GO.back()->ToLoc( frGrid) ;
|
||||
VT_CO.emplace_back( Color( 0., 255., 0., 1.)) ;
|
||||
SaveGeoObj( VT_GO, VT_CO, Process_Square_Debug_File_Name) ;
|
||||
#endif
|
||||
#if ENABLE_BISECTION_DEBUG
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( cavTstm.GetvStm()[0]->Clone())) ;
|
||||
VT_GO.back()->ToLoc( frGrid) ;
|
||||
VT_CO.emplace_back( Color( 0., 255., 0., 1.)) ;
|
||||
SaveGeoObj( VT_GO, VT_CO, Bisection_Debug_File_Name) ;
|
||||
#endif
|
||||
|
||||
// Recupero i contorni
|
||||
INTVECTOR vnId ;
|
||||
while ( chainC.GetChainFromNear( ORIG, false, vnId)) {
|
||||
@@ -292,7 +793,6 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
Point3d ptCurr = vBiPnt[vnId[i]-1].second ;
|
||||
crvCompo.AddLine( ptCurr) ;
|
||||
}
|
||||
// la chiudo
|
||||
crvCompo.Close() ;
|
||||
// elimino le parti allineate
|
||||
crvCompo.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
||||
@@ -300,22 +800,61 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
double dCmpArea ;
|
||||
if ( ! crvCompo.GetAreaXY( dCmpArea) || ( dCmpArea < 0 && abs( dCmpArea) < 2 * dStep * dStep))
|
||||
continue ;
|
||||
// per test mettere a 1
|
||||
#if 0
|
||||
vPL.emplace_back( PolyLine()) ;
|
||||
crvCompo.ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL.back()) ;
|
||||
#else
|
||||
// eseguo offset a sinistra pari allo step
|
||||
OffsetCurve offsCompo ;
|
||||
offsCompo.Make( &crvCompo, -( dRad - 2 * EPS_SMALL), ICurve::OFF_CHAMFER) ;
|
||||
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ;
|
||||
if ( ! IsNull( pCrvOffset)) {
|
||||
vPL.emplace_back( PolyLine()) ;
|
||||
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL.back()) ;
|
||||
}
|
||||
#endif
|
||||
// memorizzo i risultati ottenuti
|
||||
vPL.emplace_back( PolyLine()) ;
|
||||
crvCompo.ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL.back()) ;
|
||||
}
|
||||
|
||||
// le polyline ricavate, definendo dei contorni di regioni, sono chiuse ; cerco di ricostruire gli spigoli vivi
|
||||
POLYLINEVECTOR vPL_Sharped( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL_Sharped.size()) ; ++ i)
|
||||
vPL_Sharped[i] = vPL[i] ;
|
||||
if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false))
|
||||
swap( vPL_Sharped, vPL) ;
|
||||
|
||||
// se vettore di PolyLine vuoto, non faccio nulla
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
|
||||
// se non ho impostato un utensile, devo effettuare un contro-offset
|
||||
if ( ! bTool) {
|
||||
ICURVEPOVECTOR vpOwCrv ; vpOwCrv.reserve( vPL.size()) ;
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vpOwCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
vpCrv.emplace_back( vpOwCrv.back()) ;
|
||||
}
|
||||
// calcolo l'Offset
|
||||
ICURVEPOVECTOR vpCrvOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vpCrvOffs, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
// resituisco le PolyLine
|
||||
POLYLINEVECTOR vPL_Offs ; vPL_Offs.reserve( vpCrvOffs.size()) ;
|
||||
for ( auto& pCrv : vpCrvOffs) {
|
||||
if ( pCrv != nullptr && pCrv->IsValid()) {
|
||||
PolyLine myPolyLine ;
|
||||
pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||
vPL_Offs.emplace_back( myPolyLine) ;
|
||||
}
|
||||
}
|
||||
swap( vPL_Offs, vPL) ;
|
||||
}
|
||||
|
||||
#if ENABLE_BISECTION_DEBUG
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( cavTstm.GetvStm()[0]->Clone())) ;
|
||||
VT_GO.back()->ToLoc( frGrid) ;
|
||||
VT_CO.emplace_back( GRAY) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
||||
pCompo->FromPolyLine( vPL[i]) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( pCompo->Clone())) ;
|
||||
VT_CO.emplace_back( WHITE) ;
|
||||
}
|
||||
SaveGeoObj( VT_GO, VT_CO, Bisection_Debug_File_Name) ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -388,7 +927,7 @@ CAvSilhouetteSurfTm( const ISurfTriMesh& Stm, const Plane3d& plPlane, double dTo
|
||||
|
||||
// calcolo della silhouette con il metodo MarchingSquares
|
||||
double dLevel = dLevelOffs ;
|
||||
if ( ! MarchingSquares( vdGrid, nStepX, nStepY, dTol, dRad, dLevel, cavTstm, frGrid, vPL))
|
||||
if ( ! MarchingSquares( vdGrid, nStepX, nStepY, dTol, dRad, 0., dLevel, cavTstm, frGrid, -1., -1., false, vPL))
|
||||
return false ;
|
||||
// riporto nella corretta posizione le curve trovate
|
||||
for ( auto& PL : vPL)
|
||||
@@ -409,7 +948,7 @@ CreateCAvParSilhouettesSurfTm( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
CAvParSilhouettesSurfTm::CAvParSilhouettesSurfTm( void)
|
||||
: m_dTol( 100 * EPS_SMALL), m_nStepX( 0), m_nStepY( 0), m_dRad( m_dTol), m_dLevelOffs( 0), m_bGridOk( false)
|
||||
: m_dTol( 100 * EPS_SMALL), m_nStepX( 0), m_nStepY( 0), m_dRad( m_dTol), m_dOffsR( 0), m_dLevelOffs( 0), m_bGridOk( false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -421,11 +960,43 @@ CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& f
|
||||
m_frGrid = frPlanes ;
|
||||
m_dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||
m_dRad = SQRT1_2 * m_dTol ;
|
||||
m_dSharpedTol = ANG_TOL_STD_DEG ;
|
||||
m_dOffsR = 0. ;
|
||||
m_nStepX = 0 ;
|
||||
m_nStepY = 0 ;
|
||||
m_dDimZ = 0 ;
|
||||
m_dLevelOffs = 0 ;
|
||||
m_dCornRad = 0. ;
|
||||
m_dMaxMat = INFINITO ;
|
||||
m_dOffsR = 0. ;
|
||||
m_dSideAng = 0. ;
|
||||
m_dMaxDepth = 0. ;
|
||||
m_bGridOk = false ;
|
||||
m_bTool = false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol,
|
||||
double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR,
|
||||
double dMaxDepth)
|
||||
{
|
||||
m_vpStm = vpStm ;
|
||||
m_frGrid = frPlanes ;
|
||||
m_dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||
m_nStepX = 0 ;
|
||||
m_nStepY = 0 ;
|
||||
m_dDimZ = 0 ;
|
||||
m_dLevelOffs = 0 ;
|
||||
m_dRad = dDiam / 2. ;
|
||||
m_dCornRad = dCornRad ;
|
||||
m_dMaxMat = dMaxMat ;
|
||||
m_dOffsR = dOffsR ;
|
||||
m_dSideAng = dSideAng ;
|
||||
m_dMaxDepth = dMaxDepth ;
|
||||
m_bGridOk = false ;
|
||||
m_bTool = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -433,7 +1004,7 @@ CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& f
|
||||
bool
|
||||
CAvParSilhouettesSurfTm::Prepare( void)
|
||||
{
|
||||
// ingombro delle superfici nel riferimento dei piani
|
||||
// ingombro delle superfici nel riferimento dei piani
|
||||
BBox3d b3All ;
|
||||
Frame3d frInv = GetInvert( m_frGrid) ;
|
||||
for ( auto pStm : m_vpStm) {
|
||||
@@ -442,16 +1013,41 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
return false ;
|
||||
b3All.Add( b3Surf) ;
|
||||
}
|
||||
// espansione in Z del Box
|
||||
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
|
||||
b3All.Expand( 0., 0., EXTRA_Z) ;
|
||||
m_dDimZ = b3All.GetDimZ() ;
|
||||
|
||||
// set utensile corrente per calcolo delle collisioni
|
||||
double dExtraXY = m_dRad + m_dOffsR ;
|
||||
if ( m_dSideAng < EPS_ANG_SMALL)
|
||||
m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
else {
|
||||
double dDeltaRad ;
|
||||
double dSideAngRad = m_dSideAng * DEGTORAD ;
|
||||
if ( m_dSideAng > 0) {
|
||||
if ( m_dCornRad < EPS_SMALL)
|
||||
dDeltaRad = m_dMaxMat * tan( dSideAngRad) ;
|
||||
else
|
||||
dDeltaRad = ( m_dCornRad * cos( dSideAngRad) +
|
||||
( m_dMaxMat + m_dCornRad * ( sin( dSideAngRad) - 1)) * tan( dSideAngRad)) ;
|
||||
}
|
||||
else
|
||||
dDeltaRad = tan( dSideAngRad) * m_dMaxMat ;
|
||||
|
||||
double dStemRad = m_dRad + dDeltaRad ;
|
||||
double dTipRad = m_dRad ;
|
||||
dExtraXY = dStemRad + m_dOffsR ;
|
||||
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
}
|
||||
|
||||
// calcolo dati della griglia
|
||||
const double EXTRA_XY = 1.5 * m_dTol ;
|
||||
const double EXTRA_Z = 10 * m_dTol ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
|
||||
const double EXTRA_XY = ( m_bTool ? dExtraXY + 2. : 1.5 * m_dTol) ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, 0.) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
m_dDimZ = b3All.GetDimZ() ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
|
||||
// calcolo dei punti della griglia (sul top del cilindro)
|
||||
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
|
||||
@@ -463,9 +1059,7 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
}
|
||||
}
|
||||
|
||||
// esecuzione della verifica
|
||||
if ( ! m_cavTstm.SetStdTool( m_dDimZ, m_dRad, 0))
|
||||
return false ;
|
||||
// esecuzione verifica della collisione
|
||||
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
|
||||
return false ;
|
||||
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
|
||||
@@ -483,6 +1077,20 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
}
|
||||
}
|
||||
|
||||
// disegno la griglia colorando i punti in base alle altezze trovate
|
||||
#if ENABLE_COLORED_GRID_DEBUG
|
||||
vector<IGeoObj*> VT_GO ;
|
||||
vector<Color> VT_CO ;
|
||||
for ( int i = 0 ; i < int( vPntM.size()) ; ++ i) {
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
myPt->Set( vPntM[i].first) ;
|
||||
double myAngle = 240 + 120 * ( vPntM[i].second / m_dDimZ) ;
|
||||
VT_GO.emplace_back( static_cast<IGeoObj*>( Release( myPt))) ;
|
||||
VT_CO.emplace_back( Color( GetColorFromHSV( HSV( myAngle, 1., 1.)))) ;
|
||||
}
|
||||
SaveGeoObj( VT_GO, VT_CO, Colored_Grid_Debug_File_Name) ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -498,16 +1106,19 @@ CAvParSilhouettesSurfTm::GetSilhouette( double dLevel, POLYLINEVECTOR& vPL)
|
||||
return false ;
|
||||
m_bGridOk = true ;
|
||||
|
||||
// calcolo della silhouette con il metodo MarchingSquares
|
||||
dLevel += m_dLevelOffs ;
|
||||
// controllo se ho impostato un utensile, in caso negativo, la silhouette richiede un contro-offset
|
||||
double dCalcLevel = max( dLevel, 0.) ;
|
||||
if ( ! MarchingSquares( m_vdGrid, m_nStepX, m_nStepY, m_dTol, m_dRad, dCalcLevel, m_cavTstm, m_frGrid, vPL))
|
||||
// calcolo della silhouette con il metodo MarchingSquare
|
||||
if ( ! MarchingSquares( m_vdGrid, m_nStepX, m_nStepY, m_dTol, m_dRad, m_dOffsR, dCalcLevel, m_cavTstm, m_frGrid,
|
||||
m_dDimZ, dCalcLevel, m_bTool, vPL))
|
||||
return false ;
|
||||
|
||||
// riporto nella corretta posizione le curve trovate
|
||||
for ( auto& PL : vPL) {
|
||||
if ( dLevel < dCalcLevel - EPS_SMALL)
|
||||
PL.Translate( Vector3d{ 0, 0, dLevel - dCalcLevel}) ;
|
||||
PL.ToGlob( m_frGrid) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+14
-1
@@ -14,31 +14,44 @@
|
||||
#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) ;
|
||||
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 ;
|
||||
} ;
|
||||
+316
-19
@@ -24,6 +24,7 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const int STEP_PE = 50 ;
|
||||
const double MAX_MOVE = 20000 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICAvToolSurfTm*
|
||||
@@ -80,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 ;
|
||||
@@ -130,7 +131,7 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se riferimento di movimento già presente
|
||||
// Se riferimento di movimento già presente
|
||||
if ( m_frMove.IsValid()) {
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
@@ -158,6 +159,47 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
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)
|
||||
@@ -168,7 +210,7 @@ CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vecto
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
@@ -239,7 +281,7 @@ CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vecto
|
||||
bool
|
||||
CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
||||
{
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti da verificare
|
||||
@@ -279,7 +321,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Controllo la tolleranza lineare (se negativa non vanno fatti controlli sui punti medi)
|
||||
@@ -359,11 +401,93 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
||||
{
|
||||
// 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é
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti
|
||||
@@ -405,6 +529,40 @@ 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,
|
||||
@@ -443,20 +601,100 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
double
|
||||
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, vtMove) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * vtMove ;
|
||||
vtTriaN = Tria.GetN() ;
|
||||
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() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
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()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -485,7 +723,8 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d&
|
||||
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 ;
|
||||
@@ -509,6 +748,64 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d&
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -519,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 ;
|
||||
|
||||
@@ -34,11 +34,29 @@ 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, 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 :
|
||||
@@ -47,9 +65,12 @@ class CAvToolSurfTm : public ICAvToolSurfTm
|
||||
|
||||
private :
|
||||
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 ;
|
||||
bool PrepareHashGrid( void) ;
|
||||
|
||||
+1891
-1158
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
|
||||
|
||||
+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)
|
||||
|
||||
+220
-73
@@ -298,12 +298,71 @@ CurveGetAreaXY( const ICurve& crvC, double& dArea)
|
||||
// verifico sia chiusa
|
||||
if ( ! crvC.IsClosed())
|
||||
return false ;
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL) ;
|
||||
// calcolo l'area
|
||||
|
||||
double dAreaXY = 0 ;
|
||||
PL.GetAreaXY( dAreaXY) ;
|
||||
int nType = crvC.GetType() ;
|
||||
if ( nType == CRV_ARC) {
|
||||
// se circonferenza
|
||||
const CurveArc* pArc = GetBasicCurveArc( &crvC) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
double dAng = pArc->GetAngCenter() ;
|
||||
if ( abs( abs( dAng) - ANG_FULL) > EPS_ANG_SMALL)
|
||||
return false ;
|
||||
double dRad = pArc->GetRadius() ;
|
||||
Vector3d vtN = pArc->GetNormVersor() ;
|
||||
dAreaXY = PIGRECO * dRad * dRad * vtN * Z_AX * ( dAng > 0 ? 1 : -1) ;
|
||||
}
|
||||
else if ( nType == CRV_BEZIER) {
|
||||
// se Bezier approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL) ;
|
||||
PL.GetAreaXY( dAreaXY) ;
|
||||
}
|
||||
else if ( nType == CRV_COMPO) {
|
||||
// se composita calcolo il contributo di ogni sottotratto
|
||||
const CurveComposite* pCompo = GetBasicCurveComposite( &crvC) ;
|
||||
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) {
|
||||
const ICurve* pCrv = pCompo->GetCurve( i) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
if ( pCrv->GetType() == CRV_LINE) {
|
||||
Point3d ptS, ptE ;
|
||||
if ( ! pCrv->GetStartPoint( ptS) || ! pCrv->GetEndPoint( ptE))
|
||||
return false ;
|
||||
dAreaXY += ( ptS.x - ptE.x) * ( ptS.y + ptE.y) ;
|
||||
}
|
||||
else if ( pCrv->GetType() == CRV_ARC) {
|
||||
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
Point3d ptS, ptE ;
|
||||
if ( ! pArc->GetStartPoint( ptS) || ! pArc->GetEndPoint( ptE))
|
||||
return false ;
|
||||
// recupero i dati dell'arco
|
||||
Point3d ptC = pArc->GetCenter() ;
|
||||
Vector3d vtN = pArc->GetNormVersor() ;
|
||||
double dRad = pArc->GetRadius() ;
|
||||
double dAng = pArc->GetAngCenter() ;
|
||||
dAreaXY += ( ptS.x - ptC.x) * ( ptS.y + ptC.y) +
|
||||
( ptC.x - ptE.x) * ( ptE.y + ptC.y) +
|
||||
dRad * dRad * dAng * DEGTORAD * vtN * Z_AX ;
|
||||
}
|
||||
else if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
// approssimo la sottocurva con polilinea
|
||||
PolyLine PL ;
|
||||
pCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL) ;
|
||||
Point3d ptS, ptE ;
|
||||
for ( bool bFound = PL.GetFirstLine( ptS, ptE) ; bFound ; bFound = PL.GetNextLine( ptS, ptE)) {
|
||||
dAreaXY += ( ptS.x - ptE.x) * ( ptS.y + ptE.y) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
dAreaXY *= 0.5 ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
|
||||
// restituisco il valore
|
||||
if ( &dArea != nullptr)
|
||||
dArea = dAreaXY ;
|
||||
@@ -454,8 +513,13 @@ CurveToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot)
|
||||
LineToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
|
||||
{
|
||||
// verifico sia una linea
|
||||
const CurveLine* pCrvLine = GetBasicCurveLine( pCrv) ;
|
||||
if ( pCrvLine == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
|
||||
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
|
||||
pCrvBezier->Init( nDeg, true) ;
|
||||
@@ -501,7 +565,7 @@ ArcToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
|
||||
nParts = max( nParts, 2) ;
|
||||
for ( int i = 0 ; i < nParts ; ++ i) {
|
||||
// copio l'arco originale
|
||||
CurveArc cArc = *pArc ;
|
||||
CurveArc cArc = *GetBasicCurveArc(pArc->Clone()) ;
|
||||
// lo limito alla parte di interesse
|
||||
cArc.TrimStartEndAtParam( i / double( nParts), ( i + 1) / double( nParts)) ;
|
||||
// creo la curva di Bezier equivalente
|
||||
@@ -525,8 +589,13 @@ ArcToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
CompositeToBezierCurve( const ICurveComposite* pCC, int nDeg, bool bMakeRatOrNot)
|
||||
CompositeToBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot)
|
||||
{
|
||||
// verifico sia una composita
|
||||
const CurveComposite* pCC = GetBasicCurveComposite( pCrv) ;
|
||||
if ( pCC == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// converto tutte le curve in bezier razionali di grado 2
|
||||
PtrOwner<ICurveComposite> pCCBezier( CreateCurveComposite()) ;
|
||||
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
|
||||
@@ -561,10 +630,15 @@ CompositeToBezierCurve( const ICurveComposite* pCC, int nDeg, bool bMakeRatOrNot
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, double dTol)
|
||||
EditBezierCurve( const ICurve* pCrv, int nDeg, bool bMakeRatOrNot, double dTol)
|
||||
{
|
||||
// se nDeg == -1 allora viene mantenuto il grado della curva originale
|
||||
|
||||
// verifico sia una bezier
|
||||
const CurveBezier* pCrvBezier = GetBasicCurveBezier( pCrv) ;
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
if( nDeg == 2 || nDeg == 1)
|
||||
return nullptr ;
|
||||
|
||||
@@ -626,6 +700,7 @@ EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, d
|
||||
return Release( pCrvNew) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
||||
{
|
||||
@@ -677,6 +752,7 @@ BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
||||
return Release( pNewBezier) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
|
||||
{
|
||||
@@ -828,8 +904,13 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
ApproxBezierWithCubics(const ICurve* pCrv, double dTol)
|
||||
{
|
||||
// verifico sia una bezier
|
||||
const CurveBezier* pCrvBezier = GetBasicCurveBezier( pCrv) ;
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// cerco di stimare quanti cambi di concavità ho
|
||||
// tiro una linea tra il primo punto di controllo e l'ultimo e poi scorro gli altri punti di controllo
|
||||
// controllando quante volte salto da un lato all'altro della linea
|
||||
@@ -861,7 +942,7 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
PtrOwner<CurveLine> pCL2( CreateBasicCurveLine()) ;
|
||||
pCL2->Set( ptEnd, ptAux2) ;
|
||||
IntersLineLine ill( *pCL1, *pCL2, false) ;
|
||||
if( ill.GetNumInters() != 0) {
|
||||
if ( ill.GetNumInters() != 0) {
|
||||
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||
ptCen = iccInfo.IciA[0].ptI ;
|
||||
double dDist1 = Dist( ptStart, ptCen) ;
|
||||
@@ -871,7 +952,7 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
cArc.SetC2PN( ptCen, ptStart, ptEnd, plPLane.GetVersN()) ;
|
||||
// controllo se il raggio della circonferenza risultante coincide con quello calcolato prima
|
||||
// impongo inoltre che l'angolo al centro sia minore di 90 gradi
|
||||
if( abs( cArc.GetRadius() - dDist1) < EPS_SMALL && cArc.GetAngCenter() < 90 + EPS_SMALL)
|
||||
if ( abs( cArc.GetRadius() - dDist1) < EPS_SMALL && cArc.GetAngCenter() < 90 + EPS_SMALL)
|
||||
bIsArc = true ;
|
||||
}
|
||||
}
|
||||
@@ -880,22 +961,22 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
int nSidePrec = -2 ;
|
||||
int nCross = 0 ;
|
||||
// se non ho un arco cerco di capire se ho cambi di concavità
|
||||
if( ! bIsArc) {
|
||||
for( int i = 1 ; i < pCrvBezier->GetDegree() - 1; ++i) {
|
||||
if ( ! bIsArc) {
|
||||
for ( int i = 1 ; i < pCrvBezier->GetDegree() - 1; ++i) {
|
||||
ptCtrl = pCrvBezier->GetControlPoint( i) ;
|
||||
DistPointCurve dpc( ptCtrl, *pCL) ;
|
||||
int nSide = -2 ;
|
||||
dpc.GetSideAtMinDistPoint( 0, vtN, nSide) ;
|
||||
if ( i > 0 && nSide * nSidePrec < 1)
|
||||
++nCross ;
|
||||
if( nSide != 0)
|
||||
if ( nSide != 0)
|
||||
nSidePrec = nSide ;
|
||||
}
|
||||
}
|
||||
// determino in quanti tratti spezzare la curva originale guardando il grado e i cambi di concavità
|
||||
int nParts = nCross > nDeg / 2 ? nCross : nDeg / 2 + 1 ;
|
||||
bool bOneIsEnough = false ;
|
||||
if( ((nDeg == 2 || nDeg == 3) && ! bRat) || bIsArc) {
|
||||
if ((( nDeg == 2 || nDeg == 3) && ! bRat) || bIsArc) {
|
||||
nParts = 1 ;
|
||||
bOneIsEnough = true ;
|
||||
}
|
||||
@@ -909,11 +990,11 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
||||
pCrvPart->TrimStartEndAtParam( double( nParts - 1) / nParts, 1) ;
|
||||
PtrOwner<ICurveBezier> pCrvCubic ;
|
||||
if( ! bIsArc)
|
||||
if ( ! bIsArc)
|
||||
pCrvCubic.Set( ApproxCurveBezierWithSingleCubic( pCrvPart)) ;
|
||||
else {
|
||||
pCrvCubic.Set( ApproxArcCurveBezierWithSingleCubic( pCrvPart, ptCen)) ;
|
||||
if( IsNull( pCrvCubic)) {
|
||||
if ( IsNull( pCrvCubic)) {
|
||||
// se fallisce allora riprovo usando più di una bezier
|
||||
bIsArc = false ;
|
||||
bOneIsEnough = false ;
|
||||
@@ -923,17 +1004,17 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
}
|
||||
}
|
||||
CalcBezierApproxError( pCrvPart, pCrvCubic, dErr) ;
|
||||
if( dErr > dTol && ! bOneIsEnough)
|
||||
if ( dErr > dTol && ! bOneIsEnough)
|
||||
nParts += 2 ;
|
||||
else {
|
||||
pCC->AddCurve( Release( pCrvCubic)) ;
|
||||
if( bOneIsEnough)
|
||||
if ( bOneIsEnough)
|
||||
break ;
|
||||
}
|
||||
++ nCount ;
|
||||
}
|
||||
|
||||
if( nCount < 100) {
|
||||
if ( nCount < 100) {
|
||||
// approssimo annche tutti gli altri tratti con una cubica
|
||||
for ( int i = nParts - 1 ; i > 0 ; --i) {
|
||||
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
||||
@@ -951,8 +1032,13 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez)
|
||||
ApproxCurveBezierWithSingleCubic( const ICurve* pCrv)
|
||||
{
|
||||
// verifico sia una bezier
|
||||
const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ;
|
||||
if ( pCrvBez == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
Point3d ptStart, ptEnd ;
|
||||
pCrvBez->GetStartPoint( ptStart) ;
|
||||
pCrvBez->GetEndPoint( ptEnd) ;
|
||||
@@ -981,20 +1067,25 @@ ApproxCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d& ptCen)
|
||||
ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen)
|
||||
{
|
||||
// verifico sia una bezier
|
||||
const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ;
|
||||
if ( pCrvBez == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// converto una curva di bezier che definisce un arco perfetto di circonferenza
|
||||
// dato il centro( della circonferenza), inizio e fine
|
||||
// N.B. : per archi con angolo al centro < 90
|
||||
PtrOwner<ICurveBezier> pCrvCubic( CreateCurveBezier()) ;
|
||||
int nDeg = pCrvBez->GetDegree() ;
|
||||
bool bRat = pCrvBez->IsRational() ;
|
||||
if( nDeg != 2 || ! bRat)
|
||||
if ( nDeg != 2 || ! bRat)
|
||||
return nullptr ;
|
||||
|
||||
Point3d ptStart = pCrvBez->GetControlPoint( 0) ;
|
||||
Point3d ptEnd = pCrvBez->GetControlPoint( 2) ;
|
||||
if( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL * 50))
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL * 50))
|
||||
return nullptr ;
|
||||
nDeg = 3 ;
|
||||
bRat = false ;
|
||||
@@ -1007,9 +1098,9 @@ ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d&
|
||||
double ay = ptStart.y - ptCen.y ;
|
||||
double bx = ptEnd.x - ptCen.x ;
|
||||
double by = ptEnd.y - ptCen.y ;
|
||||
double q1 = pow( ax, 2) + pow( ay, 2) ;
|
||||
double q1 = ax * ax + ay * ay ;
|
||||
double q2 = q1 + ax * bx + ay * by ;
|
||||
double k2 = 4./3 * ( sqrt( 2 * q1 * q2) - q2) / ( ax * by - ay * bx) ;
|
||||
double k2 = 4. / 3 * ( sqrt( 2 * q1 * q2) - q2) / ( ax * by - ay * bx) ;
|
||||
Point3d ptCtrl1, ptCtrl2 ;
|
||||
ptCtrl1.x = ptStart.x - k2 * ay ;
|
||||
ptCtrl1.y = ptStart.y + k2 * ax ;
|
||||
@@ -1025,7 +1116,9 @@ ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d&
|
||||
ICurve*
|
||||
ApproxCurveWithBezier( const ICurve*, double dTol)
|
||||
{
|
||||
// interpolazione di punti con una curva bezier
|
||||
// campiono punti lungo la curva e poi li interpolo
|
||||
|
||||
// oppure faccio la fat curve e poi calcolo una bezier che stia all'interno di quella regione
|
||||
|
||||
PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ;
|
||||
return Release( pCC) ;
|
||||
@@ -1040,7 +1133,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dTol)
|
||||
// scelgo il parametro associato ad ogni punto in modo che rispecchi la distanza tra i punti
|
||||
|
||||
int nPoints = vPnt.size() ;
|
||||
if( nPoints < 4)
|
||||
if ( nPoints < 4)
|
||||
return nullptr ;
|
||||
int nDeg = 3 ;
|
||||
DBLVECTOR vLen ;
|
||||
@@ -1110,15 +1203,15 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dTol)
|
||||
static bool
|
||||
FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
|
||||
{
|
||||
if( dU < 0)
|
||||
if ( dU < 0)
|
||||
return false ;
|
||||
else if( dU < EPS_ZERO) {
|
||||
else if ( dU < EPS_ZERO) {
|
||||
nSpan = nDeg ;
|
||||
return true ;
|
||||
}
|
||||
// trovo a quale span appartiene il parametro dU
|
||||
int nKnots = int( vKnots.size()) ;
|
||||
if( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
|
||||
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
|
||||
nSpan = nKnots - 1 ;
|
||||
return true ;
|
||||
}
|
||||
@@ -1143,7 +1236,7 @@ static bool
|
||||
CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
||||
{
|
||||
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
|
||||
if( vBasis.size() != nDeg + 1)
|
||||
if ( vBasis.size() != nDeg + 1)
|
||||
return false ;
|
||||
|
||||
int nSpan = 0 ;
|
||||
@@ -1170,7 +1263,7 @@ CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
||||
bool
|
||||
CalcBezierApproxError( const ICurveBezier* pCrvOri, const ICurveBezier* pCrvNew, double& dErr, int nPoints)
|
||||
{
|
||||
if( pCrvOri->GetType() != CRV_BEZIER || pCrvNew->GetType() != CRV_BEZIER)
|
||||
if ( pCrvOri->GetType() != CRV_BEZIER || pCrvNew->GetType() != CRV_BEZIER)
|
||||
return false ;
|
||||
|
||||
// controllo l'errore effettivo campionando più finemente
|
||||
@@ -1185,7 +1278,7 @@ CalcBezierApproxError( const ICurveBezier* pCrvOri, const ICurveBezier* pCrvNew,
|
||||
pCrvNew->GetParamAtLength( double (i) / nPoints * dLenNew, dParNew) ;
|
||||
pCrvNew->GetPointD1D2(dParNew, ICurve::FROM_MINUS, ptNew) ; ;
|
||||
double dErrLoc = Dist( ptOri, ptNew) ;
|
||||
if( dErrLoc > dErr)
|
||||
if ( dErrLoc > dErr)
|
||||
dErr = dErrLoc ;
|
||||
}
|
||||
|
||||
@@ -1201,7 +1294,7 @@ CurveToNoArcsCurve( const ICurve* pCrv)
|
||||
return nullptr ;
|
||||
// se arco, devo trasformarlo in curva di Bezier (semplice o composta)
|
||||
if ( pCrv->GetType() == CRV_ARC) {
|
||||
return ArcToBezierCurve( pCrv) ;
|
||||
return ArcToBezierCurve( GetCurveArc(pCrv)) ;
|
||||
}
|
||||
// se curva composita, devo trasformarla in composita senza archi
|
||||
else if ( pCrv->GetType() == CRV_COMPO) {
|
||||
@@ -1252,7 +1345,7 @@ CurveToArcsPerpExtrCurve( const ICurve* pCrv, double dLinTol, double dAngTolDeg)
|
||||
bool
|
||||
NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
{
|
||||
// se con nodi extra
|
||||
// se con nodi extra
|
||||
if ( cnData.bExtraKnotes) {
|
||||
int nKnotesNbr = int( cnData.vU.size()) ;
|
||||
if ( nKnotesNbr < 4)
|
||||
@@ -1266,8 +1359,8 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
// se periodica
|
||||
if ( cnData.bPeriodic || ! cnData.bClamped) {
|
||||
bool bAlreadyChecked = false ;
|
||||
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
|
||||
// wrap della curva su se stessa
|
||||
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
|
||||
// wrap della curva su se stessa
|
||||
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
|
||||
bool bRepeated = true ;
|
||||
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
|
||||
@@ -1278,30 +1371,30 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
}
|
||||
bool bFirstAddedAtEnd = false ;
|
||||
if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){
|
||||
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
|
||||
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
|
||||
DBLVECTOR vU = cnData.vU ;
|
||||
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
|
||||
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
|
||||
if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) {
|
||||
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
|
||||
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
|
||||
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
|
||||
bFirstAddedAtEnd = true ;
|
||||
cnData.vCP.push_back( cnData.vCP[0]) ;
|
||||
if ( cnData.bRat)
|
||||
cnData.vW.push_back( cnData.vW[0]) ;
|
||||
}
|
||||
// devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo siano alla fine del vettore dei nodi
|
||||
// devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo siano alla fine del vettore dei nodi
|
||||
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
|
||||
// controllo eventualmente anche i nodi extra
|
||||
// se ne ho due in più ne tolgo uno in cima e uno in fondo
|
||||
// controllo eventualmente anche i nodi extra
|
||||
// se ne ho due in più ne tolgo uno in cima e uno in fondo
|
||||
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
|
||||
}
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) {
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
||||
}
|
||||
}
|
||||
// controllo se il vettore dei nodi ha la giusta molteplicità all'inizio e alla fine, sennò ha comunque bisogno di essere resa non periodica
|
||||
// controllo se il vettore dei nodi ha la giusta molteplicità all'inizio e alla fine, sennò ha comunque bisogno di essere resa non periodica
|
||||
double dU0 = cnData.vU[0] ;
|
||||
double dULast = cnData.vU.back() ;
|
||||
bool bSame = true ;
|
||||
@@ -1314,27 +1407,27 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
return true ;
|
||||
}
|
||||
else {
|
||||
// aggiungo i punti ripetuti ( controllando se il primo l'ho già aggiunto o c'è già)
|
||||
// aggiungo i punti ripetuti ( controllando se il primo l'ho già aggiunto o c'è già)
|
||||
bFirstAddedAtEnd = bFirstAddedAtEnd || AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ;
|
||||
for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) {
|
||||
cnData.vCP.push_back( cnData.vCP[i]) ;
|
||||
if ( cnData.bRat)
|
||||
cnData.vW.push_back( cnData.vW[i]) ;
|
||||
}
|
||||
// recupero il vettore dei nodi
|
||||
// recupero il vettore dei nodi
|
||||
cnData.vU = vU ;
|
||||
// verifico se ho nodi extra
|
||||
// verifico se ho nodi extra
|
||||
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
|
||||
// significa che ci sono due nodi extra:
|
||||
// se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli
|
||||
// significa che ci sono due nodi extra:
|
||||
// se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli
|
||||
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 2, cnData.vU.end()) ;
|
||||
}
|
||||
// sennò ne tolgo uno all'inizio e uno alla fine
|
||||
// sennò ne tolgo uno all'inizio e uno alla fine
|
||||
else
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
|
||||
}
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
// se ne ho solo uno in più lo tolgo in cima
|
||||
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
|
||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
||||
}
|
||||
@@ -1343,7 +1436,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
}
|
||||
|
||||
if ( ! bAlreadyChecked) {
|
||||
// se non ho già controllato guardo se ho già la giusta molteplicità all'inizio e alla fine del vettore dei nodi
|
||||
// se non ho già controllato guardo se ho già la giusta molteplicità all'inizio e alla fine del vettore dei nodi
|
||||
double dU0 = cnData.vU[0] ;
|
||||
double dULast = cnData.vU.back() ;
|
||||
bool bSame = true ;
|
||||
@@ -1357,10 +1450,10 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
}
|
||||
}
|
||||
|
||||
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
|
||||
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
|
||||
bool bCollapsed = true ;
|
||||
Point3d ptFirst = cnData.vCP.front() ;
|
||||
for( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
|
||||
for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
|
||||
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
|
||||
bCollapsed = false ;
|
||||
break ;
|
||||
@@ -1373,10 +1466,10 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
|
||||
// e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1))
|
||||
|
||||
// l'agoritmo per l'inserimento dei nodi l' A5.1 del libro delle Nurbs ( Piegl e Tiller), con qualche modifica
|
||||
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
|
||||
// l'agoritmo per l'inserimento dei nodi l' A5.1 del libro delle Nurbs ( Piegl e Tiller), con qualche modifica
|
||||
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
|
||||
|
||||
// comincio ad aumentare la molteplictià del nodo u_m-p+1
|
||||
// comincio ad aumentare la molteplictià del nodo u_m-p+1
|
||||
int nCP = int( cnData.vCP.size()) ;
|
||||
int nU = nCP + cnData.nDeg - 1 ;
|
||||
int nDeg = cnData.nDeg ;
|
||||
@@ -1579,18 +1672,15 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
return nullptr ;
|
||||
// numero degli intervalli
|
||||
int nInt = nU - 2 * cnData.nDeg + 1 ;
|
||||
// verifico le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro)
|
||||
bool bOk = true ;
|
||||
for ( int i = 1 ; i < cnData.nDeg ; ++ i) {
|
||||
if ( abs( cnData.vU[i] - cnData.vU[0]) >= EPS_ZERO)
|
||||
bOk = false ;
|
||||
// sistemo le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro)
|
||||
for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) {
|
||||
if ( abs( cnData.vU[i] - cnData.vU[cnData.nDeg - 1]) >= EPS_ZERO)
|
||||
const_cast<double&>( cnData.vU[i]) = cnData.vU[cnData.nDeg - 1] ;
|
||||
}
|
||||
for ( int i = 1 ; i < cnData.nDeg ; ++ i) {
|
||||
if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - 1]) >= EPS_ZERO)
|
||||
bOk = false ;
|
||||
for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) {
|
||||
if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - cnData.nDeg]) >= EPS_ZERO)
|
||||
const_cast<double&>( cnData.vU[nU - 1 - i]) = cnData.vU[nU - cnData.nDeg] ;
|
||||
}
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
|
||||
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
|
||||
if ( nInt == 1) {
|
||||
@@ -1936,7 +2026,7 @@ CalcCurveVoronoiDiagram( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nBound)
|
||||
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
|
||||
|
||||
return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ;
|
||||
}
|
||||
|
||||
@@ -1985,13 +2075,14 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids)
|
||||
CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids,
|
||||
bool bMergeOnlySameProps)
|
||||
{
|
||||
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
|
||||
return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ;
|
||||
return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -2017,6 +2108,62 @@ CalcCurveLimitOffset( const ICurve& crvC, double& dOffs)
|
||||
return pVoronoiObj->CalcLimitOffset( 0, bLeft, dOffs) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CalcCurveSingleCurvesOffset( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dOffs)
|
||||
{
|
||||
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
|
||||
return pVoronoiObj->CalcSingleCurvesOffset( vCrvs, dOffs) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs, int nType)
|
||||
{
|
||||
// creo oggetto Voronoi con le curve passate
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return pVoronoiObj->CalcOffset( vCrvs, dOffs, nType) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs,
|
||||
bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps)
|
||||
{
|
||||
// controllo validità delle curve
|
||||
for ( auto& pCrv : vpCrvs) {
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
}
|
||||
// se offset nullo restituisco direttamente le curve
|
||||
if ( abs( dOffs) < EPS_SMALL) {
|
||||
for ( auto& pCrv : vpCrvs) {
|
||||
if ( ! vCrvs.emplace_back( pCrv->Clone()))
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
// creo oggetto Voronoi con le curve passate
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return pVoronoiObj->CalcFatCurve( vCrvs, dOffs, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
ResetCurveVoronoi( const ICurve& crvC)
|
||||
|
||||
+1
-1
@@ -33,5 +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 ICurveBezier* pCrvBez) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
|
||||
+22
-14
@@ -2274,17 +2274,17 @@ CurveBezier::MakeRationalStandardForm( void)
|
||||
{
|
||||
if ( ! m_bRat)
|
||||
return false ;
|
||||
double dW0 = m_vWeCtrl[0] ;
|
||||
double dW0 = m_vWeCtrl.front() ;
|
||||
double dWn = m_vWeCtrl.back() ;
|
||||
if( dW0 > 1- EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
if ( dW0 > 1 - EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
return true ;
|
||||
if( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
if ( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
return false ;
|
||||
|
||||
// formula del Farin
|
||||
// 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 ;
|
||||
m_vWeCtrl[i] *= Pow( dCoeff, i) / dW0 ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -2293,13 +2293,13 @@ CurveBezier::MakeRationalStandardForm( void)
|
||||
bool
|
||||
CurveBezier::MakeNonRational( double dTol)
|
||||
{
|
||||
if( ! m_bRat)
|
||||
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) {
|
||||
if ( abs( m_vWeCtrl[i] - 1) > EPS_SMALL) {
|
||||
bIsActualRat = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -2323,8 +2323,8 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
pNewBez->Init( nDeg, false) ;
|
||||
PNTVECTOR vPntCtrl ;
|
||||
PNTVECTOR vPntSampling ;
|
||||
for ( int p = 0 ; p < nDeg + 1; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ;
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
vPntCtrl.push_back( pt) ;
|
||||
}
|
||||
@@ -2334,8 +2334,8 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
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) ;
|
||||
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)
|
||||
@@ -2353,15 +2353,15 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
// calcolo l'errore di approssimazione sulla curva
|
||||
CalcBezierApproxError( this, pNewBez, dErr) ;
|
||||
bOk = dErr < dTol ;
|
||||
if( bOk) {
|
||||
if ( bOk) {
|
||||
// aggiorno la curva di bezier originale con quella approssimata
|
||||
Init( nDeg, false) ;
|
||||
for( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
|
||||
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
|
||||
}
|
||||
}
|
||||
else if( nDeg < m_nDeg + 4)
|
||||
else if ( nDeg < m_nDeg + 4)
|
||||
goto retry ;
|
||||
}
|
||||
|
||||
@@ -2383,3 +2383,11 @@ CurveBezier::IsALine( void) const
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PNTVECTOR
|
||||
CurveBezier::GetAllControlPoints( void) const
|
||||
{
|
||||
PNTVECTOR vPntCtrl = m_vPtCtrl ;
|
||||
return vPntCtrl ;
|
||||
}
|
||||
@@ -153,6 +153,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
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 ;
|
||||
|
||||
+5
-2
@@ -502,8 +502,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
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, dLinTol)) ;
|
||||
// forzo la spezzatura della curva
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 2 * dLinTol ;
|
||||
}
|
||||
// se la polilinea è formata da 2 punti
|
||||
else if ( PL.GetPointNbr() == 2) {
|
||||
@@ -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 ;
|
||||
|
||||
+65
-32
@@ -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)
|
||||
@@ -375,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 ;
|
||||
@@ -388,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 ;
|
||||
}
|
||||
|
||||
@@ -1778,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 ;
|
||||
}
|
||||
@@ -1825,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()) ;
|
||||
@@ -2989,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) ;
|
||||
@@ -3168,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
|
||||
@@ -3181,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
|
||||
@@ -3264,11 +3305,12 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
if ( ! bPlaneArcs) {
|
||||
ptP1.Scale( frRef, 1, 1, 0) ;
|
||||
ptP2.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
ptC1Fin.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ;
|
||||
bool bCirc = ( AreSamePointEpsilon( ptP1, ptP3, dCurrLinTol)) ;
|
||||
if ( bCirc) {
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
if ( ! bPlaneArcs)
|
||||
@@ -3277,6 +3319,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
|
||||
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() ;
|
||||
@@ -3794,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 ;
|
||||
|
||||
+17
-6
@@ -152,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 ||
|
||||
@@ -197,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)) {
|
||||
@@ -232,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))
|
||||
@@ -264,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) {
|
||||
|
||||
Binary file not shown.
@@ -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>
|
||||
@@ -320,8 +320,9 @@ 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="ProjectCurveSurfBez.cpp" />
|
||||
<ClCompile Include="Quaternion.cpp" />
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||
@@ -344,6 +345,7 @@ 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" />
|
||||
@@ -430,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" />
|
||||
|
||||
@@ -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">
|
||||
@@ -540,15 +540,18 @@
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProjectCurveSurfBez.cpp">
|
||||
<Filter>File di origine\GeoProject</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">
|
||||
@@ -1229,6 +1232,9 @@
|
||||
<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) ;
|
||||
|
||||
+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
@@ -571,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) ;
|
||||
@@ -636,7 +636,7 @@ 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()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+2
-2
@@ -625,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) ;
|
||||
@@ -690,7 +690,7 @@ 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()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+2
-2
@@ -669,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) ;
|
||||
@@ -733,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()) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -253,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(),
|
||||
|
||||
+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
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
+107
-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,10 +45,10 @@ 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) ;
|
||||
@@ -108,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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,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) ;
|
||||
@@ -145,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() ;
|
||||
@@ -162,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 ;
|
||||
|
||||
@@ -174,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) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,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)
|
||||
@@ -217,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) ||
|
||||
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
+149
-25
@@ -16,9 +16,17 @@
|
||||
#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)
|
||||
@@ -52,36 +60,76 @@ IsFillet( const 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 ;
|
||||
}
|
||||
@@ -175,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 ;
|
||||
}
|
||||
|
||||
+1
-3
@@ -16,6 +16,4 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
|
||||
bool IsFillet( const 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) ;
|
||||
+59
-9
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
|
||||
}
|
||||
}
|
||||
m_CrvLst.clear() ;
|
||||
m_ptOffs = P_INVALID ;
|
||||
m_vtOut = V_INVALID ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -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,10 +707,25 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// calcolo offset con Voronoi
|
||||
ICURVEPOVECTOR vOffs ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
|
||||
if ( vOffs.size() == 0) {
|
||||
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
|
||||
double dCorr = ( dDist > 0 ? - VRONI_OFFS_TOL : VRONI_OFFS_TOL) ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist + dCorr, 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 ++)
|
||||
@@ -730,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
|
||||
@@ -811,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)
|
||||
|
||||
+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
|
||||
} ;
|
||||
+3
-3
@@ -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() ;
|
||||
|
||||
+51
-14
@@ -54,7 +54,7 @@ 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)) {
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ 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)) {
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -234,10 +234,10 @@ bool
|
||||
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
||||
{
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
if ( PL.m_lUPoints.size() == 0)
|
||||
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() ;
|
||||
@@ -1085,15 +1085,8 @@ PolyLine::Invert( bool bInvertU)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::Flatten( double dZ)
|
||||
PolyLine::MyRemoveSamePoints( double dToler)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// ciclo su tutti gli elementi per portarli alla Z indicata
|
||||
for ( auto& UPoint : m_lUPoints) {
|
||||
UPoint.first.z = dZ ;
|
||||
}
|
||||
// elimino i punti consecutivi diventati coincidenti (almeno 2)
|
||||
if ( m_lUPoints.size() < 2)
|
||||
return true ;
|
||||
@@ -1104,7 +1097,7 @@ PolyLine::Flatten( double dZ)
|
||||
// mentre esiste un corrente
|
||||
while ( currP != m_lUPoints.end()) {
|
||||
// se coincidono
|
||||
if ( AreSamePointApprox( precP->first, currP->first)) {
|
||||
if ( AreSamePointEpsilon( precP->first, currP->first, dToler)) {
|
||||
// elimino il punto corrente
|
||||
currP = m_lUPoints.erase( currP) ;
|
||||
// il precedente rimane inalterato
|
||||
@@ -1119,6 +1112,50 @@ PolyLine::Flatten( double dZ)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::Flatten( double dZ)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// ciclo su tutti gli elementi per portarli alla Z indicata
|
||||
for ( auto& UPoint : m_lUPoints)
|
||||
UPoint.first.z = dZ ;
|
||||
// elimino i punti consecutivi diventati coincidenti
|
||||
MyRemoveSamePoints() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::FlattenInAutoPlane( double dToler)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// 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 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
|
||||
@@ -1289,7 +1326,7 @@ bool
|
||||
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||
{
|
||||
// se vuota non faccio alcunché
|
||||
if ( m_lUPoints.size() == 0)
|
||||
if ( m_lUPoints.empty())
|
||||
return false ;
|
||||
|
||||
// determino le intersezioni dei lati con il piano
|
||||
|
||||
@@ -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,55 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfBez.cpp Data : 07.05.24 Versione : 2.6e3
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Bezier.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.05.24 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
|
||||
PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
|
||||
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, vtDir, dLinTol, dMaxSegmLen, vPt5ax) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
|
||||
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, gpRef, dLinTol, dMaxSegmLen, vPt5ax) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
|
||||
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, crRef, dLinTol, dMaxSegmLen, vPt5ax) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ISurfTriMesh& tmRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
|
||||
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, tmRef, dLinTol, dMaxSegmLen, vPt5ax) ;
|
||||
}
|
||||
@@ -1,414 +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 "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
|
||||
const double COS_ANG_LIM = 0.0175 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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 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, 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) {
|
||||
// intersezione retta di proiezione con superficie
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
intPLSTM.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) {
|
||||
// calcolo il punto
|
||||
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)) {
|
||||
// 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) {
|
||||
// calcolo il punto
|
||||
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 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, 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)) {
|
||||
// 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) {
|
||||
// calcolo il punto
|
||||
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)) {
|
||||
// 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) {
|
||||
// calcolo il punto
|
||||
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 ;
|
||||
}
|
||||
+32
-667
@@ -95,56 +95,17 @@ ISurfBezier*
|
||||
GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
|
||||
bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &vtExtr == 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 ;
|
||||
//// se richiesta chiusura agli estremi
|
||||
//bool bDoCapEnds = false ;
|
||||
//if ( bCapEnds) {
|
||||
// // verifico che la curva sia chiusa e piatta
|
||||
// Plane3d plPlane ;
|
||||
// double dArea ;
|
||||
// if ( PL.IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) {
|
||||
// // componente dell'estrusione perpendicolare al piano della curva
|
||||
// double dOrthoExtr = plPlane.GetVersN() * vtExtr ;
|
||||
// if ( ( abs( dOrthoExtr) > EPS_SMALL)) {
|
||||
// bDoCapEnds = true ;
|
||||
// // se negativa, inverto il senso del contorno
|
||||
// if ( dOrthoExtr < 0)
|
||||
// PL.Invert() ;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ;
|
||||
// creo e setto la superficie trimesh
|
||||
// creo e setto la superficie di Bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr))
|
||||
return nullptr ;
|
||||
|
||||
//// se da fare, metto i tappi sulle estremità
|
||||
//if ( bDoCapEnds) {
|
||||
// // creo la prima superficie di estremità
|
||||
// SurfTriMesh STM1 ;
|
||||
// if ( ! STM1.CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// // la copio
|
||||
// SurfTriMesh STM2 = STM1 ;
|
||||
// // inverto la prima superficie
|
||||
// STM1.Invert() ;
|
||||
// // traslo la seconda
|
||||
// STM2.Translate( vtExtr) ;
|
||||
|
||||
// ////// SurfCompo?
|
||||
// //// le unisco alla superficie del fianco
|
||||
// //if ( ! pSbz->DoSewing( STM1) || ! pSTM->DoSewing( STM2))
|
||||
// // return nullptr ;
|
||||
//}
|
||||
// restituisco la superficie
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
@@ -201,45 +162,6 @@ GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
//// calcolo la polilinea che approssima la curva
|
||||
//PolyLine PL ;
|
||||
//if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
// return nullptr ;
|
||||
|
||||
//// se richiesta chiusura degli estremi
|
||||
//if ( bCapEnds && ! PL.IsClosed()) { // serve la SURFCOMPO
|
||||
// Vector3d vtAxN = vtAx ;
|
||||
// vtAxN.Normalize() ;
|
||||
// double dPosIni = 0, dPosFin = 0 ;
|
||||
// Point3d ptP ;
|
||||
// // proietto l'ultimo punto sull'asse di rotazione
|
||||
// if ( PL.GetLastPoint( ptP)) {
|
||||
// dPosFin = ( ptP - ptAx) * vtAxN ;
|
||||
// Point3d ptPOnAx = ptAx + dPosFin * vtAxN ;
|
||||
// // se non giace sull'asse, aggiungo il punto proiettato
|
||||
// if ( ! AreSamePointApprox( ptP, ptPOnAx)) {
|
||||
// double dU ;
|
||||
// PL.GetLastU( dU) ;
|
||||
// PL.AddUPoint( ( dU + 1), ptPOnAx) ;
|
||||
// }
|
||||
// }
|
||||
// // inverto la polilinea
|
||||
// PL.Invert() ;
|
||||
// // proietto l'ultimo punto (era il primo) sull'asse di rotazione
|
||||
// if ( PL.GetLastPoint( ptP)) {
|
||||
// dPosIni = ( ptP - ptAx) * vtAxN ;
|
||||
// Point3d ptPOnAx = ptAx + dPosIni * vtAxN ;
|
||||
// // se non giace sull'asse, aggiungo il punto proiettato
|
||||
// if ( ! AreSamePointApprox( ptP, ptPOnAx)) {
|
||||
// double dU ;
|
||||
// PL.GetLastU( dU) ;
|
||||
// PL.AddUPoint( ( dU + 1), ptPOnAx) ;
|
||||
// }
|
||||
// }
|
||||
// // decido se reinvertire la polilinea
|
||||
// if ( dPosFin > dPosIni)
|
||||
// PL.Invert() ;
|
||||
//}
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
@@ -259,392 +181,31 @@ ISurfBezier*
|
||||
GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
// 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 bezier
|
||||
// creo e setto la superficie bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
|
||||
return nullptr ;
|
||||
//// se richiesti caps /// richiede la SurfCompo
|
||||
//if ( bCapEnds) {
|
||||
// // determino se la sezione è chiusa e piatta
|
||||
// Plane3d plPlane ; double dArea ;
|
||||
// bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ;
|
||||
// // determino non sia una semplice rivoluzione
|
||||
// bool bRevolved = ( abs( abs( dAngRotDeg) - ANG_FULL) < EPS_ANG_SMALL && abs( dMove) < EPS_SMALL) ;
|
||||
// // se sezione chiusa e piatta e non rivoluzione, posso aggiungere i tappi
|
||||
// if ( bSectClosedFlat && ! bRevolved) {
|
||||
// // aggiungo il cap sull'inizio
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSTM->DoSewing( *pSci) ;
|
||||
// // aggiungo il cap sulla fine
|
||||
// Vector3d vtMove = vtAx ;
|
||||
// vtMove.Normalize() ;
|
||||
// vtMove *= dMove ;
|
||||
// PL.Translate( vtMove) ;
|
||||
// PL.Rotate( ptAx, vtAx, dAngRotDeg) ;
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSce->Invert() ;
|
||||
// pSTM->DoSewing( *pSce) ;
|
||||
// }
|
||||
//}
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
|
||||
// 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
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
//
|
||||
////-------------------------------------------------------------------------------
|
||||
//static ISurfBezier*
|
||||
//GetSurfBezierSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
//{
|
||||
// // verifico che la linea guida sia piana
|
||||
// Plane3d plGuide ;
|
||||
// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
// // determino se la guida è chiusa
|
||||
// bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// // curve di offset
|
||||
// OffsetCurve OffsCrvR ;
|
||||
// if ( ! OffsCrvR.Make( pGuide, dDimH / 2, ICurve::OFF_FILLET) || OffsCrvR.GetCurveCount() == 0)
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurve> pCrvR( OffsCrvR.GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvR))
|
||||
// return nullptr ;
|
||||
// OffsetCurve OffsCrvL ;
|
||||
// if ( ! OffsCrvL.Make( pGuide, -dDimH / 2, ICurve::OFF_FILLET) || OffsCrvL.GetCurveCount() == 0)
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurve> pCrvL( OffsCrvL.GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvL))
|
||||
// return nullptr ;
|
||||
// // costruisco le parti di superficie
|
||||
// PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
// if ( IsNull( pSrfTop))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
|
||||
// if ( IsNull( pSrfBot))
|
||||
// return nullptr ;
|
||||
// pSrfBot->Translate( -dDimV * vtNorm) ;
|
||||
// pSrfBot->Invert() ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ;
|
||||
// if ( IsNull( pSrfRgt))
|
||||
// return nullptr ;
|
||||
// pSrfRgt->Invert() ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvL, -dDimV * vtNorm, false, dLinTol)) ;
|
||||
// if ( IsNull( pSrfLft))
|
||||
// return nullptr ;
|
||||
// // unisco le parti
|
||||
// PtrOwner<ISurfTriMesh> pSTM( Release( pSrfTop)) ;
|
||||
// pSTM->DoSewing( *pSrfRgt) ;
|
||||
// pSTM->DoSewing( *pSrfLft) ;
|
||||
// pSTM->DoSewing( *pSrfBot) ;
|
||||
// // salvo tolleranza lineare usata e imposto angolo per smooth
|
||||
// pSTM->SetLinearTolerance( dLinTol) ;
|
||||
// pSTM->SetSmoothAngle( 20) ;
|
||||
// // se guida aperta e tappi piatti
|
||||
// if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
|
||||
// // verifico che le due estremità siano chiuse e piatte
|
||||
// POLYLINEVECTOR vPL ;
|
||||
// if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
// return nullptr ;
|
||||
// Plane3d plEnds ; double dArea ;
|
||||
// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// // aggiungo il cap sull'inizio
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
|
||||
// return nullptr ;
|
||||
// pSci->Invert() ;
|
||||
// pSTM->DoSewing( *pSci) ;
|
||||
// // aggiungo il cap sulla fine
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
|
||||
// return nullptr ;
|
||||
// pSce->Invert() ;
|
||||
// pSTM->DoSewing( *pSce) ;
|
||||
// }
|
||||
// // se altrimenti guida aperta e tappi arrotondati
|
||||
// if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) {
|
||||
// // 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))
|
||||
// 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) ;
|
||||
// }
|
||||
// // restituisco la superficie
|
||||
// return Release( pSTM) ;
|
||||
//}
|
||||
//
|
||||
////-------------------------------------------------------------------------------
|
||||
//static ISurfBezier*
|
||||
//GetSurfBezierBeveledRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
//{
|
||||
// // metodo di calcolo impostato da USE_VORONOI
|
||||
//
|
||||
// // verifico che la linea guida sia piana
|
||||
// Plane3d plGuide ;
|
||||
// if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// // assegno la normale del piano
|
||||
// Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
// // determino il punto centrale della sezione
|
||||
// Point3d ptCen ;
|
||||
// pGuide->GetStartPoint( ptCen) ;
|
||||
// ptCen -= dDimV / 2 * vtNorm ;
|
||||
// // determino se la guida è chiusa
|
||||
// bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// // curve di offset
|
||||
// const int NUM_OFFS = 4 ;
|
||||
// OffsetCurve vOffsCrv[NUM_OFFS] ;
|
||||
// double vDist[NUM_OFFS] = { dDimH / 2 - dBevelH, -dDimH / 2 + dBevelH, dDimH / 2, -dDimH / 2} ;
|
||||
// bool bOk = true ;
|
||||
// if ( ! USE_VORONOI) {
|
||||
// future<bool> vRes[NUM_OFFS] ;
|
||||
// for ( int i = 0 ; i < NUM_OFFS ; ++ i)
|
||||
// vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET) ;
|
||||
// bool bOk = true ;
|
||||
// int nFin = 0 ;
|
||||
// while ( nFin < NUM_OFFS) {
|
||||
// for ( int i = 0 ; i < NUM_OFFS ; ++ i) {
|
||||
// if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
// bOk = vRes[i].get() && bOk ;
|
||||
// ++ nFin ;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
|
||||
// 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)
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurve> pCrvR( vOffsCrv[0].GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvR))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurve> pCrvL( vOffsCrv[1].GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvL))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurve> pCrvRb( vOffsCrv[2].GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvRb))
|
||||
// return nullptr ;
|
||||
// pCrvRb->Translate( - dBevelV * vtNorm) ;
|
||||
// PtrOwner<ICurve> pCrvLb( vOffsCrv[3].GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvLb))
|
||||
// return nullptr ;
|
||||
// pCrvLb->Translate( - dBevelV * vtNorm) ;
|
||||
// // costruisco le parti di superficie
|
||||
// PtrOwner<ISurfTriMesh> pSrfTop( GetSurfTriMeshRuled( pCrvR, pCrvL, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
// if ( IsNull( pSrfTop))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfBot( pSrfTop->Clone()) ;
|
||||
// if ( IsNull( pSrfBot))
|
||||
// return nullptr ;
|
||||
// pSrfBot->Translate( -dDimV * vtNorm) ;
|
||||
// pSrfBot->Invert() ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfTopR( GetSurfTriMeshRuled( pCrvRb, pCrvR, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
// if ( IsNull( pSrfTopR))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfBotR( pSrfTopR->Clone()) ;
|
||||
// if ( IsNull( pSrfBotR))
|
||||
// return nullptr ;
|
||||
// pSrfBotR->Mirror( ptCen, vtNorm) ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfTopL( GetSurfTriMeshRuled( pCrvL, pCrvLb, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
// if ( IsNull( pSrfTopL))
|
||||
// return nullptr ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfBotL( pSrfTopL->Clone()) ;
|
||||
// if ( IsNull( pSrfBotL))
|
||||
// return nullptr ;
|
||||
// pSrfBotL->Mirror( ptCen, vtNorm) ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfRgt( GetSurfTriMeshByExtrusion( pCrvRb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
|
||||
// if ( IsNull( pSrfRgt))
|
||||
// return nullptr ;
|
||||
// pSrfRgt->Invert() ;
|
||||
// PtrOwner<ISurfTriMesh> pSrfLft( GetSurfTriMeshByExtrusion( pCrvLb, ( -dDimV + 2 * dBevelV) * vtNorm, false, dLinTol)) ;
|
||||
// if ( IsNull( pSrfLft))
|
||||
// return nullptr ;
|
||||
// // unisco le parti
|
||||
// int nBuckets = max( 4 * ( pSrfRgt->GetVertexSize() + pSrfLft->GetVertexSize()), 1000) ;
|
||||
// StmFromTriangleSoup stmSoup ;
|
||||
// if ( ! stmSoup.Start( nBuckets))
|
||||
// return nullptr ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfTop) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfTopR) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfTopL) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfRgt) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfLft) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfBotR) ;
|
||||
// stmSoup.AddSurfTriMesh( *pSrfBotL) ;
|
||||
// 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()) ;
|
||||
// // 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)
|
||||
// return nullptr ;
|
||||
// Plane3d plEnds ; double dArea ;
|
||||
// if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 50 * EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// // calcolo il cap sull'inizio
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( vPL[0]))
|
||||
// return nullptr ;
|
||||
// pSci->Invert() ;
|
||||
// // calcolo il cap sulla fine
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( vPL[1]))
|
||||
// return nullptr ;
|
||||
// pSce->Invert() ;
|
||||
// // cucio i tappi all'estrusione
|
||||
// if ( ! pSTM->DoSewing( *pSci) || ! pSTM->DoSewing( *pSce))
|
||||
// return nullptr ;
|
||||
// }
|
||||
// // se altrimenti guida aperta e tappi arrotondati
|
||||
// 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))
|
||||
// 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) ;
|
||||
// // completo unione e recupero la superficie risultante
|
||||
// if ( ! stmSoup.End())
|
||||
// return nullptr ;
|
||||
// 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) ;
|
||||
//}
|
||||
//
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfBezierRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
//{
|
||||
// // verifica parametri
|
||||
// if ( pGuide == nullptr || dBevelH > 0.4 * dDimH || dBevelV > 0.4 * dDimV)
|
||||
// return nullptr ;
|
||||
// // determino se sezione squadrata o con smusso
|
||||
// bool bSharp = ( dBevelH < 100 * EPS_SMALL || dBevelV < 100 * EPS_SMALL) ;
|
||||
// // eseguo
|
||||
// if ( bSharp)
|
||||
// return GetSurfBezierSharpRectSwept( dDimH, dDimV, pGuide, nCapType, dLinTol) ;
|
||||
// else
|
||||
// return GetSurfBezierBeveledRectSwept( dDimH, dDimV, dBevelH, dBevelV, pGuide, nCapType, dLinTol) ;
|
||||
//}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
//// determino se la sezione è chiusa
|
||||
//bool bSectClosed = pSect->IsClosed() ;
|
||||
//// determino se la guida è chiusa
|
||||
//bool bGuideClosed = pGuide->IsClosed() ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
// riferimento all'inizio della linea guida
|
||||
Frame3d frStart ;
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
@@ -654,7 +215,7 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch( pGuide->GetType()) {
|
||||
switch ( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
bGuideIsPolyLine = true ;
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
@@ -925,14 +486,10 @@ GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vect
|
||||
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 se la sezione è chiusa
|
||||
//bool bSectClosed = pSect->IsClosed() ;
|
||||
//// determino se la guida è chiusa
|
||||
//bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
bool bRMF = vtAx.IsSmall() ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
// riferimento all'inizio della linea guida
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
@@ -952,7 +509,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
@@ -960,7 +517,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
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_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
@@ -988,18 +545,18 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if( pGuide->GetType() == CRV_LINE)
|
||||
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)
|
||||
// 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())
|
||||
if ( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
@@ -1009,7 +566,7 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
nSpanV = pCrvV->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
|
||||
if ( pSect->GetType() != CRV_BEZIER)
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
@@ -1023,46 +580,44 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
FRAME3DVECTOR vFrames ;
|
||||
if ( bRMF) {
|
||||
RotationMinimizingFrame RMF ;
|
||||
if( bGuideIsPolyLine) {
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RotationXplaneFrame RXF ;
|
||||
if( bGuideIsPolyLine) {
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
//// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
|
||||
// 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) ;
|
||||
pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
|
||||
PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ;
|
||||
@@ -1125,191 +680,6 @@ GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfTriMeshSwept( 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//////////////////////
|
||||
//{
|
||||
// // verifica parametri
|
||||
// if ( pSect == nullptr || pGuide == nullptr)
|
||||
// return nullptr ;
|
||||
//
|
||||
// bool bIsLine = false ;
|
||||
// if ( pGuide->GetType() == CRV_LINE)
|
||||
// bIsLine = true ;
|
||||
// else {
|
||||
// const CurveComposite* pCompo = GetBasicCurveComposite( pGuide) ;
|
||||
// Point3d ptStart, ptEnd ;
|
||||
// if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
|
||||
// bIsLine = true ;
|
||||
// }
|
||||
// // se la guida è piana
|
||||
// Plane3d plGuide ;
|
||||
// if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL))
|
||||
// return GetSurfBezierSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ;
|
||||
//
|
||||
// // altrimenti swept 3d
|
||||
// return GetSurfBezierSwept3d( pSect, pGuide, vtAx, bCapEnds, dLinTol) ;
|
||||
//}
|
||||
//
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfBezierSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, const Vector3d& vtAx,
|
||||
// bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
//{
|
||||
// // verifica dei parametri
|
||||
// if ( pSfrSect == nullptr || pGuide == nullptr)
|
||||
// return nullptr ;
|
||||
//
|
||||
// // predispongo collettore superfici componenti
|
||||
// StmFromTriangleSoup StmSoup ;
|
||||
// StmSoup.Start() ;
|
||||
//
|
||||
// // per ogni loop della superficie, creo una Swept
|
||||
// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
|
||||
// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
|
||||
// // recupero il loop
|
||||
// PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( nC, nL)) ;
|
||||
// if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
|
||||
// return nullptr ;
|
||||
// // creo la Trimesh Swept
|
||||
// PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, vtAx, false, dLinTol)) ;
|
||||
// if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid())
|
||||
// return nullptr ;
|
||||
// // aggiungo la Swept ricavata al risultato finale ( come triangoli )
|
||||
// StmSoup.AddSurfTriMesh( *pStmLoopSwept) ;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Recupero la superficie
|
||||
// if ( ! StmSoup.End())
|
||||
// return nullptr ;
|
||||
// PtrOwner<ISurfTriMesh> pStmSwept( StmSoup.GetSurf()) ;
|
||||
// if ( IsNull( pStmSwept))
|
||||
// return nullptr ;
|
||||
//
|
||||
// // se rischiesta chiusura...
|
||||
// // Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa
|
||||
// if ( bCapEnds && ! pGuide->IsClosed()) {
|
||||
// // recupero i loop all'inizio (dalla regione e apportunamente approssimati)
|
||||
// POLYLINEVECTOR vPLi ;
|
||||
// for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
|
||||
// for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
|
||||
// vPLi.emplace_back() ;
|
||||
// if ( ! pSfrSect->ApproxLoopWithLines( nC, nL, dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLi.back()))
|
||||
// return nullptr ;
|
||||
// }
|
||||
// }
|
||||
// // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
|
||||
// PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
// if ( ! pSci->CreateByRegion( vPLi))
|
||||
// return nullptr ;
|
||||
// pStmSwept->DoSewing( *pSci) ;
|
||||
// // recupero i loops alla fine
|
||||
// POLYLINEVECTOR vPLe ;
|
||||
// if ( ! pStmSwept->GetLoops( vPLe))
|
||||
// return nullptr ;
|
||||
// // creo la superficie alla fine e la attacco
|
||||
// PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
// if ( ! pSce->CreateByRegion( vPLe))
|
||||
// return nullptr ;
|
||||
// // attacco la superficie finale alla swept
|
||||
// pSce->Invert() ;
|
||||
// pStmSwept->DoSewing( *pSce) ;
|
||||
// }
|
||||
// // se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
// double dVol ;
|
||||
// if ( pStmSwept->GetVolume( dVol) && dVol < 0)
|
||||
// pStmSwept->Invert() ;
|
||||
//
|
||||
// return Release( pStmSwept) ;
|
||||
//}
|
||||
//
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfBezierTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
//{
|
||||
// // verifica parametri
|
||||
// if ( pSect == nullptr || pGuide == nullptr)
|
||||
// return nullptr ;
|
||||
// // determino se la sezione è chiusa
|
||||
// bool bSectClosed = pSect->IsClosed() ;
|
||||
// // punto iniziale della sezione e vettore a inizio guida
|
||||
// Point3d ptStart ;
|
||||
// if ( ! pSect->GetStartPoint( ptStart))
|
||||
// return nullptr ;
|
||||
// Point3d ptGuide ;
|
||||
// if ( ! pGuide->GetStartPoint( ptGuide))
|
||||
// return nullptr ;
|
||||
// Vector3d vtDelta = ptStart - ptGuide ;
|
||||
// // calcolo la polilinea che approssima la guida
|
||||
// PolyLine PLG ;
|
||||
// if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
|
||||
// return nullptr ;
|
||||
// // determino se la guida è chiusa
|
||||
// bool bGuideClosed = PLG.IsClosed() ;
|
||||
// // calcolo la superficie
|
||||
// PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSTM))
|
||||
// return nullptr ;
|
||||
// // salvo tolleranza lineare usata
|
||||
// pSTM->SetLinearTolerance( dLinTol) ;
|
||||
// // superficie swept
|
||||
// PtrOwner<ICurve> pPrevCrv ;
|
||||
// Point3d ptP ;
|
||||
// bool bPoint = PLG.GetFirstPoint( ptP) ;
|
||||
// while ( bPoint) {
|
||||
// // nuova curva
|
||||
// PtrOwner<ICurve> pCurrCrv( pSect->Clone()) ;
|
||||
// if ( IsNull( pCurrCrv))
|
||||
// return nullptr ;
|
||||
// pCurrCrv->Translate( ptP - ptStart + vtDelta) ;
|
||||
// // se esiste la curva precedente, costruisco la rigata (di tipo minima distanza)
|
||||
// if ( ! IsNull( pPrevCrv)) {
|
||||
// PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ;
|
||||
// if ( IsNull( pSr))
|
||||
// return nullptr ;
|
||||
// pSTM->DoSewing( *pSr) ;
|
||||
// }
|
||||
// // salvo la curva come prossima precedente
|
||||
// pPrevCrv.Set( pCurrCrv) ;
|
||||
// // prossimo punto
|
||||
// bPoint = PLG.GetNextPoint( ptP) ;
|
||||
// }
|
||||
// // se richiesti caps e sezione chiusa e guida aperta
|
||||
// if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// // calcolo la polilinea che approssima la sezione
|
||||
// PolyLine PLS ;
|
||||
// if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS))
|
||||
// return nullptr ;
|
||||
// // verifico che la sezione sia chiusa e piatta
|
||||
// Plane3d plSect ; double dArea ;
|
||||
// if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) {
|
||||
// // aggiungo il cap sull'inizio
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS))
|
||||
// return nullptr ;
|
||||
// pSci->Invert() ;
|
||||
// Point3d ptGi ; PLG.GetFirstPoint( ptGi) ;
|
||||
// pSci->Translate( ptGi - ptStart + vtDelta) ;
|
||||
// pSTM->DoSewing( *pSci) ;
|
||||
// // aggiungo il cap sulla fine
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS))
|
||||
// return nullptr ;
|
||||
// Point3d ptGe ; PLG.GetLastPoint( ptGe) ;
|
||||
// pSce->Translate( ptGe - ptStart + vtDelta) ;
|
||||
// pSTM->DoSewing( *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 Release( pSTM) ;
|
||||
//}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
|
||||
@@ -1317,16 +687,12 @@ GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
|
||||
// verifica parametri
|
||||
if ( &ptP == nullptr || 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->CreateByPointCurve( ptP, pCurve))
|
||||
return nullptr ;
|
||||
//// salvo tolleranza lineare usata
|
||||
//pSbz->SetLinearTolerance( dLinTol) ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
@@ -1362,8 +728,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType))
|
||||
return nullptr ;
|
||||
//// salvo tolleranza lineare usata
|
||||
//pSbz->SetLinearTolerance( dLinTol) ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
@@ -1404,4 +769,4 @@ GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -135,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) {
|
||||
|
||||
+5
-6
@@ -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
|
||||
@@ -577,10 +578,8 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
|
||||
bool
|
||||
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
|
||||
{
|
||||
// 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 bool : riferito al vettore originale delle polyline, riporta true se la polyline è stata invertita
|
||||
// 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 ;
|
||||
|
||||
+2
-2
@@ -1300,7 +1300,7 @@ 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()) ;
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
|
||||
return nullptr ;
|
||||
@@ -1310,7 +1310,7 @@ 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()) ;
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
vnPLIndMat.clear() ;
|
||||
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
|
||||
return nullptr ;
|
||||
|
||||
+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)
|
||||
|
||||
+701
-410
File diff suppressed because it is too large
Load Diff
+51
-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,16 +76,15 @@ 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)
|
||||
if ( m_pSTM == nullptr)
|
||||
GetAuxSurf() ;
|
||||
dVolume = 0 ;
|
||||
if( m_pSTM != nullptr)
|
||||
if ( m_pSTM != nullptr)
|
||||
m_pSTM->GetVolume( dVolume) ;
|
||||
return true ; }
|
||||
bool GetCentroid( Point3d& ptCen) const override ;
|
||||
@@ -103,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,
|
||||
@@ -113,23 +120,24 @@ 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
|
||||
@@ -138,8 +146,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
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 non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
|
||||
// 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 ;
|
||||
@@ -148,6 +156,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
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 ;
|
||||
@@ -159,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)
|
||||
@@ -203,34 +212,42 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
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
|
||||
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
|
||||
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 ;
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+9
-5
@@ -143,7 +143,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
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 ;
|
||||
@@ -557,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) ;
|
||||
@@ -1210,18 +1210,22 @@ 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) ;
|
||||
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 > 25 * 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()) ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
+355
-39
@@ -234,9 +234,13 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
|
||||
m_vPart.clear() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
if ( ! vtN.Normalize( EPS_ZERO))
|
||||
return SVT_DEL ;
|
||||
// inserisco il triangolo
|
||||
try { m_vTria.emplace_back( nIdVert, nTFlag) ;}
|
||||
catch(...) { return SVT_NULL ;}
|
||||
// aggiorno la sua normale
|
||||
m_vTria.back().vtN = vtN ;
|
||||
// aggiorno massimo TFlag
|
||||
m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ;
|
||||
// ne determino l'indice
|
||||
@@ -1154,7 +1158,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_CHAMFER) ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
@@ -1170,7 +1174,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
return false ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_CHAMFER) ;
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
@@ -1220,16 +1224,17 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
// se rimasto qualcosa
|
||||
if ( pgTria.GetSideCount() > 0) {
|
||||
// lo proietto sul piano e creo la regione
|
||||
pgTria.Scale( frOCS, 1, 1, 0) ;
|
||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_CHAMFER) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
if ( pgTria.Scale( frOCS, 1, 1, 0)) {
|
||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1242,7 +1247,7 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
return true ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_CHAMFER) ;
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
@@ -1687,11 +1692,13 @@ SurfTriMesh::AdjustVertices( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustAdjacencies( void)
|
||||
SurfTriMesh::AdjustAdjacencies( bool AdjustVert)
|
||||
{
|
||||
// sistemo le relazioni tra triangoli e vertici
|
||||
if ( ! AdjustVertices())
|
||||
return false ;
|
||||
if ( AdjustVert) {
|
||||
if ( ! AdjustVertices())
|
||||
return false ;
|
||||
}
|
||||
// matrice di incidenza vertici-triangoli
|
||||
INTMATRIX mVertTria( GetVertexSize()) ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
@@ -1874,7 +1881,7 @@ SurfTriMesh::TestSealing( void)
|
||||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
|
||||
bClosed = false ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1936,7 +1943,7 @@ SurfTriMesh::PackVertices( void)
|
||||
++ nFirstFree ;
|
||||
}
|
||||
else
|
||||
vVId.push_back( nId) ;
|
||||
vVId.push_back( nId) ;
|
||||
}
|
||||
else {
|
||||
if ( nFirstFree == SVT_NULL)
|
||||
@@ -2091,6 +2098,17 @@ SurfTriMesh::CreateByFlatContour( const PolyLine& PL)
|
||||
return AdjustTopology() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL)
|
||||
{
|
||||
INTMATRIX vnPLIndMat ;
|
||||
vnPLIndMat.push_back( { 0}) ;
|
||||
for ( int i = 1 ; i < int( vPL.size()) ; ++ i)
|
||||
vnPLIndMat[0].push_back( i) ;
|
||||
return CreateByRegion( vPL, vnPLIndMat) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat)
|
||||
@@ -3032,7 +3050,7 @@ SurfTriMesh::AddBiTriangle( const int nIdVert[4])
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::DoCompacting( double dTol)
|
||||
{
|
||||
{
|
||||
// imposto ricalcolo
|
||||
m_nStatus = ERR ;
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -3073,6 +3091,7 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
int nVIdSize = int( vVId.size()) ;
|
||||
|
||||
// sistemo gli indici dei vertici nei triangoli
|
||||
INTVECTOR vInvalidIds ;
|
||||
for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) {
|
||||
// salto i triangoli cancellati
|
||||
if ( m_vTria[nId].nIdVert[0] == SVT_DEL)
|
||||
@@ -3089,15 +3108,51 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
// aggiorno il triangolo
|
||||
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
|
||||
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
// se due vertici coincidono o la normale non è calcolabile, cancello il triangolo
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] ||
|
||||
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] ||
|
||||
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] ||
|
||||
! CalcTriangleNormal( nId))
|
||||
RemoveTriangle( nId) ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
|
||||
// verifico se triangolo da rimuovere per vertici coincidenti
|
||||
bool bRemove = false ;
|
||||
int nTAdj1 = SVT_NULL, nTAdj2 = SVT_NULL ;
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[1] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[1] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
if ( bRemove) {
|
||||
// sistemo le contro adiacenze
|
||||
if ( nTAdj1 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj1].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj1].nIdAdjac[j] = nTAdj2 ;
|
||||
}
|
||||
if ( nTAdj2 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj2].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj2].nIdAdjac[j] = nTAdj1 ;
|
||||
}
|
||||
// rimuovo il triangolo
|
||||
RemoveTriangle( nId) ;
|
||||
}
|
||||
|
||||
// verifico se il triangolo va rimosso per normale non calcolabile
|
||||
else if ( ! CalcTriangleNormal( nId))
|
||||
vInvalidIds.emplace_back( nId) ;
|
||||
}
|
||||
|
||||
// elimino triangoli invalidi ( con gestione speciale per evitare T-junctions)
|
||||
if ( ! vInvalidIds.empty())
|
||||
RemoveInvalidTriangles( vInvalidIds) ;
|
||||
|
||||
// compatto il vettore dei vertici
|
||||
if ( ! PackVertices())
|
||||
return false ;
|
||||
@@ -3334,22 +3389,23 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
|
||||
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
|
||||
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
||||
|
||||
// aggiorno le facce
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
|
||||
// se c'è mirror, devo invertire la faccia
|
||||
if ( bMirror)
|
||||
InvertTriangle( i) ;
|
||||
// aggiorno la normale
|
||||
if ( ! CalcTriangleNormal( i)) {
|
||||
// elimino il triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
// se c'è mirror, devo invertire le facce
|
||||
if ( bMirror) {
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL)
|
||||
InvertTriangle( i) ;
|
||||
}
|
||||
|
||||
// rimuovo i triangoli resi invalidi dalla scalatura
|
||||
bool bOk = DoCompacting() ;
|
||||
|
||||
return DoCompacting() ;
|
||||
// rimuovo i triangoli doppi
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -3973,6 +4029,56 @@ SurfTriMesh::CloneShell( int nShell) const
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartLocalBBox( int nP, BBox3d& b3Loc) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Loc.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Loc.Add( m_vVert[m_vTria[i].nIdVert[j]].ptP) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Ref.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Ref.Add( GetToGlob( m_vVert[m_vTria[i].nIdVert[j]].ptP, frRef)) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetPartCount( void) const
|
||||
@@ -4063,6 +4169,133 @@ SurfTriMesh::GetPartVolume( int nPart, double& dVolume) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
vPL.clear() ;
|
||||
// aggiorno timestamp dei triangoli
|
||||
++ m_nTimeStamp ;
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nTemp = m_nTimeStamp ;
|
||||
// incremento time stamp
|
||||
++ m_nTimeStamp ;
|
||||
// recupero il vettore delle Shell che compongono la part
|
||||
const auto& vShell = m_vPart[nPart].vShell ;
|
||||
// ciclo sui triangoli
|
||||
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
|
||||
// se triangolo valido e non ancora visitato
|
||||
if ( m_vTria[nT].nIdVert[0] != SVT_DEL && m_vTria[nT].nTemp != m_nTimeStamp &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[nT].nShell) != vShell.end()) {
|
||||
// determino i triangoli adiacenti
|
||||
int nAdjT[3] ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
nAdjT[j] = m_vTria[nT].nIdAdjac[j] ;
|
||||
// se tutti e tre i lati sono di contorno
|
||||
if ( nAdjT[0] == SVT_NULL &&
|
||||
nAdjT[1] == SVT_NULL &&
|
||||
nAdjT[2] == SVT_NULL) {
|
||||
// ho trovato un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
}
|
||||
// se i due lati 0 e 1 sono di contorno
|
||||
else if ( nAdjT[0] == SVT_NULL &&
|
||||
nAdjT[1] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se i due lati 1 e 2 sono di contorno
|
||||
else if ( nAdjT[1] == SVT_NULL &&
|
||||
nAdjT[2] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se i due lati 2 e 0 sono di contorno
|
||||
else if ( nAdjT[2] == SVT_NULL &&
|
||||
nAdjT[0] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 0 è di contorno
|
||||
else if ( nAdjT[0] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 1 è di contorno
|
||||
else if ( nAdjT[1] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 2 è di contorno
|
||||
else if ( nAdjT[2] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
// cammino lungo il loop fino a chiuderlo
|
||||
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti non c'è contorno
|
||||
else {
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemovePart( int nPart)
|
||||
@@ -4184,3 +4417,86 @@ SurfTriMesh::SetTempInt( int nId, int nTempInt) const
|
||||
m_vTria[nId].nTemp = nTempInt ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol)
|
||||
{
|
||||
// scorro i triangoli
|
||||
for ( const Triangle3dEx& Tria : vTria) {
|
||||
// ciclo sui tre vertici
|
||||
int nIdV[3]{} ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
// verifico se vertice già presente
|
||||
int nId ;
|
||||
if ( ! VertGrid.Find( Tria.GetP( nV), dVertexTol, nId)) {
|
||||
// se non presente, lo aggiugo
|
||||
nIdV[nV] = AddVertex( Tria.GetP( nV)) ;
|
||||
if ( nIdV[nV] == SVT_NULL)
|
||||
return false ;
|
||||
VertGrid.InsertPoint( Tria.GetP( nV), nIdV[nV]) ;
|
||||
}
|
||||
else
|
||||
nIdV[nV] = nId ;
|
||||
}
|
||||
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
|
||||
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
|
||||
int nT = AddTriangle( nIdV, Tria.GetGrade()) ;
|
||||
if ( nT != SVT_NULL && nT != SVT_DEL) {
|
||||
// associo relazione vertice-triangolo
|
||||
for ( int i = 0 ; i < 3 ; ++ i)
|
||||
m_vVert[nIdV[i]].nIdTria = nT ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustTopologyFromZMap( void)
|
||||
{
|
||||
// cancello tutti i vertici che puntano a triangoli cancellati
|
||||
bool bPack = false ;
|
||||
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
|
||||
if ( m_vVert[i].nIdTria == SVT_NULL) {
|
||||
m_vVert[i].nIdTria = SVT_DEL ;
|
||||
bPack = true ;
|
||||
}
|
||||
}
|
||||
if ( bPack)
|
||||
PackVertices() ;
|
||||
m_nStatus = SurfTriMesh::OK ;
|
||||
|
||||
// calcolo le adiacenze
|
||||
if ( ! AdjustAdjacencies())
|
||||
return false ;
|
||||
|
||||
// verifico l'orientamento ( TODO -- Da migliorare...)
|
||||
// Ora per funzionare è necessario che il ciclo sui triangoli parta da un triangolo orientato
|
||||
// correttamente e che i triangoli invertiti siano "circondati" da triangoli tutti orientati correttamente
|
||||
if ( ! AdjustOrientations())
|
||||
return false ;
|
||||
|
||||
// calcolo le facce
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
|
||||
// rimozione delle TJunction
|
||||
bool bModified = false ;
|
||||
if ( ! RemoveTJunctions( bModified, SQ_EPS_SMALL))
|
||||
return false ;
|
||||
if ( bModified) {
|
||||
if ( ! AdjustVertices() || ! DoCompacting())
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
TestSealing() ;
|
||||
|
||||
// semplifico le facce ( anche più piccola)
|
||||
if ( ! SimplifyFacets( MAX_EDGE_LEN_STD, false, 5. * EPS_SMALL))
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::AdjustTopologyFromZMap")
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+24
-8
@@ -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>
|
||||
|
||||
@@ -251,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, const INTMATRIX& vnPLIndMat) 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 ;
|
||||
@@ -327,7 +328,7 @@ 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 ;
|
||||
@@ -336,10 +337,13 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
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 ;
|
||||
@@ -365,12 +369,15 @@ 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 GetTempInt( int nId, int& nTempInt) const ;
|
||||
bool ResetTempInts( void) const ;
|
||||
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 ;
|
||||
@@ -386,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) ;
|
||||
@@ -431,14 +438,16 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
|
||||
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
|
||||
@@ -481,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
|
||||
|
||||
+44
-85
@@ -56,7 +56,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
|
||||
// Divido il loop di partenza in sotto-loop
|
||||
int nIterationCount = 0 ;
|
||||
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
|
||||
while ( ! cvOpenChain.empty()) { // per ogni catena aperta...
|
||||
bool bLoopSplitted = false ;
|
||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||
if ( vnDegVec[nLastOpenLoopN] == 1) {
|
||||
@@ -287,7 +287,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
// Recupero i concatenamenti
|
||||
INTVECTOR vIds ;
|
||||
Point3d ptNearStart = ( it->second.size() > 0 ? it->second[0].ptSt : ORIG) ;
|
||||
Point3d ptNearStart = ( ! it->second.empty() ? it->second[0].ptSt : ORIG) ;
|
||||
CHAINVECTOR vChain ;
|
||||
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
||||
Chain chTemp ;
|
||||
@@ -502,9 +502,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop
|
||||
// chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
|
||||
// sotto-loop chiusi di cui è formato il perimetro.
|
||||
@@ -704,16 +702,18 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// Elimino loop interni non validi
|
||||
bool bDouble = true ;
|
||||
// Verifico se i loop interni sono validi
|
||||
bool bAllInvalid = true ;
|
||||
for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) {
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 2) {
|
||||
bDouble = false ;
|
||||
// se chain formata da tre segmenti significa che si tratta di due linee sovrapposte ( il terzo tratto è quello aggiunto
|
||||
// per forzare la chiusura)
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 3) {
|
||||
bAllInvalid = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vInnerLoop.size() == 0 || bDouble) {
|
||||
if ( vInnerLoop.empty() || bAllInvalid) {
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -753,63 +753,20 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.emplace_back( CurLoop) ;
|
||||
}
|
||||
|
||||
// poligono
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[1]) ;
|
||||
|
||||
// controllo direzioni delle normali
|
||||
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
|
||||
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
|
||||
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
|
||||
// Ciclo sui segmenti del loop esterno
|
||||
auto itSt = ExternLoopList.begin() ;
|
||||
auto itEn = itSt ;
|
||||
++ itEn ;
|
||||
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
|
||||
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
|
||||
Point3d ptSt = itSt->first ;
|
||||
Point3d ptEn = itEn->first ;
|
||||
Vector3d vtSeg = ptEn - ptSt ;
|
||||
double dSegLen = vtSeg.Len() ;
|
||||
vtSeg /= dSegLen ;
|
||||
// Vettore dei punti dei loop interni che stanno sul segmento del loop esterno
|
||||
PNTUVECTOR vPointWithOrder ;
|
||||
// Ciclo sui loop interni
|
||||
for ( int nInnPoly = 1 ; nInnPoly < int( vPolygons.size()) ; ++ nInnPoly) {
|
||||
// Ciclo sui punti dei loop interni
|
||||
Point3d ptInnPoint ;
|
||||
bool bIsFirst = true ;
|
||||
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
|
||||
while ( bContinue) {
|
||||
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
double dLongPos = ( ptInnPoint - ptSt) * vtSeg ;
|
||||
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
|
||||
POINTU NewPointU ;
|
||||
NewPointU.first = ptInnPoint ;
|
||||
NewPointU.second = dLongPos ;
|
||||
if ( ! bIsFirst)
|
||||
vPointWithOrder.emplace_back( NewPointU) ;
|
||||
}
|
||||
bIsFirst = false ;
|
||||
bContinue = vPolygons[nInnPoly].GetNextPoint( ptInnPoint) ;
|
||||
}
|
||||
}
|
||||
// Riordino i punti interni sul segmento esterno in funzione della distanza dall'origine di esso
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) - 1 ; ++ nPi) {
|
||||
for ( int nPj = nPi + 1 ; nPj < int( vPointWithOrder.size()) ; ++ nPj) {
|
||||
if ( vPointWithOrder[nPi].second > vPointWithOrder[nPj].second) {
|
||||
swap( vPointWithOrder[nPi], vPointWithOrder[nPj]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Aggiungo i punti al loop esterno
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
|
||||
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
|
||||
}
|
||||
// controllo la direzione della normale del triangolo con quella del poligono di area maggiore
|
||||
// ( per gestire eventuali inscatolamenti)
|
||||
Vector3d vtPoly = V_NULL ;
|
||||
double dMaxArea = -1 ;
|
||||
for ( int i = 1 ; i < int( vPolygons.size()) ; i ++) {
|
||||
Plane3d plPoly ;
|
||||
double dAreaPoly ;
|
||||
vPolygons[i].IsClosedAndFlat( plPoly, dAreaPoly) ;
|
||||
if ( dAreaPoly > dMaxArea) {
|
||||
vtPoly = plPoly.GetVersN() ;
|
||||
dMaxArea = dAreaPoly ;
|
||||
}
|
||||
}
|
||||
bool bCodirectedNormals = trTria.GetN() * vtPoly > 0. ;
|
||||
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -836,6 +793,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
|
||||
// Divido i loop che si autointercettano
|
||||
// TO DO : da verificare. Questa porzione di codice non dovrebbe andare prima della triangolazione?
|
||||
int nInitialLoopNum = int( vPolygons.size()) ;
|
||||
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
@@ -883,11 +841,11 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
itSt2 = LoopPointList.emplace( itEn2, vAddingPointWithOrder[nPi]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Spezzo i loop autointersecantesi
|
||||
POLYLINEVECTOR vAuxPolygons ;
|
||||
vAuxPolygons.emplace_back( vPolygons[nL]) ;
|
||||
|
||||
|
||||
bool bSplitted = true ;
|
||||
while ( bSplitted) {
|
||||
bSplitted = false ;
|
||||
@@ -956,16 +914,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.erase( vPolygons.begin() + i) ;
|
||||
else
|
||||
++ i ;
|
||||
|
||||
}
|
||||
|
||||
bool bCordirectedNormals_intLoop = bCodirectedNormals ;
|
||||
// eventuale inversione della prima curva ( che determina il verso della triangolazione) per averla orientata
|
||||
// come il triangolo
|
||||
if ( ! vPolygons.empty()) {
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[0]) ;
|
||||
// controllo direzioni delle normali
|
||||
bCordirectedNormals_intLoop = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
if ( ! bCordirectedNormals_intLoop)
|
||||
if ( trTria.GetN() * pgPol.GetVersN() < 0.)
|
||||
vPolygons[0].Invert() ;
|
||||
}
|
||||
|
||||
@@ -981,7 +936,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCordirectedNormals_intLoop)
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
|
||||
@@ -1123,7 +1078,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
{
|
||||
{
|
||||
bool bModif = false ;
|
||||
SurfTriMesh& SurfB = Other ;
|
||||
|
||||
@@ -1176,7 +1131,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
INTVECTOR vNearTria ;
|
||||
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
|
||||
// I scorro tutti i triangoli di B che intersecano il box di A
|
||||
// Scorro tutti i triangoli di B che intersecano il box di A
|
||||
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
|
||||
|
||||
// Se il triangolo B non è valido, continuo
|
||||
@@ -1365,7 +1320,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
SurfB.ResetHashGrids3d() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
@@ -1375,15 +1330,19 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Box del triangolo A
|
||||
BBox3d b3dTriaA ;
|
||||
trTriaA.GetLocalBBox( b3dTriaA) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
|
||||
// Se il triangolo B non è valido, continuo
|
||||
// Se il triangolo B non è valido, continuo
|
||||
Triangle3d trTriaB ;
|
||||
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
|
||||
continue ;
|
||||
// Se i triangoli sono sovrapposti
|
||||
// Se sono già stati classificati entrambi come sovrapposti continuo
|
||||
if ( abs( m_vTria[nTA].nTempShell) == 2 && abs( SurfB.m_vTria[vNearTria[nTB]].nTempShell) == 2)
|
||||
continue ;
|
||||
|
||||
// Se i triangoli sono sovrapposti
|
||||
TRIA3DVECTOR vTriaAB ;
|
||||
Point3d ptTempA, ptTempB ;
|
||||
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
|
||||
@@ -1475,7 +1434,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
@@ -1625,12 +1584,12 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sistemazioni varie
|
||||
bool bOk = ( AdjustVertices() && DoCompacting()) ;
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
bOk = bOk && RemoveTJunctions( bModified) ;
|
||||
if ( bModified)
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
@@ -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()) ;
|
||||
}
|
||||
+206
-33
@@ -17,7 +17,6 @@
|
||||
#include "Triangulate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -35,6 +34,7 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
// recupero i vertici dei triangoli
|
||||
int nIdV[3] ;
|
||||
GetTriangle( nT, nIdV) ;
|
||||
bool bToRemove = false ;
|
||||
// ciclo sui triangoli adiacenti
|
||||
for ( int nE = 0 ; nE < 3 ; ++ nE) {
|
||||
// recupero triangolo adiacente, se non esiste passo al successivo
|
||||
@@ -53,10 +53,14 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
}
|
||||
}
|
||||
if ( nCoinc == 3) {
|
||||
RemoveTriangle( nAdjT) ;
|
||||
// se i vertici coincidono rimuovo entrambi i triangoli
|
||||
bToRemove = true ;
|
||||
bModified = true ;
|
||||
RemoveTriangle( nAdjT) ;
|
||||
}
|
||||
}
|
||||
if ( bToRemove)
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -86,8 +90,8 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
// Recupero i vertici del triangolo A
|
||||
Point3d ptSegSt, ptSegEn, ptVertA ;
|
||||
if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
|
||||
return false ;
|
||||
// Recupero il vertice opposto del triangolo B
|
||||
Point3d ptVertB ;
|
||||
@@ -98,23 +102,43 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
if ( ! DiagDist.IsSmall())
|
||||
return false ;
|
||||
double dPos1, dPos2 ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) ||
|
||||
dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL ||
|
||||
dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL)
|
||||
return false ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2))
|
||||
return false ;
|
||||
if ( dPos1 < - EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() + EPS_SMALL ||
|
||||
dPos2 < - EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() + EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Eseguo il flipping
|
||||
m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
|
||||
|
||||
// sistemo anche le contro-adiacenze
|
||||
int nTC = m_vTria[nTA].nIdAdjac[nEdgeA] ;
|
||||
if ( nTC != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTC].nIdAdjac[i] == nTB) {
|
||||
m_vTria[nTC].nIdAdjac[i] = nTA ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
int nTD = m_vTria[nTB].nIdAdjac[nEdgeB] ;
|
||||
if ( nTD != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTD].nIdAdjac[i] == nTA) {
|
||||
m_vTria[nTD].nIdAdjac[i] = nTB ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
SurfTriMesh::RemoveTJunctions( bool& bModified, double dMinSqDist)
|
||||
{
|
||||
bModified = false ;
|
||||
|
||||
@@ -123,6 +147,11 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
|
||||
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
|
||||
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
|
||||
// se adiacenze tutte valide, passo al successivo
|
||||
if ( m_vTria[nT].nIdAdjac[0] != SVT_DEL && m_vTria[nT].nIdAdjac[0] != SVT_NULL &&
|
||||
m_vTria[nT].nIdAdjac[1] != SVT_DEL && m_vTria[nT].nIdAdjac[1] != SVT_NULL &&
|
||||
m_vTria[nT].nIdAdjac[2] != SVT_DEL && m_vTria[nT].nIdAdjac[2] != SVT_NULL)
|
||||
continue ;
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
@@ -150,6 +179,8 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
if ( dSegLen < EPS_SMALL)
|
||||
continue ;
|
||||
vtSeg /= dSegLen ;
|
||||
int nV1 = m_vTria[nT].nIdVert[nSeg] ;
|
||||
int nV2 = m_vTria[nT].nIdVert[Next( nSeg)] ;
|
||||
// Ciclo sui triangoli vicini
|
||||
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
|
||||
// Salto il triangolo se è quello di riferimento
|
||||
@@ -157,13 +188,16 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
continue ;
|
||||
// Cerco i vertici che stanno sul lato del triangolo
|
||||
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
|
||||
int nCurrVert = m_vTria[vNearTria[nI]].nIdVert[nVert] ;
|
||||
if ( nCurrVert == nV1 || nCurrVert == nV2)
|
||||
continue ;
|
||||
Point3d ptVert ;
|
||||
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
|
||||
continue ;
|
||||
double dProj = ( ptVert - ptSegSt) * vtSeg ;
|
||||
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
|
||||
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H)
|
||||
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
|
||||
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
|
||||
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < dMinSqDist)
|
||||
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
|
||||
}
|
||||
}
|
||||
// Riordino i vertici sul segmento
|
||||
@@ -307,16 +341,42 @@ ChooseGoodStartPoint( PNTULIST& PointList)
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
// -------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const
|
||||
{
|
||||
// vettore dei loop della faccia adiacente
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
// Ciclo sui punti del loop
|
||||
auto itLast = PointList.begin() ;
|
||||
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
|
||||
|
||||
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia
|
||||
if ( itLast->second != it->second) {
|
||||
|
||||
// bisogna fermarsi per analizzare il tratto corrente alla ricerca di punti allineati se dal punto corrente
|
||||
// inizia un tratto adiacente ad un'altra faccia oppure se il punto corrente non verrà eliminato dal loop
|
||||
// della faccia adiacente
|
||||
|
||||
bool bAnalyze = ( itLast->second != it->second) ;
|
||||
if ( bAnalyze)
|
||||
LoopVec.clear() ;
|
||||
if ( ! bAnalyze && itLast->second != - 1) {
|
||||
if ( LoopVec.empty())
|
||||
GetFacetLoops( int( itLast->second), LoopVec) ;
|
||||
for ( int i = 0 ; i < int( LoopVec.size()) && ! bAnalyze ; i ++) {
|
||||
const PNTULIST& PointListAdj = LoopVec[i].GetUPointList() ;
|
||||
int nSamePoints = 0 ;
|
||||
for ( auto itAdj = PointListAdj.begin() ; itAdj != prev( PointListAdj.end()) ; ++ itAdj) {
|
||||
// cerco il punto corrente sul loop della faccia adiacente
|
||||
if ( AreSamePointApprox( it->first, itAdj->first))
|
||||
++ nSamePoints ;
|
||||
if ( ( nSamePoints == 1 && int( PointListAdj.size()) <= 4) || nSamePoints > 1) {
|
||||
bAnalyze = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAnalyze) {
|
||||
// Raccolgo i punti in una polyline
|
||||
PolyLine PL ;
|
||||
int nPar = -1 ;
|
||||
@@ -326,7 +386,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
}
|
||||
PL.AddUPoint( ++nPar, it->first) ;
|
||||
// Provo ad eliminare i punti allineati
|
||||
PL.RemoveAlignedPoints( 50 * EPS_SMALL) ;
|
||||
PL.RemoveAlignedPoints( dTolAlign) ;
|
||||
if ( PL.GetPointNbr() < nPar + 1) {
|
||||
// rimuovo dalla lista dei punti gli eliminati (salto gli estremi)
|
||||
int nUCurr = 1 ;
|
||||
@@ -418,7 +478,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced, double dTolAlign)
|
||||
{
|
||||
// La trimesh deve essere valida
|
||||
if ( ! IsValid())
|
||||
@@ -433,8 +493,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
|
||||
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
|
||||
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
|
||||
|
||||
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
|
||||
|
||||
// Recupero i loop della faccia ( il parametro indica la faccia adiacente)
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
GetFacetLoops( nF, LoopVec) ;
|
||||
|
||||
@@ -445,13 +505,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Lista dei punti del loop
|
||||
PNTULIST& PointList = LoopVec[nL].GetUPointList() ;
|
||||
|
||||
// Se il loop è un triangolo, non va modificato
|
||||
if ( int( PointList.size()) <= 4)
|
||||
continue ;
|
||||
|
||||
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
|
||||
if ( ! ChooseGoodStartPoint( PointList))
|
||||
continue ;
|
||||
|
||||
// Sistemo il loop
|
||||
bool bModif = false ;
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif))
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, dTolAlign, bModif))
|
||||
return false ;
|
||||
if ( bModif)
|
||||
bToRetriangulate = true ;
|
||||
@@ -479,9 +543,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Eseguo la ritriangolazione della faccia
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( LoopVec, vPt, vTr)) {
|
||||
if ( Triangulate().Make( LoopVec, vPt, vTr) && ! vTr.empty())
|
||||
FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
|
||||
}
|
||||
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto
|
||||
else
|
||||
return false ;
|
||||
@@ -502,17 +565,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Cancello i triangoli
|
||||
for ( int nT : vDelTria)
|
||||
RemoveTriangle( nT) ;
|
||||
|
||||
|
||||
// Applico le nuove triangolazioni delle facce
|
||||
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
|
||||
const PNTVECTOR& vPt = itF->second.first ;
|
||||
const INTVECTOR& vTr = itF->second.second ;
|
||||
// Inserisco i nuovi triangoli
|
||||
// Inserisco i nuovi triangoli
|
||||
bool bFirstTria = true ;
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
auto itCol = ColorMap.find( itF->first) ;
|
||||
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
|
||||
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
|
||||
@@ -525,7 +588,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
@@ -539,10 +602,10 @@ bool
|
||||
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
|
||||
{
|
||||
// Se la catena da aggiungere è vuota, non devo fare alcunchè
|
||||
if ( ChainToAdd.size() == 0)
|
||||
if ( ChainToAdd.empty())
|
||||
return true ;
|
||||
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
||||
if ( OrigChain.size() == 0)
|
||||
if ( OrigChain.empty())
|
||||
return false ;
|
||||
// Se la catena originale è chiusa non posso aggiungere nulla
|
||||
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
|
||||
@@ -722,3 +785,113 @@ SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECT
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const
|
||||
{
|
||||
// recupero il lato più lungo del triangolo
|
||||
double dLen0 = SqDist( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
double dLen1 = SqDist( m_vVert[m_vTria[nT].nIdVert[1]].ptP, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
double dLen2 = SqDist( m_vVert[m_vTria[nT].nIdVert[2]].ptP, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
nEdge = -1 ;
|
||||
if ( dLen0 > dLen1 && dLen0 > dLen2)
|
||||
nEdge = 0 ;
|
||||
else if ( dLen1 > dLen2)
|
||||
nEdge = 1 ;
|
||||
else
|
||||
nEdge = 2 ;
|
||||
|
||||
// recupero il triangolo adiacente sul lato più lungo
|
||||
nAdjTrg = m_vTria[nT].nIdAdjac[nEdge] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveInvalidTriangles( const INTVECTOR& vIds)
|
||||
{
|
||||
// al momento gestito solo per trimesh con adiacenze definite, eventualmente da estendere.
|
||||
// Analoga a RemoveFistInvalidTrg in Triangulate.cpp
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
unordered_map<int, bool> InvalidMap ;
|
||||
for ( auto nId : vIds)
|
||||
InvalidMap[nId] = true ;
|
||||
|
||||
for ( int i = 0 ; i < int( vIds.size()) ; i++) {
|
||||
|
||||
int nTA = vIds[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
|
||||
// recupero il triangolo adiacente sul suo lato più lungo
|
||||
int nTB, nEdgeA ;
|
||||
FindAdjacentOnLongerEdge( nTA, nEdgeA, nTB) ;
|
||||
|
||||
// se adiacente è nullo posso rimuovere tranquillamente il triangolo senza creare TJunctions
|
||||
if ( nTB == SVT_NULL) {
|
||||
RemoveTriangle( nTA) ;
|
||||
continue ;
|
||||
}
|
||||
// se adiacente è valido posso fare il flip per rendere valido nTA
|
||||
else if ( ! InvalidMap[nTB]) {
|
||||
FlipTriangles( nTA, nTB) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
// se adiacente è invalido creo una catena da risolvere non appena si trova un triangolo valido
|
||||
else {
|
||||
INTVECTOR vChain = {nTA} ;
|
||||
INTVECTOR vChainEdges = {nEdgeA} ;
|
||||
int nTCurr = nTB ;
|
||||
|
||||
while ( nTCurr != SVT_NULL && InvalidMap[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
int nTOther, nEdgeCurr ;
|
||||
FindAdjacentOnLongerEdge( nTCurr, nEdgeCurr, nTOther) ;
|
||||
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTriangles( nTCurr, nTOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena dopo aver fatto flip
|
||||
nTOther = m_vTria[vChain.back()].nIdAdjac[vChainEdges.back()] ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nEdgeCurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, posso rimuovere tutti i triangoli della catena
|
||||
if ( nTCurr == SVT_NULL) {
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
RemoveTriangle( vChain[k]) ;
|
||||
InvalidMap[vChain[k]] = false ;
|
||||
}
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido trovato
|
||||
else {
|
||||
FlipTriangles( vChain.back(), nTCurr) ;
|
||||
InvalidMap[vChain.back()] = false ;
|
||||
for ( int i = int( vChain.size()) - 2 ; i >= 0 ; i--) {
|
||||
int nTA = vChain[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
// eseguo il flip con il triangolo adiacente sul suo lato più lungo
|
||||
int nTOther = m_vTria[nTA].nIdAdjac[vChainEdges[i]] ;
|
||||
FlipTriangles( nTA, nTOther) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
struct PairHashInt64 {
|
||||
size_t operator()(const std::pair<int64_t, int64_t>& key) const {
|
||||
size_t h1 = std::hash<int64_t>{}(key.first) ;
|
||||
size_t h2 = std::hash<int64_t>{}(key.second) ;
|
||||
return h1 ^ (h2 << 1); // Combine hashes
|
||||
}
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
struct Inters {
|
||||
@@ -33,13 +42,13 @@ struct Inters {
|
||||
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
|
||||
bool operator < ( Inters& b)
|
||||
{
|
||||
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
|
||||
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
const auto iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
|
||||
int nPos2 = std::distance( vEdges.begin(), iter2) ;
|
||||
// se sono loop interni li ordino in modo decrescente rispetto all'area
|
||||
// se sono loop interni li ordino in modo decrescente rispetto all'area
|
||||
bool bEqIn = ( nIn == b.nIn) ;
|
||||
double dAreaA = 0 , dAreaB = 0 ;
|
||||
if ( bEqIn && nIn == -1) {
|
||||
@@ -54,7 +63,7 @@ struct Inters {
|
||||
pl.Close() ;
|
||||
pl.GetAreaXY( dAreaB) ;
|
||||
}
|
||||
// se nIn è un vertice sistemo il valore
|
||||
// se nIn è un vertice sistemo il valore
|
||||
int nEdgeIn = nIn ;
|
||||
if ( nIn > 3)
|
||||
nEdgeIn = nIn - 4 ;
|
||||
@@ -66,13 +75,13 @@ struct Inters {
|
||||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
|
||||
}
|
||||
|
||||
static bool FirstEncounter ( Inters& a, Inters& b)
|
||||
static bool FirstEncounter( Inters& a, Inters& b)
|
||||
{
|
||||
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
|
||||
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
|
||||
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
|
||||
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
|
||||
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
|
||||
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
// trovo i lati di ingresso e uscita
|
||||
// trovo i lati di ingresso e uscita
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ;
|
||||
@@ -83,13 +92,13 @@ struct Inters {
|
||||
int nPos4 = std::distance( vEdges.begin(), iter4) ;
|
||||
int nFirstA = 0 ;
|
||||
int nFirstB = 0 ;
|
||||
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
|
||||
// salvo il lato che viene prima confrontando ingresso e uscita
|
||||
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
|
||||
// salvo il lato che viene prima confrontando ingresso e uscita
|
||||
if ( nPos2 < nPos1) {
|
||||
nPos1 = nPos2 ;
|
||||
nFirstA = int( a.vpt.size()) - 1 ;
|
||||
}
|
||||
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
|
||||
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
|
||||
else if ( nPos2 == nPos1 ) {
|
||||
if ( nPos1 == 0 )
|
||||
nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
@@ -116,11 +125,11 @@ struct Inters {
|
||||
}
|
||||
a.bSortedbyStart = nFirstA == 0 ;
|
||||
b.bSortedbyStart = nFirstB == 0 ;
|
||||
// se sono diversi ritorno il confronto
|
||||
// se sono diversi ritorno il confronto
|
||||
if ( nPos1 != nPos3)
|
||||
return nPos1 < nPos3 ;
|
||||
// se sono uguali devo valutare il punto di intersezione
|
||||
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
|
||||
// se sono uguali devo valutare il punto di intersezione
|
||||
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) ||
|
||||
( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
|
||||
@@ -154,17 +163,15 @@ class Cell
|
||||
public :
|
||||
~Cell( void) {}
|
||||
Cell( void)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
|
||||
m_ptPbl( ORIG), m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true)
|
||||
{
|
||||
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
|
||||
m_ptPtr = ptTr ;
|
||||
}
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ORIG),
|
||||
m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
Cell( const Point3d& ptBL, const Point3d& ptTR)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
|
||||
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_ptPbl( ptBL),
|
||||
m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
bool IsSame( const Cell& cOtherCell) const
|
||||
{ return ( m_nId == cOtherCell.m_nId) ; }
|
||||
void SetBottomLeft( const Point3d& ptBL)
|
||||
@@ -183,9 +190,11 @@ class Cell
|
||||
{ return Point3d( m_ptPbl.x, m_ptPtr.y) ; }
|
||||
Point3d GetBottomRight( void) const
|
||||
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
|
||||
Point3d GetCenter( void) const
|
||||
{ return ( m_ptPbl + m_ptPtr) / 2 ; }
|
||||
double GetSplitValue( void) const
|
||||
{ return m_dSplit ; }
|
||||
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente
|
||||
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, altrimenti orizzontalmente
|
||||
{ return m_bSplitVert ; }
|
||||
bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia
|
||||
{ return ( m_nChild1 == -2 && m_nChild2 == -2) ; }
|
||||
@@ -194,9 +203,11 @@ class Cell
|
||||
void SetProcessed( bool bProcessed = true)
|
||||
{ m_bProcessed = bProcessed ; }
|
||||
static bool minorX( const Cell& c1, const Cell& c2)
|
||||
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
|
||||
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
|
||||
static bool minorY( const Cell& c1, const Cell& c2)
|
||||
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
|
||||
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
|
||||
void AddPoly( int nPolyId)
|
||||
{ m_vnPolyId.push_back( nPolyId) ;}
|
||||
|
||||
public :
|
||||
int m_nId ; // Id della cella
|
||||
@@ -209,9 +220,9 @@ class Cell
|
||||
double m_dSplit ; // parametro a cui è stata splittata la cella
|
||||
int m_nChild1 ; // prima cella figlio
|
||||
int m_nChild2 ; // seconda cella figlio
|
||||
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
|
||||
int m_nFlag ; // flag che indica la caratterizzazione della cella rispetto ai loop di trim
|
||||
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
|
||||
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
bool m_bLabelled ; // flag che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
|
||||
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U)
|
||||
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
|
||||
@@ -219,6 +230,7 @@ class Cell
|
||||
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
|
||||
int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo
|
||||
// contati in senso CCW a partire dal bottom left
|
||||
INTVECTOR m_vnPolyId ; // indici dei poligoni associati a questa cella nel vettore m_vPolygons del Tree
|
||||
|
||||
private :
|
||||
Point3d m_ptPbl ; // punto bottom left
|
||||
@@ -233,53 +245,48 @@ class Tree
|
||||
public :
|
||||
~Tree( void) ;
|
||||
Tree( void) ;
|
||||
//Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
|
||||
bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
|
||||
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh
|
||||
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
|
||||
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells = {}) ; // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
// se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ;
|
||||
Tree( const Point3d ptBl, const Point3d ptTr) ; // da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
|
||||
bool SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
|
||||
bool BuildTree( double dLinTol = LIN_TOL_STD,
|
||||
double dSideMin = 1, // è la minima lunghezza del lato di una cella
|
||||
double dSideMax = INFINITO) ; // è la massima dimensione di un triangolo della trimesh
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
// ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
||||
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; };
|
||||
void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell
|
||||
bool GetEdges3D ( std::vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) const // funzione che restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i) vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ; return true ; };
|
||||
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
|
||||
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
|
||||
bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli
|
||||
bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U
|
||||
bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V
|
||||
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||
bool IsClosedU( void) const // restituisce flag di chiusara in U
|
||||
{ return m_bClosedU ; }
|
||||
bool IsClosedV( void) const // restituisce flag di chiusara in V
|
||||
{ return m_bClosedV ; }
|
||||
BOOLVECTOR GetPoles( void) // restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||
{ return m_vbPole ; }
|
||||
|
||||
private :
|
||||
bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico
|
||||
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
|
||||
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
|
||||
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1
|
||||
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
|
||||
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
|
||||
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
|
||||
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
|
||||
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
|
||||
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
|
||||
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
|
||||
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
|
||||
void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
|
||||
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
|
||||
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
|
||||
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
|
||||
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
|
||||
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
|
||||
bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
|
||||
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
|
||||
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
|
||||
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation,
|
||||
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
|
||||
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
|
||||
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario
|
||||
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
|
||||
@@ -294,39 +301,30 @@ class Tree
|
||||
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
|
||||
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
|
||||
bool AdjustCuts( void) ;
|
||||
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
|
||||
bool CloseOpenCuts( void) ;
|
||||
bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ;
|
||||
bool UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) ;
|
||||
bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre
|
||||
bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ;
|
||||
|
||||
bool GetPoint(double dU, double dV, Point3d& pt) const ;
|
||||
bool SavePoint( double dU, double dV, Point3d& pt) ;
|
||||
|
||||
private :
|
||||
const SurfBezier* m_pSrfBz ; // superficie di bezier
|
||||
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
|
||||
bool m_bTrimmed ; // superficie trimmata
|
||||
//INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
|
||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
//ICURVEPOVECTOR m_vLoop ; // curve di loop
|
||||
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||
bool m_bBilinear ; // superficie bilineare
|
||||
bool m_bMulti ; // superficie multi-patch
|
||||
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
||||
bool m_bClosedV ; // superficie chiusa lungo il parametro V
|
||||
BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge)
|
||||
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
|
||||
int m_nDegU ; // grado della superficie nel parametro U
|
||||
int m_nDegV ; // grado della superficie nel parametro V
|
||||
int m_nSpanU ; // numero di span lungo il parametro U
|
||||
int m_nSpanV ; // numero di span lungo il parametro V
|
||||
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
|
||||
POLYLINEMATRIX m_vPolygonsCorr ; // matrice dei poligoni del tree, corretti per i punti che sono nei poli
|
||||
POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree
|
||||
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
std::unordered_map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01
|
||||
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
mutable std::unordered_map<std::pair<int64_t, int64_t>,Point3d, PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
|
||||
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
||||
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
||||
bool m_bTestMode ; // bool che indica se la test mode è attiva
|
||||
POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
} ;
|
||||
+433
-28
@@ -22,20 +22,27 @@
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include "/EgtDev/Extern/fist/Include/api_fist.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
|
||||
enum TrgType { TRG_STD = 0, TRG_CAP = 1, TRG_NEEDLE = 2} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
|
||||
static bool MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
static bool RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
static int CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg) ;
|
||||
static bool FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTrgA, int&nEdgeA, int& nTrgB, int& nEdgeB) ;
|
||||
static bool FlipTrg( INTVECTOR& vTr, int nTrgA, int nTrgB, int nEdgeA, int nEdgeB) ;
|
||||
static bool TestAdjacentOnEdge( INTVECTOR& vTr, int nTrgA, int nEdgeA, int nTrgTest1, int nTrgTest2, int& nTrgB, int& nEdgeB) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool FORCE_EARCUT_HPP = false ;
|
||||
static bool FORCE_FIST = false ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// In : PolyLine
|
||||
@@ -49,8 +56,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
|
||||
if ( PL.GetPointNbr() < 4)
|
||||
if ( PL.GetPointNbr() < 4 || ! PL.IsClosed())
|
||||
return false ;
|
||||
|
||||
// se fist ( e geometria più complessa di un quadrilatero)
|
||||
if ( FORCE_FIST && PL.GetPointNbr() > 5)
|
||||
return MakeByFist( {PL}, vPt, vTr) ;
|
||||
|
||||
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
|
||||
double dArea ;
|
||||
Plane3d plPlane ;
|
||||
@@ -117,6 +129,11 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// se una sola polilinea mi riconduco al caso precedente
|
||||
if ( vPL.size() == 1)
|
||||
return Make( vPL[0], vPt, vTr) ;
|
||||
|
||||
// se fist
|
||||
if ( FORCE_FIST)
|
||||
return MakeByFist( vPL, vPt, vTr) ;
|
||||
|
||||
// verifico che la polilinea esterna sia chiusa e piana e calcolo il piano medio del poligono
|
||||
double dArea ;
|
||||
Plane3d plExtPlane ;
|
||||
@@ -134,7 +151,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea2, 50 * EPS_SMALL) ||
|
||||
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// forzo esecuzione triangolazione con earcut.hpp
|
||||
if ( FORCE_EARCUT_HPP) {
|
||||
@@ -236,32 +253,30 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// se non ho PolyLine, allora non faccio nulla
|
||||
if ( int( vPLORIG.size()) == 0)
|
||||
if ( vPLORIG.empty())
|
||||
return true ;
|
||||
|
||||
|
||||
POLYLINEVECTOR vPL ;
|
||||
Vector3d vtN ;
|
||||
// se non sono stati passate le info per ordinare le polyline allora le ordino
|
||||
// se non sono stati passate le info per ordinare le polyline allora le ordino
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if( vnPLIndMatPre.size() == 0){
|
||||
if ( vnPLIndMatPre.empty()) {
|
||||
if ( ! CalcRegionPolyLines( vPLORIG, vtN, vnPLIndMat, vbInvert))
|
||||
return false ;
|
||||
vPL = vPLORIG ;
|
||||
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.back().Invert() ;
|
||||
}
|
||||
for ( int i = 0 ; i < int( vbInvert.size()) ; i++) {
|
||||
if ( vbInvert[i])
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ho già calcolato e riordinato tutto, devo solo fare una copia delle polyline
|
||||
// non serve fare le eventuali inversioni delle polyline, perché se è già stata calcolata la matrice dei chunck allora sono GIà state invertire
|
||||
// ho già calcolato e riordinato tutto, devo solo fare una copia delle polyline
|
||||
// non serve fare le eventuali inversioni delle polyline, perché se è già stata calcolata la matrice dei chunck allora sono già state invertire
|
||||
vPL = vPLORIG ;
|
||||
vnPLIndMat = vnPLIndMatPre ;
|
||||
}
|
||||
|
||||
|
||||
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
|
||||
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
|
||||
@@ -276,7 +291,7 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
|
||||
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
|
||||
vTr.push_back( nSize + vTr_tmp[t]) ;
|
||||
}
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -449,7 +464,7 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vTr.push_back( vPol[i]) ;
|
||||
vTr.push_back( vPol[vNext[i]]) ;
|
||||
}
|
||||
// �Delete� vertex v[i] by redirecting next and previous links
|
||||
// Delete vertex v[i] by redirecting next and previous links
|
||||
// of neighboring verts past it. Decrement vertex count
|
||||
vNext[vPrev[i]] = vNext[i] ;
|
||||
vPrev[vNext[i]] = vPrev[i] ;
|
||||
@@ -578,7 +593,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
vEar[vNext[i]] = EAS_NULL ;
|
||||
// �Delete� vertex v[i] by redirecting next and previous links
|
||||
// Delete vertex v[i] by redirecting next and previous links
|
||||
// of neighboring verts past it. Decrement vertex count
|
||||
vNext[vPrev[i]] = vNext[i] ;
|
||||
vPrev[vNext[i]] = vPrev[i] ;
|
||||
@@ -716,7 +731,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
vEar[vNext[i]] = EAS_NULL ;
|
||||
// �Delete� vertex v[i] by redirecting next and previous links
|
||||
// Delete vertex v[i] by redirecting next and previous links
|
||||
// of neighboring verts past it. Decrement vertex count
|
||||
vNext[vPrev[i]] = vNext[i] ;
|
||||
vPrev[vNext[i]] = vPrev[i] ;
|
||||
@@ -803,14 +818,14 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
}
|
||||
}
|
||||
// If vertex k is inside the ear triangle, then this is not an ear
|
||||
else if ( TestPointInTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
|
||||
else if ( TestPointInOrOnTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
|
||||
bIsEar = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The �ear� triangle is clockwise so v[i] is not an ear
|
||||
// The ear triangle is clockwise so v[i] is not an ear
|
||||
bIsEar = false ;
|
||||
}
|
||||
|
||||
@@ -963,6 +978,28 @@ Triangulate::TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// test if point p is inside or on the border of triangle (a, b, c)
|
||||
bool
|
||||
Triangulate::TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
|
||||
{
|
||||
// If P is on a vertex is considered inside
|
||||
if ( AreSamePoint( ptP, ptA))
|
||||
return true ;
|
||||
if ( AreSamePoint( ptP, ptB))
|
||||
return true ;
|
||||
if ( AreSamePoint( ptP, ptC))
|
||||
return true ;
|
||||
// If P is on the right of at least one edge is outside
|
||||
if ( TriangleIsCCW( ptA, ptP, ptB, EPS_SMALL))
|
||||
return false ;
|
||||
if ( TriangleIsCCW( ptB, ptP, ptC, EPS_SMALL))
|
||||
return false ;
|
||||
if ( TriangleIsCCW( ptC, ptP, ptA, EPS_SMALL))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd)
|
||||
@@ -1155,14 +1192,14 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// non ho trovato alcunch�, errore
|
||||
// non ho trovato alcunchè, errore
|
||||
if ( nI == - 1)
|
||||
return false ;
|
||||
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
|
||||
if ( AreSamePointApprox( ptInt, vPt[nI]))
|
||||
return true ;
|
||||
// devo ora verificare che il segmento che unisce i punti non intersechi altri lati del contorno esterno
|
||||
// altrimenti tengo il punto con raggio pi� vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
|
||||
// altrimenti tengo il punto con raggio più vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
|
||||
int nJ = nI ;
|
||||
Point3d ptPa = ptP ;
|
||||
Point3d ptPb = vPt[nI] ;
|
||||
@@ -1178,7 +1215,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
||||
double dMinTan = INFINITO ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < nNumPt ; ++ i) {
|
||||
// salto il punto gi� trovato
|
||||
// salto il punto già trovato
|
||||
if ( i == nJ)
|
||||
continue ;
|
||||
// verifico se sta nel triangolo
|
||||
@@ -1214,7 +1251,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
||||
bool
|
||||
Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const Point3d& ptCorn, const Point3d& ptNext)
|
||||
{
|
||||
// la parte valida del settore � a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
|
||||
// la parte valida del settore è a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
|
||||
// se corner convesso
|
||||
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
|
||||
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
|
||||
@@ -1229,13 +1266,381 @@ Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const
|
||||
bool
|
||||
ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi)
|
||||
{
|
||||
// se il nuovo inizio coincide col vecchio, non devo fare alcunch�
|
||||
// se il nuovo inizio coincide col vecchio, non devo fare alcunchè
|
||||
if ( nNewStart == 0)
|
||||
return true ;
|
||||
// se il nuovo indice � oltre la dimensione del vettore, errore
|
||||
// se il nuovo indice è oltre la dimensione del vettore, errore
|
||||
if ( nNewStart >= int( vPi.size()))
|
||||
return false ;
|
||||
// ciclo di aggiustamento
|
||||
rotate( vPi.begin(), vPi.begin() + nNewStart, vPi.end()) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzioni per triangolare usando la libreria FIST
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg)
|
||||
{
|
||||
Vector3d vtV1 = vPt[vTr[3*nTrg + 1]] - vPt[vTr[3*nTrg]] ;
|
||||
Vector3d vtV2 = vPt[vTr[3*nTrg + 2]] - vPt[vTr[3*nTrg + 1]] ;
|
||||
Vector3d vtN = vtV1 ^ vtV2 ;
|
||||
double dSqN = vtN.SqLen() ;
|
||||
|
||||
double dSqLen1 = vtV1.SqLen() ;
|
||||
double dSqLen2 = vtV2.SqLen() ;
|
||||
double dSqLen3 = ( vtV1 + vtV2).SqLen() ;
|
||||
// un triangolo è invalido ( needle o cap) se viene scartato dai controlli di AddTriangle
|
||||
if ( dSqN < SQ_EPS_ZERO || dSqN < SQ_EPS_TRIA_H * max( {dSqLen1, dSqLen2, dSqLen3})) {
|
||||
if ( dSqLen1 < SQ_EPS_ZERO || dSqLen2 < SQ_EPS_ZERO || dSqLen3 < SQ_EPS_ZERO)
|
||||
return TRG_NEEDLE ;
|
||||
else
|
||||
return TRG_CAP ;
|
||||
}
|
||||
else
|
||||
return TRG_STD ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FlipTrg( INTVECTOR& vTr, int nTA, int nTB, int nEA, int nEB)
|
||||
{
|
||||
vTr[3*nTA + nEA] = vTr[3*nTB + ( nEB + 2) % 3] ;
|
||||
vTr[3*nTB + nEB] = vTr[3*nTA + ( nEA + 2) % 3] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TestAdjacentOnEdge( INTVECTOR& vTr, int nTA, int nEA, int nTTest1, int nTTest2, int& nTB, int& nEB)
|
||||
{
|
||||
// individuo quale triangolo tra nTTest1 e nTTest2 è quello adiacente a nTA lungo il lato nEA
|
||||
nTB = -1 ;
|
||||
nEB = -1 ;
|
||||
// recupero i vertici di nEA
|
||||
int nV1 = vTr[3*nTA + nEA] ;
|
||||
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
|
||||
|
||||
// verifico se è TTest1 quello adiacente
|
||||
if ( vTr[3*nTTest1] == nV2 && vTr[3*nTTest1+1] == nV1) {
|
||||
nEB = 0 ;
|
||||
nTB = nTTest1 ;
|
||||
}
|
||||
else if ( vTr[3*nTTest1+1] == nV2 && vTr[3*nTTest1+2] == nV1) {
|
||||
nEB = 1 ;
|
||||
nTB = nTTest1 ;
|
||||
}
|
||||
else if ( vTr[3*nTTest1] == nV1 && vTr[3*nTTest1+2] == nV2) {
|
||||
nEB = 2 ;
|
||||
nTB = nTTest1 ;
|
||||
}
|
||||
// verifico se è TTest2 quello adiacente
|
||||
else if ( vTr[3*nTTest2] == nV2 && vTr[3*nTTest2+1] == nV1) {
|
||||
nEB = 0 ;
|
||||
nTB = nTTest2 ;
|
||||
}
|
||||
else if ( vTr[3*nTTest2+1] == nV2 && vTr[3*nTTest2+2] == nV1) {
|
||||
nEB = 1 ;
|
||||
nTB = nTTest2 ;
|
||||
}
|
||||
else if ( vTr[3*nTTest2] == nV1 && vTr[3*nTTest2+2] == nV2) {
|
||||
nEB = 2 ;
|
||||
nTB = nTTest2 ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTA, int& nEA, int& nTB, int& nEB)
|
||||
{
|
||||
// recupero il lato più lungo del triangolo nTA
|
||||
nEA = -1 ;
|
||||
double dMaxLen = -1 ;
|
||||
for ( int j = 0 ; j < 3 ; j++) {
|
||||
double dCurrLen = SqDist( vPt[vTr[3*nTA + j]], vPt[vTr[3*nTA + ( j+1)%3]]) ;
|
||||
if ( dCurrLen > dMaxLen) {
|
||||
dMaxLen = dCurrLen ;
|
||||
nEA = j ;
|
||||
}
|
||||
}
|
||||
|
||||
// cerco il triangolo nTB adiacente a nTA lungo nEA
|
||||
nTB = -1 ;
|
||||
nEB = -1 ;
|
||||
int nV1 = vTr[3*nTA + nEA] ;
|
||||
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
|
||||
int nTria = vTr.size() / 3 ;
|
||||
for ( int j = 0 ; j < nTria ; j++) {
|
||||
if ( j == nTA)
|
||||
continue ;
|
||||
if ( vTr[3*j] == nV2 && vTr[3*j+1] == nV1) {
|
||||
nEB = 0 ;
|
||||
nTB = j ;
|
||||
break ;
|
||||
}
|
||||
else if ( vTr[3*j+1] == nV2 && vTr[3*j+2] == nV1) {
|
||||
nEB = 1 ;
|
||||
nTB = j ;
|
||||
break ;
|
||||
}
|
||||
else if ( vTr[3*j] == nV1 && vTr[3*j+2] == nV2) {
|
||||
nEB = 2 ;
|
||||
nTB = j ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// scorro tutti i triangoli alla ricerca di triangoli validi per FIST ma invalidi per le nostre tolleranze.
|
||||
// I triangoli invalidi possono essere di due tipologie: cap o needle.
|
||||
// I triangoli cap se eliminati danno origine a T-junctions, quindi devono essere gestiti opportunamente con dei flip.
|
||||
// I triangoli needle se eliminati non sono problematici, ma i loro vertici coincidenti vanno gestiti opportunamente nel
|
||||
// calcolo delle adiacenze dei triangoli cap.
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
int nTria = int( vTr.size()) / 3 ;
|
||||
INTVECTOR vCapTria ;
|
||||
INTVECTOR vNeedleTria ;
|
||||
BOOLVECTOR vbIsValidTria( nTria, true) ;
|
||||
bool bRemovedTrg = false ;
|
||||
|
||||
for ( int i = 0 ; i < nTria ; i ++) {
|
||||
int nTrgType = CalcTriangleType( vPt, vTr, i) ;
|
||||
if ( nTrgType == TRG_CAP) {
|
||||
vbIsValidTria[i] = false ;
|
||||
vCapTria.emplace_back( i) ;
|
||||
}
|
||||
else if ( nTrgType == TRG_NEEDLE) {
|
||||
vNeedleTria.emplace_back( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// se non ci sono triangoli cap non c'è bisogno di modifiche
|
||||
if ( vCapTria.empty())
|
||||
return true ;
|
||||
|
||||
// 1) elimino i triangoli di tipo needle gestendo i vertici coincidenti
|
||||
if ( ! vNeedleTria.empty()) {
|
||||
bRemovedTrg = true ;
|
||||
for ( int i = 0 ; i < int( vNeedleTria.size()) ; i++) {
|
||||
int nT = vNeedleTria[i] ;
|
||||
if ( vTr[3*nT] != vTr[3*nT+1] && vTr[3*nT] != vTr[3*nT+2] && vTr[3*nT+1] != vTr[3*nT+2]) {
|
||||
// individuo i vertici coincidenti
|
||||
int nOldId = -1 ;
|
||||
int nNewId = -1 ;
|
||||
Vector3d vtV1 = vPt[vTr[3*nT+1]] - vPt[vTr[3*nT]] ;
|
||||
if ( vtV1.SqLen() < SQ_EPS_ZERO) {
|
||||
// vertici coincidenti 0 e 1
|
||||
nOldId = vTr[3*nT] ;
|
||||
nNewId = vTr[3*nT+1] ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtV2 = vPt[vTr[3*nT+2]] - vPt[vTr[3*nT+1]] ;
|
||||
if ( vtV2.SqLen() < SQ_EPS_ZERO) {
|
||||
// vertici coincidenti 1 e 2
|
||||
nOldId = vTr[3*nT+1] ;
|
||||
nNewId = vTr[3*nT+2] ;
|
||||
}
|
||||
else {
|
||||
// vertici coincidenti 0 e 2
|
||||
nOldId = vTr[3*nT] ;
|
||||
nNewId = vTr[3*nT+2] ;
|
||||
}
|
||||
}
|
||||
// aggiorno il vettore dei triangoli unificando i vertici coincidenti
|
||||
for ( int k = 0 ; k < int( vTr.size()) ; k ++) {
|
||||
if ( vTr[k] == nOldId)
|
||||
vTr[k] = nNewId ;
|
||||
}
|
||||
}
|
||||
// annullo il triangolo
|
||||
vTr[3*nT] = -1 ;
|
||||
vTr[3*nT+1] = -1 ;
|
||||
vTr[3*nT+2] = -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) sistemo i triangoli di tipo cap
|
||||
for ( int i = 0 ; i < int( vCapTria.size()) ; i++) {
|
||||
|
||||
int nTA = vCapTria[i] ;
|
||||
// verifico se il triangolo è già stato resto valido ( da una catena)
|
||||
if ( vbIsValidTria[nTA])
|
||||
continue ;
|
||||
|
||||
// trovo l'adiacenza sul suo lato più lungo
|
||||
int nEA = -1 ;
|
||||
int nEB = -1 ;
|
||||
int nTB = -1 ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
|
||||
|
||||
if ( nTB == -1) {
|
||||
// se non ha un triangolo adiacente posso annullarlo
|
||||
vTr[3*nTA] = -1 ;
|
||||
vTr[3*nTA+1] = -1 ;
|
||||
vTr[3*nTA+2] = -1 ;
|
||||
vbIsValidTria[nTA] = true ;
|
||||
bRemovedTrg = true ;
|
||||
continue ;
|
||||
}
|
||||
else if ( vbIsValidTria[nTB]) {
|
||||
// se è adiacente è valido, eseguo il flip
|
||||
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
|
||||
vbIsValidTria[nTA] = true ;
|
||||
}
|
||||
else {
|
||||
// se adiacente è invalido, individuo una catena di triangoli invalidi da risolvere non appena si indentifica
|
||||
// adiacenza con triangolo valido
|
||||
INTVECTOR vChain, vChainEdges ;
|
||||
vChain.emplace_back( nTA) ;
|
||||
vChainEdges.emplace_back( nEA) ;
|
||||
int nTCurr = nTB ;
|
||||
int nEOther ;
|
||||
while ( nTCurr != -1 && ! vbIsValidTria[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
int nTOther, nECurr ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTCurr, nECurr, nTOther, nEOther) ;
|
||||
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTrg( vTr, nTCurr, nTOther, nECurr, nEOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena tra i due appena flippati
|
||||
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTCurr, nTOther, nTB, nEB) ;
|
||||
nTOther = nTB ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nECurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
|
||||
if ( nTCurr == -1) {
|
||||
bRemovedTrg = true ;
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
if ( vbIsValidTria[vChain[k]])
|
||||
continue ;
|
||||
vTr[3*vChain[k]] = -1 ;
|
||||
vTr[3*vChain[k] + 1] = -1 ;
|
||||
vTr[3*vChain[k] + 2] = -1 ;
|
||||
vbIsValidTria[vChain[k]] = true ;
|
||||
}
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido
|
||||
else {
|
||||
FlipTrg( vTr, vChain.back(), nTCurr, vChainEdges.back(), nEOther) ;
|
||||
vbIsValidTria[vChain.back()] = true ;
|
||||
int nTrgTest1 = vChain.back() ;
|
||||
int nTrgTest2 = nTCurr ;
|
||||
for ( int j = int( vChain.size()-2) ; j >= 0 ; j--) {
|
||||
// triangolo corrente
|
||||
int nTA = vChain[j] ;
|
||||
if ( vbIsValidTria[nTA])
|
||||
continue ;
|
||||
int nEA = vChainEdges[j] ;
|
||||
// devo trovare il nuovo adiacente dopo il flip dei successivi nella catena
|
||||
TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ;
|
||||
// flip per rendere valido il triangolo corrente
|
||||
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
|
||||
vbIsValidTria[nTA] = true ;
|
||||
// aggiorno i trg di test per lo step successivo
|
||||
nTrgTest1 = nTA ;
|
||||
nTrgTest2 = nTB ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se sono stati annullati dei triangoli, li rimuovo dal vettore
|
||||
if ( bRemovedTrg) {
|
||||
INTVECTOR vTrTmp ;
|
||||
vTrTmp.reserve( vTr.size()) ;
|
||||
for ( int i = 0 ; i < int( vTr.size()) ; i++)
|
||||
if ( vTr[i] != -1)
|
||||
vTrTmp.emplace_back( vTr[i]) ;
|
||||
swap( vTr, vTrTmp) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
// opzioni di triangolazione
|
||||
rt_options rt_opt ;
|
||||
InitDefaults( &rt_opt) ;
|
||||
rt_opt.ears_top = false ;
|
||||
rt_opt.ears_random = false ;
|
||||
rt_opt.ears_sorted = true ;
|
||||
rt_opt.ears_fancy = true ;
|
||||
|
||||
// creo oggetto di fist per triangolazione
|
||||
global_struct fist ;
|
||||
InitGlobalStruct( &fist, &rt_opt, true) ;
|
||||
|
||||
// allocazione ottimizzata degli array di fist
|
||||
int nLoops = int( vPL.size()) ;
|
||||
int nVertices = 0 ;
|
||||
for ( int i = 0 ; i < nLoops ; i ++)
|
||||
nVertices += ( vPL[i].GetPointNbr() - 1) ;
|
||||
OptimizeMemoryAllocation( &fist, nLoops, nVertices) ;
|
||||
|
||||
// assegno i dati a fist
|
||||
for ( int i = 0 ; i < nLoops ; i ++) {
|
||||
// salvo i vertici saltando il primo punto ( coincide con l'ultimo)
|
||||
Point3d pt ;
|
||||
if ( ! vPL[i].GetFirstPoint( pt))
|
||||
return false ;
|
||||
while ( vPL[i].GetNextPoint( pt))
|
||||
StoreVertex( &fist.c_vertex, pt.x, pt.y, pt.z) ;
|
||||
// salvo il loop
|
||||
int nPoints = vPL[i].GetPointNbr() ;
|
||||
AddLoopInFace( &fist, nLoops - 1, i == 0, nPoints - 1) ;
|
||||
}
|
||||
StoreGroupNumber( &fist.c_list, &fist.c_vertex) ;
|
||||
|
||||
// eseguo triangolazione
|
||||
Triangulate( &fist) ;
|
||||
|
||||
// recupero i vertici da fist
|
||||
vPt.reserve( fist.c_vertex.num_vertices) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_vertices ; i ++)
|
||||
vPt.emplace_back( fist.c_vertex.vertices[i].x, fist.c_vertex.vertices[i].y, fist.c_vertex.vertices[i].z) ;
|
||||
|
||||
// recupero i triangoli da fist
|
||||
vTr.reserve( 3 * fist.c_vertex.num_triangles) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) {
|
||||
vTr.emplace_back( fist.c_vertex.triangles[i].v1) ;
|
||||
vTr.emplace_back( fist.c_vertex.triangles[i].v2) ;
|
||||
vTr.emplace_back( fist.c_vertex.triangles[i].v3) ;
|
||||
}
|
||||
|
||||
// rimuovo eventuali triangoli validi per fist ma invalidi per le nostre tolleranze
|
||||
RemoveFistInvalidTrg( vPt, vTr) ;
|
||||
|
||||
// chiudo fist e dealloco la sua memoria
|
||||
FIST_TerminateProgram( &fist) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class Triangulate
|
||||
bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ;
|
||||
bool TestIntersection( const Point3d& ptA1, const Point3d& ptA2, const Point3d& ptB1, const Point3d& ptB2) ;
|
||||
bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
|
||||
bool TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
|
||||
bool SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) ;
|
||||
bool GetPntVectorFromPolyline( const PolyLine& PL, bool bXmaxStart, PNTVECTOR& vPi) ;
|
||||
bool GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& nI) ;
|
||||
|
||||
+105
-17
@@ -497,7 +497,7 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
|
||||
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
||||
int nPos = ic + jc * m_nNx[0] ;
|
||||
if ( m_Values[0][nPos].size() > 0) {
|
||||
if ( ! m_Values[0][nPos].empty()) {
|
||||
Point3d ptP = m_MapFrame.Orig() + dX * m_MapFrame.VersX() + dY * m_MapFrame.VersY() ;
|
||||
b3Loc.Add( ptP + m_Values[0][nPos][0].dMin * m_MapFrame.VersZ()) ;
|
||||
b3Loc.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * m_MapFrame.VersZ()) ;
|
||||
@@ -541,7 +541,7 @@ VolZmap::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
|
||||
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
||||
int nPos = ic + jc * m_nNx[0] ;
|
||||
if ( nPos >= 0 && m_Values[0][nPos].size() > 0) {
|
||||
if ( nPos >= 0 && ! m_Values[0][nPos].empty()) {
|
||||
Point3d ptP = frUse.Orig() + dX * frUse.VersX() + dY * frUse.VersY() ;
|
||||
b3Ref.Add( ptP + m_Values[0][nPos][0].dMin * frUse.VersZ()) ;
|
||||
b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ;
|
||||
@@ -1520,14 +1520,14 @@ VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
|
||||
|
||||
// ciclo sulle griglie
|
||||
bool bCompleted = true ;
|
||||
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
|
||||
for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
|
||||
// definisco dei sistemi di riferimento ausiliari
|
||||
Frame3d frMapFrame ;
|
||||
if ( g == 0)
|
||||
if ( nG == 0)
|
||||
frMapFrame = m_MapFrame ;
|
||||
else if ( g == 1)
|
||||
else if ( nG == 1)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
|
||||
else if ( g == 2)
|
||||
else if ( nG == 2)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
|
||||
|
||||
// oggetto per calcolo massivo intersezioni
|
||||
@@ -1538,33 +1538,121 @@ VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
|
||||
vector<future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
// se dimensione griglia in X maggiore di dimensione Y
|
||||
if ( m_nNx[g] > m_nNy[g]) {
|
||||
int nDexNum = m_nNx[g] / nThreadMax ;
|
||||
int nRemainder = m_nNx[g] % nThreadMax ;
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
|
||||
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
// se dimensione griglia in Y maggiore di dimensione X
|
||||
else {
|
||||
int nDexNum = m_nNy[g] / nThreadMax ;
|
||||
int nRemainder = m_nNy[g] % nThreadMax ;
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
|
||||
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bCompleted)
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm)
|
||||
{
|
||||
// controllo sulla superficie
|
||||
double dVol ;
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() ||
|
||||
! pStm->GetVolume( dVol) || dVol < 0)
|
||||
return false ;
|
||||
|
||||
// controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente
|
||||
BBox3d BBox_stm, BBox_curr ;
|
||||
if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr))
|
||||
return false ;
|
||||
BBox3d BBox_inters ;
|
||||
if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty())
|
||||
return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap
|
||||
Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone
|
||||
|
||||
// ciclo sulle griglie
|
||||
bool bCompleted = true ;
|
||||
for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
|
||||
// definisco dei sistemi di riferimento ausiliari
|
||||
Frame3d frMapFrame ;
|
||||
if ( nG == 0)
|
||||
frMapFrame = m_MapFrame ;
|
||||
else if ( nG == 1)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
|
||||
else if ( nG == 2)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
|
||||
|
||||
// oggetto per calcolo massivo intersezioni
|
||||
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
||||
|
||||
// numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector<future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
// se dimensione griglia in X maggiore di dimensione Y
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::SubtractMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
// se dimensione griglia in Y maggiore di dimensione X
|
||||
else {
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::SubtractMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,23 @@
|
||||
#include "ObjGraphicsMgr.h"
|
||||
#include "GeoObjRW.h"
|
||||
#include "Tool.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <tuple>
|
||||
|
||||
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
|
||||
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
|
||||
|
||||
// ------------------------- FORWARD -------------------------------------------------------------
|
||||
class IntersParLinesSurfTm ;
|
||||
class BBox3d ;
|
||||
class Frame3d ;
|
||||
|
||||
// ------------------------- STRUTTURE -----------------------------------------------------------
|
||||
struct AppliedVector {
|
||||
@@ -33,6 +41,55 @@ struct AppliedVector {
|
||||
int nPropIndex ;
|
||||
} ;
|
||||
|
||||
struct MachInfo {
|
||||
int n5AxisType ;
|
||||
int nSub ;
|
||||
int nStepCnt ;
|
||||
double dSide ;
|
||||
Vector3d vtDirTipStartEx ;
|
||||
Vector3d vtDirTipEndEx ;
|
||||
Vector3d vtDirTopStartEx ;
|
||||
Vector3d vtDirTopEndEx ;
|
||||
VCT3DVECTOR vvtTipStartAux ;
|
||||
VCT3DVECTOR vvtTipEndAux ;
|
||||
VCT3DVECTOR vvtTopStartAux ;
|
||||
VCT3DVECTOR vvtTopEndAux ;
|
||||
Vector3d vtDirTip ;
|
||||
Vector3d vtDirTop ;
|
||||
MachInfo( int n5AxisType_, int nSub_, int nStepCnt_, double dSide_, Vector3d vtDirTipStartEx_, Vector3d vtDirTipEndEx_, Vector3d vtDirTopStartEx_, Vector3d vtDirTopEndEx_,
|
||||
VCT3DVECTOR vvtTipStartAux_, VCT3DVECTOR vvtTipEndAux_, VCT3DVECTOR vvtTopStartAux_, VCT3DVECTOR vvtTopEndAux_, Vector3d vtDirTip_, Vector3d vtDirTop_) :
|
||||
n5AxisType( n5AxisType_), nSub( nSub_), nStepCnt( nStepCnt_), dSide( dSide_), vtDirTipStartEx( vtDirTipStartEx_), vtDirTipEndEx( vtDirTipEndEx_), vtDirTopStartEx( vtDirTopStartEx_), vtDirTopEndEx( vtDirTopEndEx_),
|
||||
vvtTipStartAux( vvtTipStartAux_), vvtTipEndAux( vvtTipEndAux_), vvtTopStartAux( vvtTopStartAux_), vvtTopEndAux( vvtTopEndAux_), vtDirTip( vtDirTip_), vtDirTop( vtDirTop_) {}
|
||||
};
|
||||
|
||||
struct ToolInfo {
|
||||
double dHeight ;
|
||||
double dMaxRad ;
|
||||
double dMinRad ;
|
||||
double dTan ;
|
||||
double dMaxH ;
|
||||
double dMinH ;
|
||||
double dMaxRadApprox ;
|
||||
double dMinRadApprox ;
|
||||
BBox3d bbStartCyl ;
|
||||
BBox3d bbEndCyl ;
|
||||
Frame3d frToolStart ;
|
||||
Frame3d frToolEnd ;
|
||||
//Vector3d vtDirTip ;
|
||||
//Vector3d vtDirTop ;
|
||||
ToolInfo( double dHeight_, double dMaxRad_, double dMinRad_, double dTan_, double dMaxH_, double dMinH_, double dMaxRadApprox_, double dMinRadApprox_,
|
||||
BBox3d bbStartCyl_, BBox3d bbEndCyl_, Frame3d frToolStart_, Frame3d frToolEnd_) :
|
||||
dHeight ( dHeight_), dMaxRad( dMaxRad_), dMinRad( dMinRad_), dTan( dTan_), dMaxH( dMaxH_), dMinH( dMinH_), dMaxRadApprox( dMaxRadApprox_), dMinRadApprox( dMinRadApprox_),
|
||||
bbStartCyl( bbStartCyl_), bbEndCyl( bbEndCyl_), frToolStart( frToolStart_), frToolEnd( frToolEnd_) {}
|
||||
};
|
||||
|
||||
struct SurfBezForInters {
|
||||
SurfBezier sBez ;
|
||||
BBox3d bbSurf ;
|
||||
double A1, A2, B1, B2, C1, C2 ;
|
||||
Vector3d d ;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{
|
||||
@@ -80,10 +137,13 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0.) override ;
|
||||
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
ISurfTriMesh* GetSurfTriMesh( void) const override ;
|
||||
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
|
||||
bool GetVolume( double& dVol) const override ;
|
||||
bool IsTriDexel( void) const override
|
||||
@@ -93,7 +153,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{ return m_nDexVoxRatio ; }
|
||||
bool ChangeResolution( int nDexVoxRatio) override ;
|
||||
void SetShowEdges( bool bShow) override
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
{ m_bShowEdges = bShow ; // qui � necessario far ricreare la grafica
|
||||
m_OGrMgr.Clear() ; }
|
||||
bool GetShowEdges( void) const override
|
||||
{ return m_bShowEdges ; }
|
||||
@@ -144,6 +204,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool RemovePart( int nPart) override ;
|
||||
int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
@@ -258,9 +319,12 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
|
||||
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) ;
|
||||
bool SelectGeneralMotion( int nGrid, const PNTVECTOR& ptPs, const PNTVECTOR& ptPe, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int n5AxisType) ;
|
||||
bool SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) ;
|
||||
bool InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) ;
|
||||
bool InitializeAuxPoints( Point3d ptTop1s[3], Point3d ptTop1e[3], Point3d ptTop2s[3], Point3d ptTop2e[3],
|
||||
Point3d ptBottom1s[3], Point3d ptBottom1e[3], Point3d ptBottom2s[3], Point3d ptBottom2e[3]) ;
|
||||
// SOTTRAZIONI
|
||||
// UTENSILI
|
||||
// Asse di simmetria parallelo a Z
|
||||
@@ -288,11 +352,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
// lavorazioni a 5 assi
|
||||
bool GenTool_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
|
||||
bool Cyl_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, double dHeightCorr = 0, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
|
||||
bool CylBall_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
|
||||
bool Conus_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe, int nToolNum, int n5AxisType = VolZmap::Move5Axis::ACROSS) ;
|
||||
|
||||
// COMPONENTI
|
||||
// Asse di simmetria diretto come l'asse Z
|
||||
@@ -311,7 +380,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realt� MillingPerp
|
||||
// Asse di simmetria con orientazione generica
|
||||
bool CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
|
||||
double dHei, double dRad, bool bTapB, bool bTapT, int nToolNum) ;
|
||||
@@ -327,7 +396,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
// lavorazioni a 5 assi
|
||||
bool Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe,
|
||||
double dHeight, double dMaxRad, double dMinRad, int nToolNum, int n5AxisType) ;
|
||||
bool CompCyl_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtLs, const VCT3DVECTOR& vtLe,
|
||||
double dHeight, double dRadius, int nToolNum,int n5AxisType) ;
|
||||
bool CompConus_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& ptE, const VCT3DVECTOR& vtToolDirS, const VCT3DVECTOR& vtToolDirE, double dHei, double dMaxRad, double dMinRad,
|
||||
bool bTapB, bool bTapT,const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum, int n5AxisType) ;
|
||||
|
||||
// Generica traslazione sfera
|
||||
bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ;
|
||||
// Additivi
|
||||
@@ -341,7 +418,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// BBox per utensili e solidi semplici con movimenti di traslazione
|
||||
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, const Vector3d& vtV2,
|
||||
double dRad, double dTipRad, double dHei,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
|
||||
@@ -372,6 +449,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& frTruncPyramFrame, double dSegMin, double dSegMax, double dHeight,
|
||||
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
|
||||
bool IntersToolLine( const Point3d& ptLineStart, const Vector3d& vtLineDir, const MachInfo& mi, const ToolInfo& ti,
|
||||
const std::vector<SurfBezForInters>& vSurfBez,PNTVEC3DVECTOR& vInters, INTVECTOR& vSurfInters) const ;
|
||||
bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ;
|
||||
// Voxel: esistenza e passaggio da N a ijk per i voxel
|
||||
bool IsValidVoxel( int nN) const ;
|
||||
@@ -432,17 +511,55 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di superfici
|
||||
bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
public :
|
||||
// ------------------------- ENUM ----------------------------------------------------------------
|
||||
enum MillingPhase {
|
||||
COUNT_START_VOL = 0 ,
|
||||
ONLY_LATERAL_SURF = 1 ,
|
||||
COUNT_END_VOL = 2 ,
|
||||
COUNT_START_END = 3
|
||||
} ;
|
||||
|
||||
enum Move5Axis{
|
||||
ALONG_CONVEX = 0 ,
|
||||
ALONG_CONCAVE = 1 ,
|
||||
ACROSS = 2 ,
|
||||
NO_BASE_INTERS = 3
|
||||
} ;
|
||||
|
||||
enum CuttingSurface {
|
||||
NONE = -1,
|
||||
TOOL = 0 ,
|
||||
BZ = 1 ,
|
||||
LATERAL = 2
|
||||
} ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2} ;
|
||||
enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2, OFFSET = 3} ;
|
||||
static const int N_MAPS = 3 ;
|
||||
static const int N_VOXBLOCK = 32 ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore propriet� temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
|
||||
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
|
||||
@@ -476,8 +593,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable BOOLVECTOR m_BlockToUpdate ;
|
||||
mutable INTVECTOR m_BlockUpdatingCounter ;
|
||||
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto
|
||||
// Se >= 0 è il numero di componenti connesse
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non � noto
|
||||
// Se >= 0 � il numero di componenti connesse
|
||||
|
||||
mutable std::vector<VoxelContainer> m_InterBlockVox ;
|
||||
mutable SharpTriaMatrix m_InterBlockOriginalSharpTria ;
|
||||
|
||||
+116
-20
@@ -17,6 +17,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
@@ -597,6 +598,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||
@@ -691,7 +693,100 @@ VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex)
|
||||
VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||
{
|
||||
// controllo sui parametri
|
||||
if ( nMap < 0 || nMap > 2 ||
|
||||
nInfI < 0 || nInfI > m_nNx[nMap] ||
|
||||
nSupI < 0 || nSupI > m_nNx[nMap] ||
|
||||
nInfJ < 0 || nInfJ > m_nNy[nMap] ||
|
||||
nSupJ < 0 || nSupJ > m_nNy[nMap])
|
||||
return false ;
|
||||
|
||||
// determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
|
||||
// definisco la retta da intersecare con la trimesh
|
||||
double dX = ( i + 0.5) * m_dStep ;
|
||||
double dY = ( j + 0.5) * m_dStep ;
|
||||
Point3d ptP0( dX, dY, 0) ;
|
||||
|
||||
// intersezioni della retta con la TriMesh
|
||||
ILSIVECTOR IntersectionResults ;
|
||||
intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ;
|
||||
|
||||
// rimuovo le intersezioni in eccesso
|
||||
for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) {
|
||||
int nJ = nI + 1 ; // prima successiva
|
||||
int nK = nJ + 1 ; // seconda successiva
|
||||
int nT = nK + 1 ; // terza successiva
|
||||
// determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh
|
||||
int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
// parametri dell'intersezione sulla linea
|
||||
double dUJ = IntersectionResults[nJ].dU ;
|
||||
double dUK = IntersectionResults[nK].dU ;
|
||||
// controllo coerenza con segni...
|
||||
if ( nSgnI != 0 && nSgnI == nSgnJ &&
|
||||
nSgnK != 0 && nSgnK == nSgnT &&
|
||||
nSgnI == - nSgnT &&
|
||||
abs( dUJ - dUK) < EPS_SMALL) {
|
||||
// ... ed elimino le intersezioni in eccesso...
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nK) ;
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nJ) ;
|
||||
}
|
||||
}
|
||||
|
||||
int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide
|
||||
bool bInside = false ; // Flag entrata/uscita per tratto di retta
|
||||
Point3d ptIn ; Vector3d vtInN ;
|
||||
|
||||
// per ogni intersezione valida trovata...
|
||||
for ( int k = 0 ; k < nInt ; ++ k) {
|
||||
// ricavo il tipo di intersezione
|
||||
int nIntType = IntersectionResults[k].nILTT ;
|
||||
// se c'è intersezione
|
||||
if ( nIntType != ILTT_NO) {
|
||||
// ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta)
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
|
||||
// se entro nella superficie trimesh...
|
||||
if ( dCos < - EPS_SMALL) {
|
||||
ptIn = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Surf.GetFacetNormal( nF, vtInN) ;
|
||||
bInside = true ; // entrata
|
||||
}
|
||||
// ...se esco dalla superficie trimesh ( prima sono per forza entrato)
|
||||
else if ( dCos > EPS_SMALL && bInside) {
|
||||
Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita
|
||||
|
||||
// Aggiungo un tratto al dexel
|
||||
SubtractIntervals( nMap, i, j,
|
||||
ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
- vtInN, - vtOutN, 0, true) ;
|
||||
bInside = false ; // uscita
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
|
||||
{
|
||||
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
||||
double dVol ;
|
||||
@@ -704,14 +799,15 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
// Determino il bounding box della TriMesh
|
||||
BBox3d SurfBBox ;
|
||||
Surf.GetLocalBBox( SurfBBox) ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
|
||||
|
||||
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
|
||||
// quindi espandiamo il bounding box per ovviare al problema.
|
||||
SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ;
|
||||
if ( dExtraBox > EPS_ZERO)
|
||||
SurfBBox.Expand( dExtraBox) ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
|
||||
|
||||
// Sistema di riferimento intrinseco dello Zmap
|
||||
m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ;
|
||||
@@ -760,15 +856,15 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
|
||||
// ciclo sulle griglie
|
||||
bool bCompleted = true ;
|
||||
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
|
||||
for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
|
||||
|
||||
// Definisco dei sistemi di riferimento ausiliari
|
||||
Frame3d frMapFrame ;
|
||||
if ( g == 0)
|
||||
if ( nG == 0)
|
||||
frMapFrame = m_MapFrame ;
|
||||
else if ( g == 1)
|
||||
else if ( nG == 1)
|
||||
frMapFrame.Set( ptMapOrig, Y_AX, Z_AX, X_AX) ;
|
||||
else if ( g == 2)
|
||||
else if ( nG == 2)
|
||||
frMapFrame.Set( ptMapOrig, Z_AX, X_AX, Y_AX) ;
|
||||
|
||||
// Oggetto per calcolo massivo intersezioni
|
||||
@@ -778,28 +874,28 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
if ( m_nNx[g] > m_nNy[g]) {
|
||||
int nDexNum = m_nNx[g] / nThreadMax ;
|
||||
int nRemainder = m_nNx[g] % nThreadMax ;
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g,
|
||||
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nDexNum = m_nNy[g] / nThreadMax ;
|
||||
int nRemainder = m_nNy[g] % nThreadMax ;
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g,
|
||||
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,7 +921,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = ( IsBox() ? BOX : GENERIC) ;
|
||||
m_nShape = ( dExtraBox > EPS_ZERO && IsBox() ? BOX : GENERIC) ;
|
||||
|
||||
// Aggiornamento dello stato
|
||||
m_nStatus = OK ;
|
||||
|
||||
+35
-5
@@ -19,6 +19,7 @@
|
||||
#include "MC_Tables.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
@@ -571,6 +572,35 @@ VolZmap::GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
VolZmap::GetSurfTriMesh( void) const
|
||||
{
|
||||
// controllo che lo Zmap sia valido
|
||||
if ( ! IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// inizializzo la superficie
|
||||
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
|
||||
return nullptr ;
|
||||
PointGrid3d VertGrid ; VertGrid.Init( 50000) ;
|
||||
|
||||
// ciclo lungo i blocchi dello Zmap
|
||||
for ( int nB = 0 ; nB < GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria ;
|
||||
GetBlockTriangles( nB, vTria) ;
|
||||
if ( ! pStm->AddTriaFromZMap( vTria, VertGrid))
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// sistemo la topologia
|
||||
if ( ! pStm->AdjustTopologyFromZMap())
|
||||
return nullptr ;
|
||||
|
||||
return ( Release( pStm)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
VolZmap::GetBlockCount( void) const
|
||||
@@ -1142,7 +1172,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
}
|
||||
|
||||
// Controllo se il voxel ha una sola faccia che giace in un piano canonico e quindi ha gestione speciale
|
||||
if ( m_nShape != BOX) {
|
||||
if ( m_nShape != BOX && m_nShape != OFFSET) {
|
||||
// Faccia XY normale Z+
|
||||
if ( nIndex == 15) {
|
||||
int nTool ; double dPos ;
|
||||
@@ -4013,7 +4043,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
|
||||
bool bNotEmpty = false ;
|
||||
for ( nj = 0 ; nj < 2 ; ++ nj) {
|
||||
int nDex = nj * int( m_nNx[0]) + ni ;
|
||||
if ( ! m_Values[0].empty() && m_Values[0][nDex].size() > 0) {
|
||||
if ( ! m_Values[0].empty() && ! m_Values[0][nDex].empty()) {
|
||||
bNotEmpty = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -4026,7 +4056,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
|
||||
bool bNotEmpty = false ;
|
||||
for ( mj = 0 ; mj < 2 ; ++ mj) {
|
||||
int nDex = mj * int( m_nNx[1]) + mi ;
|
||||
if ( ! m_Values[1].empty() && m_Values[1][nDex].size() > 0) {
|
||||
if ( ! m_Values[1].empty() && ! m_Values[1][nDex].empty()) {
|
||||
bNotEmpty = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -4056,7 +4086,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
|
||||
bool bNotEmpty = false ;
|
||||
for ( nj = int( m_nNy[0]) - 1 ; nj > int( m_nNy[0]) - 3 ; -- nj) {
|
||||
int nDex = nj * int( m_nNx[0]) + ni ;
|
||||
if ( ! m_Values[0].empty() && m_Values[0][nDex].size() > 0) {
|
||||
if ( ! m_Values[0].empty() && ! m_Values[0][nDex].empty()) {
|
||||
bNotEmpty = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -4069,7 +4099,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
|
||||
bool bNotEmpty = false ;
|
||||
for ( mj = int( m_nNy[1]) - 1 ; mj > int( m_nNy[1]) - 3 ; -- mj) {
|
||||
int nDex = mj * int( m_nNx[1]) + mi ;
|
||||
if ( ! m_Values[1].empty() && m_Values[1][nDex].size() > 0) {
|
||||
if ( ! m_Values[1].empty() && ! m_Values[1][nDex].empty()) {
|
||||
bNotEmpty = true ;
|
||||
break ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetSurfTm.cpp Data : 09.06.25 Versione : 2.7e3
|
||||
// Contenuto : Dichiarazione della funzione per calcolare l'offset di superfici TriMesh
|
||||
// mediante Zmap
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 09.06.25 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "CurveLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per sottrarre intervalli lungo un Dexel per l'offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap)
|
||||
{
|
||||
// TODO -- Aggiustare eventuali tolleranze
|
||||
return SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap)
|
||||
{
|
||||
// TODO -- Aggiustare eventuali tolleranze
|
||||
return AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
|
||||
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nTool)
|
||||
{
|
||||
// determino il Box della sfera posizionata su tale vertice
|
||||
BBox3d BBoxSphere( ptV - dOffs * Vector3d( 1., 1., 1.),
|
||||
ptV + dOffs * Vector3d( 1., 1., 1.)) ;
|
||||
// determino gli intervalli di interesse mediante intersezione con Box della sfera
|
||||
int nStartI = max( 0, int( BBoxSphere.GetMin().x / m_dStep)) ;
|
||||
int nEndI = min( m_nNx[nGrid] - 1, int( BBoxSphere.GetMax().x / m_dStep)) ;
|
||||
int nStartJ = max( 0, int( BBoxSphere.GetMin().y / m_dStep)) ;
|
||||
int nEndJ = min( m_nNy[nGrid] - 1, int( BBoxSphere.GetMax().y / m_dStep)) ;
|
||||
// aggiorno gli spilloni interessati
|
||||
double dSqRad = dOffs * dOffs ;
|
||||
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
||||
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
||||
double dX = ( i + 0.5) * m_dStep ;
|
||||
double dY = ( j + 0.5) * m_dStep ;
|
||||
Point3d ptC( dX, dY, 0.) ;
|
||||
double dStSqDXY = SqDistXY( ptC, ptV) ;
|
||||
if ( dStSqDXY < dSqRad) {
|
||||
double dMin = ptV.z - sqrt( dSqRad - dStSqDXY) ;
|
||||
Vector3d vtNmin = Point3d( dX, dY, dMin) - ptV ;
|
||||
vtNmin.Normalize() ;
|
||||
double dMax = ptV.z + sqrt( dSqRad - dStSqDXY) ;
|
||||
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ;
|
||||
vtNmax.Normalize() ;
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
|
||||
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid,
|
||||
int nTool)
|
||||
{
|
||||
// determino la lunghezza dello spigolo corrente
|
||||
double dH = Dist( ptP1, ptP2) ;
|
||||
// asse del cilindro
|
||||
Vector3d vtV = ptP2 - ptP1 ; vtV.Normalize() ;
|
||||
// calcolo box del cilindro
|
||||
BBox3d BBoxCylinder ;
|
||||
BBoxCylinder.Add( ptP1) ;
|
||||
BBoxCylinder.Add( ptP2) ;
|
||||
if ( AreSameOrOppositeVectorApprox( vtV, X_AX))
|
||||
BBoxCylinder.Expand( 0., abs( dOffs), abs( dOffs)) ;
|
||||
else if ( AreSameOrOppositeVectorApprox( vtV, Y_AX))
|
||||
BBoxCylinder.Expand( abs( dOffs), 0., abs( dOffs)) ;
|
||||
else if ( AreSameOrOppositeVectorApprox( vtV, Z_AX))
|
||||
BBoxCylinder.Expand( abs( dOffs), abs( dOffs), 0.) ;
|
||||
else {
|
||||
double dExpandX = abs( dOffs) * sqrt( 1 - vtV.x * vtV.x) ;
|
||||
double dExpandY = abs( dOffs) * sqrt( 1 - vtV.y * vtV.y) ;
|
||||
double dExpandZ = abs( dOffs) * sqrt( 1 - vtV.z * vtV.z) ;
|
||||
BBoxCylinder.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// determino gli intervalli di interesse mediante intersezione
|
||||
int nStartI = max( 0, int( BBoxCylinder.GetMin().x / m_dStep)) ;
|
||||
int nEndI = min( m_nNx[nGrid] - 1, int( BBoxCylinder.GetMax().x / m_dStep)) ;
|
||||
int nStartJ = max( 0, int( BBoxCylinder.GetMin().y / m_dStep)) ;
|
||||
int nEndJ = min( m_nNy[nGrid] - 1, int( BBoxCylinder.GetMax().y / m_dStep)) ;
|
||||
// aggiorno gli spilloni interessati
|
||||
Frame3d CylFrame ;
|
||||
if ( ! CylFrame.Set( ptP1, vtV))
|
||||
return false ;
|
||||
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
||||
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
|
||||
// L'idea è quella di creare uno ZMap a partire dal Box complessivo delle superfici TriMesh :
|
||||
// - le superfici chiuse possono già inserire i rispettivi spilloni
|
||||
// - le superfici aperte non danno contributo
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
|
||||
{
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
|
||||
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
|
||||
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
|
||||
|
||||
// --- se una sola superficie
|
||||
if ( int( vSurf.size()) == 1) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
// --- se superficie chiusa posso direttamente creare lo Zmap iniziale
|
||||
if ( vSurf[0]->IsClosed()) {
|
||||
// definisco lo Zamp a partire dall'espansione del Box della superficie
|
||||
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
|
||||
return false ;
|
||||
}
|
||||
// --- se superficie aperta, lo creo inizialmente vuoto a partire dal suo Box
|
||||
BBox3d BBoxSurf ;
|
||||
vSurf[0]->GetLocalBBox( BBoxSurf) ;
|
||||
BBoxSurf.Expand( dBoxExpansion) ;
|
||||
if ( ! CreateEmpty( BBoxSurf.GetMin(), BBoxSurf.GetDimX(), BBoxSurf.GetDimY(), BBoxSurf.GetDimZ(), dTol, true))
|
||||
return false ;
|
||||
}
|
||||
// --- se più superfici
|
||||
else {
|
||||
// calcolo il Box complessivo
|
||||
BBox3d BBoxGlob ;
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// calcolo il Box della superficie
|
||||
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
|
||||
// aggiungo il Box a quello complessivo
|
||||
BBoxGlob.Add( BBoxSurf) ;
|
||||
}
|
||||
// definisco uno Zmap vuoto a partire dal Box
|
||||
BBoxGlob.Expand( dBoxExpansion) ;
|
||||
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
|
||||
return false ;
|
||||
// aggiungo tutte le superfici chiuse
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0 || ! Surf->IsClosed())
|
||||
continue ;
|
||||
if ( ! AddSurfTm( Surf))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
|
||||
// L'idea è quella di creare uno ZMap vuoto a partire dal Box complessivo delle superfici TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
|
||||
{
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
|
||||
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
|
||||
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
|
||||
|
||||
// calcolo il Box complessivo
|
||||
BBox3d BBoxGlob ;
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// calcolo il Box della superficie
|
||||
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
|
||||
// aggiungo il Box a quello complessivo
|
||||
BBoxGlob.Add( BBoxSurf) ;
|
||||
}
|
||||
// definisco uno Zmap vuoto a partire dal Box
|
||||
BBoxGlob.Expand( dBoxExpansion) ;
|
||||
return ( CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie aperta
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// da studiare...
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie chiusa
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// controlli sulla superficie
|
||||
if ( Surf == nullptr || ! Surf->IsClosed())
|
||||
return false ;
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
|
||||
// Assunzioni :
|
||||
// - Idea Generale di Offset
|
||||
// - Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
|
||||
// centro il vertice corrente)
|
||||
// - Su ogni lato viene definito un cilindro ( con raggio di base pari al valore di Offset
|
||||
// e asse definito dall'edge stesso)
|
||||
// - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
|
||||
// definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
|
||||
//
|
||||
// - Segno dell'Offset :
|
||||
// - Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
|
||||
// - Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
|
||||
//
|
||||
// - Semplificazione entità :
|
||||
// La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
|
||||
// "spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
|
||||
// calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
|
||||
// troppo i conti introducendo variabili angolari che non sommando tutte le parti.
|
||||
//
|
||||
|
||||
// definisco vettore di frame Locali alle 3 griglie
|
||||
FRAME3DVECTOR vFrGrid( 4) ;
|
||||
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
|
||||
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
|
||||
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
|
||||
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
|
||||
|
||||
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
|
||||
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
|
||||
// ----------------------- Cilindri e Sfere -----------------------
|
||||
// scorro gli Edge della superficie
|
||||
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
|
||||
// recupero lo spigolo
|
||||
int nV1, nV2, nF1, nF2 ; double dAng ;
|
||||
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
|
||||
// controllo se il cilindro serve
|
||||
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
|
||||
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
|
||||
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
|
||||
if ( dAng * dOffs < 0)
|
||||
continue ;
|
||||
// recupero le coordinate dei vertici
|
||||
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
|
||||
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
|
||||
// esprimo gli estremi nel riferimento della griglia
|
||||
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dal cilindro
|
||||
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
|
||||
return false ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dalla sfera
|
||||
if ( ! vbVert[nV1]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
if ( ! vbVert[nV2]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
vbVert[nV1] = true ;
|
||||
vbVert[nV2] = true ;
|
||||
}
|
||||
// ----------------------- Facce -----------------------
|
||||
// scorro tutte le facce definendo una superficie di estrusione
|
||||
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
|
||||
// recupero lo faccia
|
||||
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
|
||||
// recupero la normale della faccia
|
||||
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
|
||||
// definisco la superficie di estrusione
|
||||
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vPL[i].Translate( - abs( dOffs) * vtN) ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
vpCrvs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
// recupero la TriMesh di estrusione
|
||||
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
|
||||
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
// aggiorno gli spilloni
|
||||
if ( dOffs > 0.)
|
||||
AddSurfTm( pStmExtr) ;
|
||||
else
|
||||
SubtractSurfTm( pStmExtr) ;
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet Thickening] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie generica (aperta o chiusa)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// controlli sulla superficie
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
|
||||
// non inizializzo lo Zmap, semplicemente lavoro con facce, spigoli e vertici
|
||||
|
||||
// definisco vettore di frame Locali alle 3 griglie
|
||||
FRAME3DVECTOR vFrGrid( 4) ;
|
||||
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
|
||||
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
|
||||
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
|
||||
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
|
||||
|
||||
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
|
||||
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
|
||||
// ----------------------- Cilindri e Sfere -----------------------
|
||||
// scorro gli Edge della superficie
|
||||
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
|
||||
// recupero lo spigolo
|
||||
int nV1, nV2, nF1, nF2 ; double dAng ;
|
||||
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
|
||||
// recupero le coordinate dei vertici
|
||||
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
|
||||
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
|
||||
// esprimo gli estremi nel riferimento della griglia
|
||||
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dal cilindro
|
||||
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dalla sfera
|
||||
if ( ! vbVert[nV1]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP1, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
}
|
||||
if ( ! vbVert[nV2]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP2, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
vbVert[nV1] = true ;
|
||||
vbVert[nV2] = true ;
|
||||
}
|
||||
// ----------------------- Facce -----------------------
|
||||
// scorro tutte le facce definendo una superficie di estrusione
|
||||
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
|
||||
// recupero lo faccia
|
||||
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
|
||||
// recupero la normale della faccia
|
||||
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
|
||||
// definisco la superficie di estrusione
|
||||
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vPL[i].Translate( - abs( dOffs) * vtN) ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
vpCrvs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
// recupero la TriMesh di estrusione
|
||||
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
|
||||
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
// aggiorno gli spilloni
|
||||
AddSurfTm( pStmExtr) ;
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da un
|
||||
// vettore di superfici TriMesh (aperte o chiuse).
|
||||
// Definizione :
|
||||
// - Lo Zmap di Offset ( positivo o negativo) di una superficie chiusa è automaticamente l'Offset stesso
|
||||
// - Lo Zmap di Offset ( positivo o negativo) di una superficie aperta è ????? ( da capire...)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
|
||||
{
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return true ;
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
|
||||
// inizializzo lo Zmap di Offset a partire dalle superfici
|
||||
if ( ! InitVolZMapOffs( vSurf, dOffs, dTol))
|
||||
return false ;
|
||||
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// se superficie non valida, passo alla successiva
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// aggiorno lo ZMap
|
||||
if ( Surf->IsClosed()) {
|
||||
if ( nType == STMOFF_FILLET) {
|
||||
if ( ! UpdateVolZMapByClosedSurfFilletOffset( Surf, dOffs, dTol))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// --- LE SUPERFICI APERTE SONO PER ORA DISABILITATE ---
|
||||
}
|
||||
}
|
||||
|
||||
m_nShape = OFFSET ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazine di uno Zmap di Fat Offset a partire da un
|
||||
// vettore di superfici TriMesh (aperte o chiuse).
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
|
||||
{
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return true ;
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
|
||||
// inizializzo lo Zmap di Offset a partire dalle superfici
|
||||
if ( ! InitVolZMapThickeningOffs( vSurf, dOffs, dTol))
|
||||
return false ;
|
||||
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// se superficie non valida, passo alla successiva
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
|
||||
// aggiorno lo Zmap
|
||||
if ( nType == STMOFF_FILLET) {
|
||||
if ( ! UpdateVolZMapBySurfThickeningFilletOffset( Surf, dOffs, dTol))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
m_nShape = OFFSET ;
|
||||
return true ;
|
||||
}
|
||||
+1914
-200
File diff suppressed because it is too large
Load Diff
+414
-168
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,9 @@ class Voronoi
|
||||
bool GetVroniPlane( Plane3d& plPlane) const ;
|
||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) ;
|
||||
bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ;
|
||||
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
|
||||
bool CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) ;
|
||||
bool CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) ;
|
||||
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps = true) ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
||||
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
|
||||
|
||||
@@ -81,7 +83,7 @@ class Voronoi
|
||||
bool UpdateVoronoi( double dOffs) ;
|
||||
ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ;
|
||||
bool AdjustOffsetStart( ICurveComposite* pCompo) const ;
|
||||
int GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const ;
|
||||
int GetOffsetCurveSide( const ICurve* pCrv) const ;
|
||||
ICurve* GetBisectorCurve( int i) ;
|
||||
|
||||
private :
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib")
|
||||
#pragma comment(lib, EGTEXTDIR "vroni/Lib/vroni" EGTLIBVER ".lib")
|
||||
#pragma comment(lib, EGTEXTDIR "fist/Lib/fist" EGTLIBVER ".lib")
|
||||
#pragma comment(lib, EGTLIBDIR "EgtGeneral" EGTLIBVER ".lib")
|
||||
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
|
||||
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")
|
||||
|
||||
Reference in New Issue
Block a user