Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 292c2bf87a | |||
| 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 |
+630
-62
@@ -16,11 +16,43 @@
|
|||||||
#include "GeoConst.h"
|
#include "GeoConst.h"
|
||||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||||
#include "/EgtDev/Include/EGkOffsetCurve.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 <thread>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
using namespace std ;
|
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
|
// 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
|
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)
|
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)
|
// Ricerca con metodo di bisezione (si arresta quando il medio è allineato agli estremi)
|
||||||
const int MAX_ITER = 10 ;
|
const int MAX_ITER = 10 ;
|
||||||
int nCount = 0 ;
|
int nCount = 0 ;
|
||||||
@@ -53,13 +90,15 @@ CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel,
|
|||||||
while ( nCount < MAX_ITER) {
|
while ( nCount < MAX_ITER) {
|
||||||
// verifica del punto medio
|
// verifica del punto medio
|
||||||
ptMid.z = 0 ;
|
ptMid.z = 0 ;
|
||||||
Point3d ptTest = GetToGlob( ptMid + cavTstm.GetToolHeight() * Z_AX, frGrid) ;
|
Point3d ptTest = GetToGlob( ptMid + ( cavTstm.GetToolHeight() - dOffsR) * Z_AX, frGrid) ;
|
||||||
double dMove ;
|
double dMove ;
|
||||||
cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dMove) ;
|
cavTstm.TestPosition( ptTest, frGrid.VersZ(), frGrid.VersZ(), dMove) ;
|
||||||
ptMid.z = dMove ;
|
ptMid.z = dMove ;
|
||||||
// se sta sulla linea che unisce gli estremi, basta interpolazione lineare
|
// se estremi coincidenti, allora mi fermo
|
||||||
if ( abs( ptMid.z - ( ptP1.z + ptP2.z) / 2) < EPS_SMALL / 2)
|
if ( SqDistXY( ptP1, ptP2) < 4 * SQ_EPS_SMALL) {
|
||||||
return Media( ptP1, ptP2, ( ptP1.z - dLevel) / ( ptP1.z - ptP2.z)) ;
|
ptMid.z = dLevel ;
|
||||||
|
return ptMid ;
|
||||||
|
}
|
||||||
// altrimenti nuova suddivisione della parte con estremi da parte opposta rispetto al livello
|
// altrimenti nuova suddivisione della parte con estremi da parte opposta rispetto al livello
|
||||||
bool b1On = ( ptP1.z > dLevel) ;
|
bool b1On = ( ptP1.z > dLevel) ;
|
||||||
bool bMidOn = ( ptMid.z > dLevel) ;
|
bool bMidOn = ( ptMid.z > dLevel) ;
|
||||||
@@ -76,24 +115,29 @@ CalcPoint( const Point3d& ptS, const Point3d& ptE, double dLevel,
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
static int
|
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},
|
static int LineTable[16][5] = { { 0, -1, -1, -1, -1}, // ( 0)
|
||||||
{ 1, 0, 3, -1, -1},
|
{ 1, 0, 3, -1, -1}, // ( 1)
|
||||||
{ 1, 1, 0, -1, -1},
|
{ 1, 1, 0, -1, -1}, // ( 2)
|
||||||
{ 1, 1, 3, -1, -1},
|
{ 1, 1, 3, -1, -1}, // ( 3)
|
||||||
{ 1, 2, 1, -1, -1},
|
{ 1, 2, 1, -1, -1}, // ( 4)
|
||||||
{ 2, 0, 1, 2, 3},
|
{ 2, 0, 1, 2, 3}, // ( 5.0) -> primo caso ambiguo
|
||||||
{ 1, 2, 0, -1, -1},
|
{ 1, 2, 0, -1, -1}, // ( 6)
|
||||||
{ 1, 2, 3, -1, -1},
|
{ 1, 2, 3, -1, -1}, // ( 7)
|
||||||
{ 1, 3, 2, -1, -1},
|
{ 1, 3, 2, -1, -1}, // ( 8)
|
||||||
{ 1, 0, 2, -1, -1},
|
{ 1, 0, 2, -1, -1}, // ( 9)
|
||||||
{ 2, 1, 2, 3, 0},
|
{ 2, 1, 2, 3, 0}, // ( 10.0) -> primo caso ambiguo
|
||||||
{ 1, 1, 2, -1, -1},
|
{ 1, 1, 2, -1, -1}, // ( 11)
|
||||||
{ 1, 3, 1, -1, -1},
|
{ 1, 3, 1, -1, -1}, // ( 12)
|
||||||
{ 1, 0, 1, -1, -1},
|
{ 1, 0, 1, -1, -1}, // ( 13)
|
||||||
{ 1, 3, 0, -1, -1},
|
{ 1, 3, 0, -1, -1}, // ( 14)
|
||||||
{ 0, -1, -1, -1, -1}} ;
|
{ 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
|
// flag fuori dai limiti
|
||||||
if ( nFlag < 0 || nFlag > 15)
|
if ( nFlag < 0 || nFlag > 15)
|
||||||
return -1 ;
|
return -1 ;
|
||||||
@@ -108,12 +152,42 @@ ProcessSquare( int nFlag, int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
|||||||
}
|
}
|
||||||
// due linee
|
// due linee
|
||||||
else if ( LineTable[nFlag][0] == 2) {
|
else if ( LineTable[nFlag][0] == 2) {
|
||||||
nI1s = LineTable[nFlag][1] ;
|
// controllo in quale caso sono
|
||||||
nI1e = LineTable[nFlag][2] ;
|
if ( nFlag == 5) {
|
||||||
nI2s = LineTable[nFlag][3] ;
|
// caso 5.0
|
||||||
nI2e = LineTable[nFlag][4] ;
|
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 2 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1 ;
|
return -1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +195,7 @@ ProcessSquare( int nFlag, int& nI1s, int& nI1e, int& nI2s, int& nI2e)
|
|||||||
static bool
|
static bool
|
||||||
TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd, int nFirst, int nLast,
|
TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd, int nFirst, int nLast,
|
||||||
const DBLVECTOR& vdGrid, int nStepX, double dStep,
|
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) {
|
for ( int k = nFirst ; k <= nLast ; ++ k) {
|
||||||
// recupero i differenti indici
|
// 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 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)]} ;
|
Point3d ptE{ ptS.x + ( bOnX ? dStep : 0), ptS.y + ( bOnX ? 0 : dStep), vdGrid[nInd + ( bOnX ? 1 : nStepX + 1)]} ;
|
||||||
// calcolo il punto
|
// calcolo il punto
|
||||||
Point3d ptQ = CalcPoint( ptS, ptE, dLevel, cavTstm, frGrid) ;
|
Point3d ptQ = CalcPoint( ptS, ptE, dLevel, dOffsR, cavTstm, frGrid) ;
|
||||||
umEdgePnt[ nKey] = ptQ ;
|
umEdgePnt[ nKey] = ptQ ;
|
||||||
}
|
}
|
||||||
return true ;
|
return true ;
|
||||||
@@ -142,9 +216,324 @@ TestSubEdges( unordered_map<int, Point3d>& umEdgePnt, const INTVECTOR& vEdgeInd,
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
static bool
|
static bool
|
||||||
MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep, double dRad,
|
ModifyPolyLineToSharped( PNTIVECTOR& vAdvPt, const CAvToolSurfTm& cavTstm, const Frame3d& frGrid,
|
||||||
double dLevel, const ICAvToolSurfTm& cavTstm, const Frame3d &frGrid, POLYLINEVECTOR& vPL)
|
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 ;
|
||||||
|
|
||||||
|
// 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 nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) {
|
||||||
|
// 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
|
||||||
|
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) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
// 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)) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
vPL[nPol].Clear() ;
|
||||||
|
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)
|
||||||
|
vPL[nPol].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)
|
||||||
|
vPL[nPol].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) ;
|
||||||
|
vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ;
|
||||||
|
vPL[nPol].AddUPoint( ++ dPar, ptTest) ;
|
||||||
|
vPL[nPol].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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// riposiziono la polyLine
|
||||||
|
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||||
|
// 6° gruppo, curve composita derivante dalla polyline
|
||||||
|
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||||
|
pCrvCompoPoly->FromPolyLine( vPL[nPol]) ;
|
||||||
|
//pCrvCompoPoly->SetExtrusion( frGrid.VersZ()) ;
|
||||||
|
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||||
|
vvCol[5].emplace_back( RED) ;
|
||||||
|
// 7° gruppo, controOffset
|
||||||
|
OffsetCurve offsCrv ;
|
||||||
|
offsCrv.Make( pCrvCompoPoly, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||||
|
pCrvCompoPoly.Set( ConvertCurveToComposite( offsCrv.GetLongerCurve())) ;
|
||||||
|
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( Release( pCrvCompoPoly))) ;
|
||||||
|
vvCol[6].emplace_back( WHITE) ;
|
||||||
|
string myName = Sharped_Edges_Debug_File_Name +
|
||||||
|
to_string( nChunk) + "_" +
|
||||||
|
to_string( nPol) + "_" +
|
||||||
|
to_string( dLevel) + "_" +
|
||||||
|
to_string( dAngTol) + ".nge" ;
|
||||||
|
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||||
|
#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) ;
|
||||||
|
if ( SIC.GetCrossOrOverlapIntersCount() > 0)
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Analizzo gli edge da cui passano le curve cercate
|
||||||
unordered_map<int, Point3d> umEdgePnt( 4 * ( nStepX + nStepY)) ;
|
unordered_map<int, Point3d> umEdgePnt( 4 * ( nStepX + nStepY)) ;
|
||||||
INTVECTOR vEdgeInd ;
|
INTVECTOR vEdgeInd ;
|
||||||
@@ -161,9 +550,49 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
bool bUp1 = ( vdGrid[nInd1] > dLevel) ;
|
bool bUp1 = ( vdGrid[nInd1] > dLevel) ;
|
||||||
bool bUp2 = ( vdGrid[nInd2] > dLevel) ;
|
bool bUp2 = ( vdGrid[nInd2] > dLevel) ;
|
||||||
bool bUp3 = ( vdGrid[nInd3] > 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
|
// se tutti uguali, passo al successivo
|
||||||
if ( bUp0 == bUp1 && bUp0 == bUp2 && bUp0 == bUp3)
|
if ( bUp0 == bUp1 && bUp0 == bUp2 && bUp0 == bUp3)
|
||||||
continue ;
|
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
|
// verifico quali calcolare
|
||||||
if ( bUp0 != bUp1) {
|
if ( bUp0 != bUp1) {
|
||||||
int nKey = 2 * nInd0 ;
|
int nKey = 2 * nInd0 ;
|
||||||
@@ -202,7 +631,7 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
bool bOk = true ;
|
bool bOk = true ;
|
||||||
// Se un solo thread o pochi punti
|
// Se un solo thread o pochi punti
|
||||||
if ( nThreadMax <= 1 || nEdgeCnt < 50) {
|
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
|
// altrimenti
|
||||||
else {
|
else {
|
||||||
@@ -219,7 +648,7 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
future<bool> vRes[MAX_PARTS] ;
|
future<bool> vRes[MAX_PARTS] ;
|
||||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||||
vRes[i] = async( launch::async, &TestSubEdges, ref( umEdgePnt), cref( vEdgeInd), vFstLst[i].first, vFstLst[i].second,
|
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
|
// attendo i risultati
|
||||||
int nFin = 0 ;
|
int nFin = 0 ;
|
||||||
while ( nFin < nPartCnt) {
|
while ( nFin < nPartCnt) {
|
||||||
@@ -257,15 +686,37 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
int vKey[4] = { 2 * nInd0, 2 * nInd1 + 1, 2 * nInd3, 2 * nInd0 + 1} ;
|
int vKey[4] = { 2 * nInd0, 2 * nInd1 + 1, 2 * nInd3, 2 * nInd0 + 1} ;
|
||||||
// calcolo segmenti da inserire
|
// calcolo segmenti da inserire
|
||||||
int nI1s, nI1e, nI2s, nI2e ;
|
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)
|
if ( nSegCnt == -1)
|
||||||
return false ;
|
return false ;
|
||||||
else if ( nSegCnt == 1) {
|
else if ( nSegCnt == 1) {
|
||||||
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
||||||
Point3d ptL1e = umEdgePnt.find( vKey[nI1e])->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) ;
|
vBiPnt.emplace_back( ptL1s, ptL1e) ;
|
||||||
Vector3d vtDir1 = ptL1e - ptL1s ; vtDir1.Normalize() ;
|
Vector3d vtDir1 = ptL1e - ptL1s ; vtDir1.Normalize() ;
|
||||||
chainC.AddCurve( int( vBiPnt.size()), ptL1s, vtDir1, ptL1e, vtDir1) ;
|
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) {
|
else if ( nSegCnt == 2) {
|
||||||
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
Point3d ptL1s = umEdgePnt.find( vKey[nI1s])->second ;
|
||||||
@@ -278,10 +729,33 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
vBiPnt.emplace_back( ptL2s, ptL2e) ;
|
vBiPnt.emplace_back( ptL2s, ptL2e) ;
|
||||||
Vector3d vtDir2 = ptL2e - ptL2s ; vtDir2.Normalize() ;
|
Vector3d vtDir2 = ptL2e - ptL2s ; vtDir2.Normalize() ;
|
||||||
chainC.AddCurve( int( vBiPnt.size()), ptL2s, vtDir2, ptL2e, vtDir2) ;
|
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
|
// Recupero i contorni
|
||||||
INTVECTOR vnId ;
|
INTVECTOR vnId ;
|
||||||
while ( chainC.GetChainFromNear( ORIG, false, vnId)) {
|
while ( chainC.GetChainFromNear( ORIG, false, vnId)) {
|
||||||
@@ -292,7 +766,6 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
Point3d ptCurr = vBiPnt[vnId[i]-1].second ;
|
Point3d ptCurr = vBiPnt[vnId[i]-1].second ;
|
||||||
crvCompo.AddLine( ptCurr) ;
|
crvCompo.AddLine( ptCurr) ;
|
||||||
}
|
}
|
||||||
// la chiudo
|
|
||||||
crvCompo.Close() ;
|
crvCompo.Close() ;
|
||||||
// elimino le parti allineate
|
// elimino le parti allineate
|
||||||
crvCompo.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
crvCompo.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
||||||
@@ -300,22 +773,51 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
|||||||
double dCmpArea ;
|
double dCmpArea ;
|
||||||
if ( ! crvCompo.GetAreaXY( dCmpArea) || ( dCmpArea < 0 && abs( dCmpArea) < 2 * dStep * dStep))
|
if ( ! crvCompo.GetAreaXY( dCmpArea) || ( dCmpArea < 0 && abs( dCmpArea) < 2 * dStep * dStep))
|
||||||
continue ;
|
continue ;
|
||||||
// per test mettere a 1
|
// memorizzo i risultati ottenuti
|
||||||
#if 0
|
vPL.emplace_back( PolyLine()) ;
|
||||||
vPL.emplace_back( PolyLine()) ;
|
crvCompo.ApproxWithLines( 0, 0, ICurve::APL_SPECIAL, vPL.back()) ;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 non ho impostato un utensile, devo effettuare un contro-offset
|
||||||
|
if ( ! bTool) {
|
||||||
|
POLYLINEVECTOR vPL_Offs ;
|
||||||
|
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||||
|
CurveComposite crvCompo ;
|
||||||
|
if ( ! crvCompo.FromPolyLine( vPL[i]))
|
||||||
|
return false ;
|
||||||
|
OffsetCurve offsCompo ;
|
||||||
|
offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||||
|
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ;
|
||||||
|
while ( ! IsNull( pCrvOffset)) {
|
||||||
|
PolyLine myPolyLine ;
|
||||||
|
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||||
|
vPL_Offs.emplace_back( myPolyLine) ;
|
||||||
|
pCrvOffset.Set( offsCompo.GetLongerCurve()) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +890,7 @@ CAvSilhouetteSurfTm( const ISurfTriMesh& Stm, const Plane3d& plPlane, double dTo
|
|||||||
|
|
||||||
// calcolo della silhouette con il metodo MarchingSquares
|
// calcolo della silhouette con il metodo MarchingSquares
|
||||||
double dLevel = dLevelOffs ;
|
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 ;
|
return false ;
|
||||||
// riporto nella corretta posizione le curve trovate
|
// riporto nella corretta posizione le curve trovate
|
||||||
for ( auto& PL : vPL)
|
for ( auto& PL : vPL)
|
||||||
@@ -409,7 +911,7 @@ CreateCAvParSilhouettesSurfTm( void)
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
CAvParSilhouettesSurfTm::CAvParSilhouettesSurfTm( 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 +923,43 @@ CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& f
|
|||||||
m_frGrid = frPlanes ;
|
m_frGrid = frPlanes ;
|
||||||
m_dTol = max( dTol, 100 * EPS_SMALL) ;
|
m_dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||||
m_dRad = SQRT1_2 * m_dTol ;
|
m_dRad = SQRT1_2 * m_dTol ;
|
||||||
|
m_dSharpedTol = ANG_TOL_STD_DEG ;
|
||||||
|
m_dOffsR = 0. ;
|
||||||
m_nStepX = 0 ;
|
m_nStepX = 0 ;
|
||||||
m_nStepY = 0 ;
|
m_nStepY = 0 ;
|
||||||
m_dDimZ = 0 ;
|
m_dDimZ = 0 ;
|
||||||
m_dLevelOffs = 0 ;
|
m_dLevelOffs = 0 ;
|
||||||
|
m_dCornRad = 0. ;
|
||||||
|
m_dMaxMat = INFINITO ;
|
||||||
|
m_dOffsR = 0. ;
|
||||||
|
m_dSideAng = 0. ;
|
||||||
|
m_dMaxDepth = 0. ;
|
||||||
m_bGridOk = false ;
|
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 ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,7 +967,7 @@ CAvParSilhouettesSurfTm::SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& f
|
|||||||
bool
|
bool
|
||||||
CAvParSilhouettesSurfTm::Prepare( void)
|
CAvParSilhouettesSurfTm::Prepare( void)
|
||||||
{
|
{
|
||||||
// ingombro delle superfici nel riferimento dei piani
|
// ingombro delle superfici nel riferimento dei piani
|
||||||
BBox3d b3All ;
|
BBox3d b3All ;
|
||||||
Frame3d frInv = GetInvert( m_frGrid) ;
|
Frame3d frInv = GetInvert( m_frGrid) ;
|
||||||
for ( auto pStm : m_vpStm) {
|
for ( auto pStm : m_vpStm) {
|
||||||
@@ -444,8 +978,8 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calcolo dati della griglia
|
// calcolo dati della griglia
|
||||||
const double EXTRA_XY = 1.5 * m_dTol ;
|
const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ;
|
||||||
const double EXTRA_Z = 10 * m_dTol ;
|
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
|
||||||
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
|
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
|
||||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||||
@@ -464,8 +998,25 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// esecuzione della verifica
|
// esecuzione della verifica
|
||||||
if ( ! m_cavTstm.SetStdTool( m_dDimZ, m_dRad, 0))
|
if ( m_dSideAng < EPS_ANG_SMALL)
|
||||||
return false ;
|
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 ;
|
||||||
|
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||||
|
}
|
||||||
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
|
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
|
||||||
return false ;
|
return false ;
|
||||||
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
|
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
|
||||||
@@ -483,6 +1034,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 ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,16 +1063,19 @@ CAvParSilhouettesSurfTm::GetSilhouette( double dLevel, POLYLINEVECTOR& vPL)
|
|||||||
return false ;
|
return false ;
|
||||||
m_bGridOk = true ;
|
m_bGridOk = true ;
|
||||||
|
|
||||||
// calcolo della silhouette con il metodo MarchingSquares
|
|
||||||
dLevel += m_dLevelOffs ;
|
dLevel += m_dLevelOffs ;
|
||||||
|
// controllo se ho impostato un utensile, in caso negativo, la silhouette richiede un contro-offset
|
||||||
double dCalcLevel = max( dLevel, 0.) ;
|
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 ;
|
return false ;
|
||||||
|
|
||||||
// riporto nella corretta posizione le curve trovate
|
// riporto nella corretta posizione le curve trovate
|
||||||
for ( auto& PL : vPL) {
|
for ( auto& PL : vPL) {
|
||||||
if ( dLevel < dCalcLevel - EPS_SMALL)
|
if ( dLevel < dCalcLevel - EPS_SMALL)
|
||||||
PL.Translate( Vector3d{ 0, 0, dLevel - dCalcLevel}) ;
|
PL.Translate( Vector3d{ 0, 0, dLevel - dCalcLevel}) ;
|
||||||
PL.ToGlob( m_frGrid) ;
|
PL.ToGlob( m_frGrid) ;
|
||||||
}
|
}
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
+14
-1
@@ -14,31 +14,44 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CAvToolSurfTm.h"
|
#include "CAvToolSurfTm.h"
|
||||||
|
#include "SurfFlatRegion.h"
|
||||||
#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h"
|
#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h"
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm
|
class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
// generica
|
||||||
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol) override ;
|
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 ;
|
bool GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) override ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
CAvParSilhouettesSurfTm( void) ;
|
CAvParSilhouettesSurfTm( void) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
bool Prepare( void) ;
|
bool Prepare( void) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
CISURFTMPVECTOR m_vpStm ;
|
CISURFTMPVECTOR m_vpStm ;
|
||||||
CAvToolSurfTm m_cavTstm ;
|
CAvToolSurfTm m_cavTstm ;
|
||||||
Frame3d m_frGrid ;
|
Frame3d m_frGrid ;
|
||||||
double m_dTol ;
|
double m_dTol ;
|
||||||
|
double m_dSharpedTol ;
|
||||||
int m_nStepX ;
|
int m_nStepX ;
|
||||||
int m_nStepY ;
|
int m_nStepY ;
|
||||||
double m_dRad ;
|
double m_dRad ;
|
||||||
|
double m_dCornRad ;
|
||||||
|
double m_dMaxMat ;
|
||||||
|
double m_dSideAng ;
|
||||||
|
double m_dOffsR ;
|
||||||
double m_dDimZ ;
|
double m_dDimZ ;
|
||||||
double m_dLevelOffs ;
|
double m_dLevelOffs ;
|
||||||
|
double m_dMaxDepth ;
|
||||||
bool m_bGridOk ;
|
bool m_bGridOk ;
|
||||||
|
bool m_bTool ;
|
||||||
DBLVECTOR m_vdGrid ;
|
DBLVECTOR m_vdGrid ;
|
||||||
} ;
|
} ;
|
||||||
+316
-19
@@ -24,6 +24,7 @@ using namespace std ;
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const int STEP_PE = 50 ;
|
const int STEP_PE = 50 ;
|
||||||
|
const double MAX_MOVE = 20000 ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ICAvToolSurfTm*
|
ICAvToolSurfTm*
|
||||||
@@ -80,7 +81,7 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
|||||||
bool
|
bool
|
||||||
CAvToolSurfTm::AddSurfTm( const ISurfTriMesh& Stm)
|
CAvToolSurfTm::AddSurfTm( const ISurfTriMesh& Stm)
|
||||||
{
|
{
|
||||||
// verifico validità superficie
|
// verifico validità superficie
|
||||||
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &Stm) ;
|
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &Stm) ;
|
||||||
if ( pStm == nullptr || ! pStm->IsValid())
|
if ( pStm == nullptr || ! pStm->IsValid())
|
||||||
return false ;
|
return false ;
|
||||||
@@ -130,7 +131,7 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
|||||||
// Se direzioni non definite, errore
|
// Se direzioni non definite, errore
|
||||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||||
return false ;
|
return false ;
|
||||||
// Se riferimento di movimento già presente
|
// Se riferimento di movimento già presente
|
||||||
if ( m_frMove.IsValid()) {
|
if ( m_frMove.IsValid()) {
|
||||||
// Calcolo nuovo riferimento di movimento
|
// Calcolo nuovo riferimento di movimento
|
||||||
Frame3d frMove ;
|
Frame3d frMove ;
|
||||||
@@ -158,6 +159,47 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
|||||||
return ( dTotDist > - EPS_SMALL) ;
|
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
|
bool
|
||||||
CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
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
|
// Se direzioni non definite, errore
|
||||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||||
return false ;
|
return false ;
|
||||||
// Se vettore vuoto, non devo fare alcunché
|
// Se vettore vuoto, non devo fare alcunché
|
||||||
if ( vPntM.empty())
|
if ( vPntM.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// Calcolo nuovo riferimento di movimento
|
// Calcolo nuovo riferimento di movimento
|
||||||
@@ -239,7 +281,7 @@ CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vecto
|
|||||||
bool
|
bool
|
||||||
CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
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())
|
if ( vPntM.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// Ciclo sui punti da verificare
|
// Ciclo sui punti da verificare
|
||||||
@@ -279,7 +321,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
|||||||
// Se direzioni non definite, errore
|
// Se direzioni non definite, errore
|
||||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||||
return false ;
|
return false ;
|
||||||
// Se lista vuota, non devo fare alcunché
|
// Se lista vuota, non devo fare alcunché
|
||||||
if ( lPntM.empty())
|
if ( lPntM.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// Controllo la tolleranza lineare (se negativa non vanno fatti controlli sui punti medi)
|
// 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 ;
|
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
|
bool
|
||||||
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff)
|
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())
|
if ( lPntM.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// Ciclo sui punti
|
// Ciclo sui punti
|
||||||
@@ -405,6 +529,40 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
|||||||
return true ;
|
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
|
bool
|
||||||
CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
|
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
|
double
|
||||||
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const
|
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 ;
|
double dTotDist = 0 ;
|
||||||
vtTriaN = V_NULL ;
|
vtTriaN = V_NULL ;
|
||||||
for ( auto pStm : m_vSTM) {
|
for ( auto pStm : m_vSTM) {
|
||||||
Triangle3d Tria ;
|
INTVECTOR vTria ;
|
||||||
for ( int nTria = pStm->GetFirstTriangle( Tria) ;
|
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
|
||||||
nTria != SVT_NULL ;
|
for ( int nTria : vTria) {
|
||||||
nTria = pStm->GetNextTriangle( nTria, Tria)) {
|
Triangle3d Tria ;
|
||||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
if ( pStm->GetTriangle( nTria, Tria)) {
|
||||||
if ( dDist < - EPS_SMALL)
|
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
||||||
return -1 ;
|
if ( dDist < - EPS_SMALL)
|
||||||
if ( dDist > EPS_SMALL) {
|
return -1 ;
|
||||||
dTotDist += dDist ;
|
if ( dDist > EPS_SMALL) {
|
||||||
ptT += dDist * vtMove ;
|
dTotDist += dDist ;
|
||||||
vtTriaN = Tria.GetN() ;
|
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) ;
|
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
|
||||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||||
}
|
}
|
||||||
// ciclo sui triangoli che intersecano box in 2d
|
|
||||||
|
// ciclo sui triangoli che intersecano box in 2d
|
||||||
double dTotDist = 0 ;
|
double dTotDist = 0 ;
|
||||||
vtTriaN = V_NULL ;
|
vtTriaN = V_NULL ;
|
||||||
INTVECTOR vnIds ;
|
INTVECTOR vnIds ;
|
||||||
@@ -509,6 +748,64 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d&
|
|||||||
return -1 ;
|
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 ;
|
return dTotDist ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +816,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
|
|||||||
// pulisco HashGrid 2d
|
// pulisco HashGrid 2d
|
||||||
m_HGrids.Clear() ;
|
m_HGrids.Clear() ;
|
||||||
// verifico esistenza superfici
|
// 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 ;
|
return false ;
|
||||||
// creo HashGrid 2d
|
// creo HashGrid 2d
|
||||||
const int LIM_HG_TRIA = 256 ;
|
const int LIM_HG_TRIA = 256 ;
|
||||||
|
|||||||
@@ -34,11 +34,29 @@ class CAvToolSurfTm : public ICAvToolSurfTm
|
|||||||
{ return m_Tool.GetRadius() ; }
|
{ return m_Tool.GetRadius() ; }
|
||||||
double GetToolHeight( void) const override
|
double GetToolHeight( void) const override
|
||||||
{ return m_Tool.GetHeigth() ; }
|
{ 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
|
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
|
||||||
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
|
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
|
||||||
|
|
||||||
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||||
double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ;
|
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 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 ;
|
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
@@ -47,9 +65,12 @@ class CAvToolSurfTm : public ICAvToolSurfTm
|
|||||||
|
|
||||||
private :
|
private :
|
||||||
bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
|
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) ;
|
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 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 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,
|
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 ;
|
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ;
|
||||||
bool PrepareHashGrid( void) ;
|
bool PrepareHashGrid( void) ;
|
||||||
|
|||||||
+638
-271
File diff suppressed because it is too large
Load Diff
+26
-23
@@ -2,7 +2,7 @@
|
|||||||
// EgalTech 2013-2014
|
// EgalTech 2013-2014
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// File : ChainCurves.cpp Data : 20.07.14 Versione : 1.5g3
|
// 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.
|
// curve composite a partire dalle curve date.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -43,10 +43,10 @@ bool
|
|||||||
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
|
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
|
||||||
const Point3d& ptEnd, const Vector3d& vtEnd)
|
const Point3d& ptEnd, const Vector3d& vtEnd)
|
||||||
{
|
{
|
||||||
// verifico validità Id
|
// verifico validità Id
|
||||||
if ( nId <= 0)
|
if ( nId <= 0)
|
||||||
return false ;
|
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)
|
if ( ! m_sCrvId.insert( nId).second)
|
||||||
return true ;
|
return true ;
|
||||||
// inserisco i dati della curva nel vettore
|
// inserisco i dati della curva nel vettore
|
||||||
@@ -68,7 +68,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
|||||||
m_bIsFork = false ;
|
m_bIsFork = false ;
|
||||||
m_vFork.clear() ;
|
m_vFork.clear() ;
|
||||||
|
|
||||||
// recupero l'entità più vicina al punto di start
|
// recupero l'entità più vicina al punto di start
|
||||||
int nStart ;
|
int nStart ;
|
||||||
INTVECTOR vStart ;
|
INTVECTOR vStart ;
|
||||||
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
|
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
|
||||||
@@ -82,7 +82,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
|||||||
// tolgo dal grid
|
// tolgo dal grid
|
||||||
RemoveEntityFromGrid( nId) ;
|
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 ;
|
bool bSkip = false ;
|
||||||
if ( bHaltOnFork) {
|
if ( bHaltOnFork) {
|
||||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptEnd) ;
|
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 ;
|
INTVECTOR vIdsAfter ;
|
||||||
bool bClosed = false ;
|
bool bClosed = false ;
|
||||||
if ( ! bSkip && ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd,
|
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 ;
|
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 ;
|
bool bRevSkip = false ;
|
||||||
if ( bHaltOnFork) {
|
if ( bHaltOnFork) {
|
||||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptStart) ;
|
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 ;
|
INTVECTOR vIdsBefore ;
|
||||||
if ( ! bClosed) {
|
if ( ! bClosed) {
|
||||||
bool bRevClosed ;
|
bool bRevClosed ;
|
||||||
@@ -258,7 +258,7 @@ ChainCurves::RemoveEntityFromGrid( int nId)
|
|||||||
bool
|
bool
|
||||||
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
|
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
|
||||||
{
|
{
|
||||||
// numero di entità candidate
|
// numero di entità candidate
|
||||||
int nSize = int( vStart.size()) ;
|
int nSize = int( vStart.size()) ;
|
||||||
|
|
||||||
// se nessuna, errore
|
// se nessuna, errore
|
||||||
@@ -273,7 +273,7 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
|
|||||||
|
|
||||||
// altrimenti, cerco la migliore
|
// altrimenti, cerco la migliore
|
||||||
int nI = - 1 ;
|
int nI = - 1 ;
|
||||||
double dSqDistMin = SQ_INFINITO ;
|
double dDistMin = INFINITO ;
|
||||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||||
// recupero indice e verso
|
// recupero indice e verso
|
||||||
int nId = abs( vStart[i]) - 1 ;
|
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
|
// calcolo un punto vicino all'estremo lungo la tangente
|
||||||
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
|
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
|
||||||
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
|
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
|
||||||
double dSqDist = SqDist( ptStart, ptNear) ;
|
double dDist = Dist( ptStart, ptNear) ;
|
||||||
if ( dSqDist < dSqDistMin) {
|
// tengo il segmento più vicino al punto
|
||||||
dSqDistMin = dSqDist ;
|
// 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 ;
|
nI = i ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,7 +305,7 @@ bool
|
|||||||
ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
|
ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
|
||||||
{
|
{
|
||||||
INTVECTOR vMyNext = vNext ;
|
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 ;
|
int nM = -1 ;
|
||||||
Point3d ptRef ;
|
Point3d ptRef ;
|
||||||
double dSqMinDist = m_dToler * m_dToler ;
|
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) {
|
for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) {
|
||||||
// salto l'entità più vicina
|
// salto l'entità più vicina
|
||||||
if ( i == nM)
|
if ( i == nM)
|
||||||
continue ;
|
continue ;
|
||||||
// recupero indice e verso
|
// recupero indice e verso
|
||||||
int nId = abs( vMyNext[i]) - 1 ;
|
int nId = abs( vMyNext[i]) - 1 ;
|
||||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
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 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)) ;
|
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
|
||||||
if ( dRefSqDist < dCurrSqDist)
|
if ( dRefSqDist < dCurrSqDist)
|
||||||
vMyNext[i] = 0 ;
|
vMyNext[i] = 0 ;
|
||||||
}
|
}
|
||||||
// cerco la direzione più vicina
|
// cerco la direzione più vicina
|
||||||
int nI = -1 ;
|
int nI = -1 ;
|
||||||
int nF = 0 ;
|
int nF = 0 ;
|
||||||
INTVECTOR vFork ;
|
INTVECTOR vFork ;
|
||||||
@@ -343,7 +346,7 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
|||||||
// recupero indice e verso
|
// recupero indice e verso
|
||||||
int nId = abs( vMyNext[i]) - 1 ;
|
int nId = abs( vMyNext[i]) - 1 ;
|
||||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
bool bEquiv = ( vMyNext[i] > 0) ;
|
||||||
// incremento contatore indice entità tra cui scegliere
|
// incremento contatore indice entità tra cui scegliere
|
||||||
++ nF ;
|
++ nF ;
|
||||||
vFork.push_back( vMyNext[i]) ;
|
vFork.push_back( vMyNext[i]) ;
|
||||||
// se vietata inversione, salto se controverso
|
// 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)
|
ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev)
|
||||||
{
|
{
|
||||||
INTVECTOR vMyPrev = vPrev ;
|
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 ;
|
int nM = -1 ;
|
||||||
Point3d ptRef ;
|
Point3d ptRef ;
|
||||||
double dSqMinDist = m_dToler * m_dToler ;
|
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) {
|
for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) {
|
||||||
// salto l'entità più vicina
|
// salto l'entità più vicina
|
||||||
if ( i == nM)
|
if ( i == nM)
|
||||||
continue ;
|
continue ;
|
||||||
// recupero indice e verso
|
// recupero indice e verso
|
||||||
int nId = abs( vMyPrev[i]) - 1 ;
|
int nId = abs( vMyPrev[i]) - 1 ;
|
||||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
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 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)) ;
|
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
|
||||||
if ( dRefSqDist < dCurrSqDist)
|
if ( dRefSqDist < dCurrSqDist)
|
||||||
vMyPrev[i] = 0 ;
|
vMyPrev[i] = 0 ;
|
||||||
}
|
}
|
||||||
// cerco la direzione più vicina
|
// cerco la direzione più vicina
|
||||||
int nI = - 1 ;
|
int nI = - 1 ;
|
||||||
int nF = 0 ;
|
int nF = 0 ;
|
||||||
double dProScaMax = - 1.1 ;
|
double dProScaMax = - 1.1 ;
|
||||||
@@ -428,7 +431,7 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
|||||||
// recupero indice e verso
|
// recupero indice e verso
|
||||||
int nId = abs( vMyPrev[i]) - 1 ;
|
int nId = abs( vMyPrev[i]) - 1 ;
|
||||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
bool bEquiv = ( vMyPrev[i] < 0) ;
|
||||||
// incremento contatore indice entità tra cui scegliere
|
// incremento contatore indice entità tra cui scegliere
|
||||||
++ nF ;
|
++ nF ;
|
||||||
vFork.push_back( vMyPrev[i]) ;
|
vFork.push_back( vMyPrev[i]) ;
|
||||||
// se vietata inversione, salto se controverso
|
// 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))
|
if ( dLenA > ( dRad - EPS_ZERO))
|
||||||
dLenH = 0 ;
|
dLenH = 0 ;
|
||||||
else
|
else
|
||||||
dLenH= sqrt( dRad * dRad - dLenA * dLenA) ;
|
dLenH = sqrt( dRad * dRad - dLenA * dLenA) ;
|
||||||
// versore dal punto medio della corda al centro
|
// versore dal punto medio della corda al centro
|
||||||
Vector3d vtH = vtA / dLenA ;
|
Vector3d vtH = vtA / dLenA ;
|
||||||
vtH.Rotate( Z_AX, 0, ( bCCW ? 1 : -1)) ;
|
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 ;
|
m_dRad = dRad ;
|
||||||
// calcolo il versore di start
|
// calcolo il versore di start
|
||||||
m_VtS = ( ptStart - m_PtCen) / m_dRad ;
|
m_VtS = ( ptStart - m_PtCen) / m_dRad ;
|
||||||
|
m_VtS.Normalize() ;
|
||||||
// calcolo l'angolo al centro
|
// calcolo l'angolo al centro
|
||||||
bool bDet ;
|
bool bDet ;
|
||||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
||||||
|
|||||||
+129
-60
@@ -298,12 +298,71 @@ CurveGetAreaXY( const ICurve& crvC, double& dArea)
|
|||||||
// verifico sia chiusa
|
// verifico sia chiusa
|
||||||
if ( ! crvC.IsClosed())
|
if ( ! crvC.IsClosed())
|
||||||
return false ;
|
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 ;
|
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
|
// restituisco il valore
|
||||||
if ( &dArea != nullptr)
|
if ( &dArea != nullptr)
|
||||||
dArea = dAreaXY ;
|
dArea = dAreaXY ;
|
||||||
@@ -626,6 +685,7 @@ EditBezierCurve( const ICurveBezier* pCrvBezier, int nDeg, bool bMakeRatOrNot, d
|
|||||||
return Release( pCrvNew) ;
|
return Release( pCrvNew) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
ICurveBezier*
|
ICurveBezier*
|
||||||
BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
||||||
{
|
{
|
||||||
@@ -677,6 +737,7 @@ BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
|||||||
return Release( pNewBezier) ;
|
return Release( pNewBezier) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
ICurveBezier*
|
ICurveBezier*
|
||||||
BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
|
BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
|
||||||
{
|
{
|
||||||
@@ -861,7 +922,7 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
|||||||
PtrOwner<CurveLine> pCL2( CreateBasicCurveLine()) ;
|
PtrOwner<CurveLine> pCL2( CreateBasicCurveLine()) ;
|
||||||
pCL2->Set( ptEnd, ptAux2) ;
|
pCL2->Set( ptEnd, ptAux2) ;
|
||||||
IntersLineLine ill( *pCL1, *pCL2, false) ;
|
IntersLineLine ill( *pCL1, *pCL2, false) ;
|
||||||
if( ill.GetNumInters() != 0) {
|
if ( ill.GetNumInters() != 0) {
|
||||||
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||||
ptCen = iccInfo.IciA[0].ptI ;
|
ptCen = iccInfo.IciA[0].ptI ;
|
||||||
double dDist1 = Dist( ptStart, ptCen) ;
|
double dDist1 = Dist( ptStart, ptCen) ;
|
||||||
@@ -871,7 +932,7 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
|||||||
cArc.SetC2PN( ptCen, ptStart, ptEnd, plPLane.GetVersN()) ;
|
cArc.SetC2PN( ptCen, ptStart, ptEnd, plPLane.GetVersN()) ;
|
||||||
// controllo se il raggio della circonferenza risultante coincide con quello calcolato prima
|
// controllo se il raggio della circonferenza risultante coincide con quello calcolato prima
|
||||||
// impongo inoltre che l'angolo al centro sia minore di 90 gradi
|
// 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 ;
|
bIsArc = true ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -880,22 +941,22 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
|||||||
int nSidePrec = -2 ;
|
int nSidePrec = -2 ;
|
||||||
int nCross = 0 ;
|
int nCross = 0 ;
|
||||||
// se non ho un arco cerco di capire se ho cambi di concavità
|
// se non ho un arco cerco di capire se ho cambi di concavità
|
||||||
if( ! bIsArc) {
|
if ( ! bIsArc) {
|
||||||
for( int i = 1 ; i < pCrvBezier->GetDegree() - 1; ++i) {
|
for ( int i = 1 ; i < pCrvBezier->GetDegree() - 1; ++i) {
|
||||||
ptCtrl = pCrvBezier->GetControlPoint( i) ;
|
ptCtrl = pCrvBezier->GetControlPoint( i) ;
|
||||||
DistPointCurve dpc( ptCtrl, *pCL) ;
|
DistPointCurve dpc( ptCtrl, *pCL) ;
|
||||||
int nSide = -2 ;
|
int nSide = -2 ;
|
||||||
dpc.GetSideAtMinDistPoint( 0, vtN, nSide) ;
|
dpc.GetSideAtMinDistPoint( 0, vtN, nSide) ;
|
||||||
if ( i > 0 && nSide * nSidePrec < 1)
|
if ( i > 0 && nSide * nSidePrec < 1)
|
||||||
++nCross ;
|
++nCross ;
|
||||||
if( nSide != 0)
|
if ( nSide != 0)
|
||||||
nSidePrec = nSide ;
|
nSidePrec = nSide ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// determino in quanti tratti spezzare la curva originale guardando il grado e i cambi di concavità
|
// 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 ;
|
int nParts = nCross > nDeg / 2 ? nCross : nDeg / 2 + 1 ;
|
||||||
bool bOneIsEnough = false ;
|
bool bOneIsEnough = false ;
|
||||||
if( ((nDeg == 2 || nDeg == 3) && ! bRat) || bIsArc) {
|
if ((( nDeg == 2 || nDeg == 3) && ! bRat) || bIsArc) {
|
||||||
nParts = 1 ;
|
nParts = 1 ;
|
||||||
bOneIsEnough = true ;
|
bOneIsEnough = true ;
|
||||||
}
|
}
|
||||||
@@ -909,11 +970,11 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
|||||||
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
||||||
pCrvPart->TrimStartEndAtParam( double( nParts - 1) / nParts, 1) ;
|
pCrvPart->TrimStartEndAtParam( double( nParts - 1) / nParts, 1) ;
|
||||||
PtrOwner<ICurveBezier> pCrvCubic ;
|
PtrOwner<ICurveBezier> pCrvCubic ;
|
||||||
if( ! bIsArc)
|
if ( ! bIsArc)
|
||||||
pCrvCubic.Set( ApproxCurveBezierWithSingleCubic( pCrvPart)) ;
|
pCrvCubic.Set( ApproxCurveBezierWithSingleCubic( pCrvPart)) ;
|
||||||
else {
|
else {
|
||||||
pCrvCubic.Set( ApproxArcCurveBezierWithSingleCubic( pCrvPart, ptCen)) ;
|
pCrvCubic.Set( ApproxArcCurveBezierWithSingleCubic( pCrvPart, ptCen)) ;
|
||||||
if( IsNull( pCrvCubic)) {
|
if ( IsNull( pCrvCubic)) {
|
||||||
// se fallisce allora riprovo usando più di una bezier
|
// se fallisce allora riprovo usando più di una bezier
|
||||||
bIsArc = false ;
|
bIsArc = false ;
|
||||||
bOneIsEnough = false ;
|
bOneIsEnough = false ;
|
||||||
@@ -923,17 +984,17 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CalcBezierApproxError( pCrvPart, pCrvCubic, dErr) ;
|
CalcBezierApproxError( pCrvPart, pCrvCubic, dErr) ;
|
||||||
if( dErr > dTol && ! bOneIsEnough)
|
if ( dErr > dTol && ! bOneIsEnough)
|
||||||
nParts += 2 ;
|
nParts += 2 ;
|
||||||
else {
|
else {
|
||||||
pCC->AddCurve( Release( pCrvCubic)) ;
|
pCC->AddCurve( Release( pCrvCubic)) ;
|
||||||
if( bOneIsEnough)
|
if ( bOneIsEnough)
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
++ nCount ;
|
++ nCount ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( nCount < 100) {
|
if ( nCount < 100) {
|
||||||
// approssimo annche tutti gli altri tratti con una cubica
|
// approssimo annche tutti gli altri tratti con una cubica
|
||||||
for ( int i = nParts - 1 ; i > 0 ; --i) {
|
for ( int i = nParts - 1 ; i > 0 ; --i) {
|
||||||
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
|
||||||
@@ -989,12 +1050,12 @@ ApproxArcCurveBezierWithSingleCubic( const ICurveBezier* pCrvBez, const Point3d&
|
|||||||
PtrOwner<ICurveBezier> pCrvCubic( CreateCurveBezier()) ;
|
PtrOwner<ICurveBezier> pCrvCubic( CreateCurveBezier()) ;
|
||||||
int nDeg = pCrvBez->GetDegree() ;
|
int nDeg = pCrvBez->GetDegree() ;
|
||||||
bool bRat = pCrvBez->IsRational() ;
|
bool bRat = pCrvBez->IsRational() ;
|
||||||
if( nDeg != 2 || ! bRat)
|
if ( nDeg != 2 || ! bRat)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|
||||||
Point3d ptStart = pCrvBez->GetControlPoint( 0) ;
|
Point3d ptStart = pCrvBez->GetControlPoint( 0) ;
|
||||||
Point3d ptEnd = pCrvBez->GetControlPoint( 2) ;
|
Point3d ptEnd = pCrvBez->GetControlPoint( 2) ;
|
||||||
if( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL * 50))
|
if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL * 50))
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
nDeg = 3 ;
|
nDeg = 3 ;
|
||||||
bRat = false ;
|
bRat = false ;
|
||||||
@@ -1040,7 +1101,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dTol)
|
|||||||
// scelgo il parametro associato ad ogni punto in modo che rispecchi la distanza tra i punti
|
// scelgo il parametro associato ad ogni punto in modo che rispecchi la distanza tra i punti
|
||||||
|
|
||||||
int nPoints = vPnt.size() ;
|
int nPoints = vPnt.size() ;
|
||||||
if( nPoints < 4)
|
if ( nPoints < 4)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
int nDeg = 3 ;
|
int nDeg = 3 ;
|
||||||
DBLVECTOR vLen ;
|
DBLVECTOR vLen ;
|
||||||
@@ -1110,15 +1171,15 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dTol)
|
|||||||
static bool
|
static bool
|
||||||
FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
|
FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
|
||||||
{
|
{
|
||||||
if( dU < 0)
|
if ( dU < 0)
|
||||||
return false ;
|
return false ;
|
||||||
else if( dU < EPS_ZERO) {
|
else if ( dU < EPS_ZERO) {
|
||||||
nSpan = nDeg ;
|
nSpan = nDeg ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
// trovo a quale span appartiene il parametro dU
|
// trovo a quale span appartiene il parametro dU
|
||||||
int nKnots = int( vKnots.size()) ;
|
int nKnots = int( vKnots.size()) ;
|
||||||
if( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
|
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
|
||||||
nSpan = nKnots - 1 ;
|
nSpan = nKnots - 1 ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
@@ -1143,7 +1204,7 @@ static bool
|
|||||||
CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
||||||
{
|
{
|
||||||
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
|
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
|
||||||
if( vBasis.size() != nDeg + 1)
|
if ( vBasis.size() != nDeg + 1)
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
int nSpan = 0 ;
|
int nSpan = 0 ;
|
||||||
@@ -1170,7 +1231,7 @@ CalcBasisFunc( double dU, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
|
|||||||
bool
|
bool
|
||||||
CalcBezierApproxError( const ICurveBezier* pCrvOri, const ICurveBezier* pCrvNew, double& dErr, int nPoints)
|
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 ;
|
return false ;
|
||||||
|
|
||||||
// controllo l'errore effettivo campionando più finemente
|
// controllo l'errore effettivo campionando più finemente
|
||||||
@@ -1185,7 +1246,7 @@ CalcBezierApproxError( const ICurveBezier* pCrvOri, const ICurveBezier* pCrvNew,
|
|||||||
pCrvNew->GetParamAtLength( double (i) / nPoints * dLenNew, dParNew) ;
|
pCrvNew->GetParamAtLength( double (i) / nPoints * dLenNew, dParNew) ;
|
||||||
pCrvNew->GetPointD1D2(dParNew, ICurve::FROM_MINUS, ptNew) ; ;
|
pCrvNew->GetPointD1D2(dParNew, ICurve::FROM_MINUS, ptNew) ; ;
|
||||||
double dErrLoc = Dist( ptOri, ptNew) ;
|
double dErrLoc = Dist( ptOri, ptNew) ;
|
||||||
if( dErrLoc > dErr)
|
if ( dErrLoc > dErr)
|
||||||
dErr = dErrLoc ;
|
dErr = dErrLoc ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,7 +1313,7 @@ CurveToArcsPerpExtrCurve( const ICurve* pCrv, double dLinTol, double dAngTolDeg)
|
|||||||
bool
|
bool
|
||||||
NurbsCurveCanonicalize( CNurbsData& cnData)
|
NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||||
{
|
{
|
||||||
// se con nodi extra
|
// se con nodi extra
|
||||||
if ( cnData.bExtraKnotes) {
|
if ( cnData.bExtraKnotes) {
|
||||||
int nKnotesNbr = int( cnData.vU.size()) ;
|
int nKnotesNbr = int( cnData.vU.size()) ;
|
||||||
if ( nKnotesNbr < 4)
|
if ( nKnotesNbr < 4)
|
||||||
@@ -1266,8 +1327,8 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
|||||||
// se periodica
|
// se periodica
|
||||||
if ( cnData.bPeriodic || ! cnData.bClamped) {
|
if ( cnData.bPeriodic || ! cnData.bClamped) {
|
||||||
bool bAlreadyChecked = false ;
|
bool bAlreadyChecked = false ;
|
||||||
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
|
// 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
|
// wrap della curva su se stessa
|
||||||
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
|
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
|
||||||
bool bRepeated = true ;
|
bool bRepeated = true ;
|
||||||
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
|
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
|
||||||
@@ -1278,30 +1339,30 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
|||||||
}
|
}
|
||||||
bool bFirstAddedAtEnd = false ;
|
bool bFirstAddedAtEnd = false ;
|
||||||
if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){
|
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 ;
|
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 ) {
|
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())) {
|
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
|
||||||
bFirstAddedAtEnd = true ;
|
bFirstAddedAtEnd = true ;
|
||||||
cnData.vCP.push_back( cnData.vCP[0]) ;
|
cnData.vCP.push_back( cnData.vCP[0]) ;
|
||||||
if ( cnData.bRat)
|
if ( cnData.bRat)
|
||||||
cnData.vW.push_back( cnData.vW[0]) ;
|
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) ;
|
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
|
||||||
// controllo eventualmente anche i nodi extra
|
// controllo eventualmente anche i nodi extra
|
||||||
// se ne ho due in più ne tolgo uno in cima e uno in fondo
|
// 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
|
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) ;
|
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) {
|
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) {
|
||||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
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 dU0 = cnData.vU[0] ;
|
||||||
double dULast = cnData.vU.back() ;
|
double dULast = cnData.vU.back() ;
|
||||||
bool bSame = true ;
|
bool bSame = true ;
|
||||||
@@ -1314,27 +1375,27 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
else {
|
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()) ;
|
bFirstAddedAtEnd = bFirstAddedAtEnd || AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ;
|
||||||
for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) {
|
for ( int i = bFirstAddedAtEnd ? 1 : 0 ; i < cnData.nDeg ; ++i ) {
|
||||||
cnData.vCP.push_back( cnData.vCP[i]) ;
|
cnData.vCP.push_back( cnData.vCP[i]) ;
|
||||||
if ( cnData.bRat)
|
if ( cnData.bRat)
|
||||||
cnData.vW.push_back( cnData.vW[i]) ;
|
cnData.vW.push_back( cnData.vW[i]) ;
|
||||||
}
|
}
|
||||||
// recupero il vettore dei nodi
|
// recupero il vettore dei nodi
|
||||||
cnData.vU = vU ;
|
cnData.vU = vU ;
|
||||||
// verifico se ho nodi extra
|
// verifico se ho nodi extra
|
||||||
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
|
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
|
||||||
// significa che ci sono due nodi extra:
|
// 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
|
// 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) {
|
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
|
||||||
cnData.vU = vector<double>( cnData.vU.begin() + 2, cnData.vU.end()) ;
|
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
|
else
|
||||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
|
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)
|
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
|
||||||
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
|
||||||
}
|
}
|
||||||
@@ -1343,7 +1404,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( ! bAlreadyChecked) {
|
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 dU0 = cnData.vU[0] ;
|
||||||
double dULast = cnData.vU.back() ;
|
double dULast = cnData.vU.back() ;
|
||||||
bool bSame = true ;
|
bool bSame = true ;
|
||||||
@@ -1357,10 +1418,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 ;
|
bool bCollapsed = true ;
|
||||||
Point3d ptFirst = cnData.vCP.front() ;
|
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])) {
|
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
|
||||||
bCollapsed = false ;
|
bCollapsed = false ;
|
||||||
break ;
|
break ;
|
||||||
@@ -1373,10 +1434,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
|
// 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))
|
// 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
|
// 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
|
// 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 nCP = int( cnData.vCP.size()) ;
|
||||||
int nU = nCP + cnData.nDeg - 1 ;
|
int nU = nCP + cnData.nDeg - 1 ;
|
||||||
int nDeg = cnData.nDeg ;
|
int nDeg = cnData.nDeg ;
|
||||||
@@ -1579,18 +1640,15 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
|||||||
return nullptr ;
|
return nullptr ;
|
||||||
// numero degli intervalli
|
// numero degli intervalli
|
||||||
int nInt = nU - 2 * cnData.nDeg + 1 ;
|
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)
|
// sistemo 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 = 0 ; i < cnData.nDeg - 1 ; ++ i) {
|
||||||
for ( int i = 1 ; i < cnData.nDeg ; ++ i) {
|
if ( abs( cnData.vU[i] - cnData.vU[cnData.nDeg - 1]) >= EPS_ZERO)
|
||||||
if ( abs( cnData.vU[i] - cnData.vU[0]) >= EPS_ZERO)
|
const_cast<double&>( cnData.vU[i]) = cnData.vU[cnData.nDeg - 1] ;
|
||||||
bOk = false ;
|
|
||||||
}
|
}
|
||||||
for ( int i = 1 ; i < cnData.nDeg ; ++ i) {
|
for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) {
|
||||||
if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - 1]) >= EPS_ZERO)
|
if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - cnData.nDeg]) >= EPS_ZERO)
|
||||||
bOk = false ;
|
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
|
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
|
||||||
if ( nInt == 1) {
|
if ( nInt == 1) {
|
||||||
@@ -1936,7 +1994,7 @@ CalcCurveVoronoiDiagram( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nBound)
|
|||||||
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
|
Voronoi* pVoronoiObj = GetCurveVoronoi( crvC) ;
|
||||||
if ( pVoronoiObj == nullptr)
|
if ( pVoronoiObj == nullptr)
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ;
|
return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2017,6 +2075,17 @@ CalcCurveLimitOffset( const ICurve& crvC, double& dOffs)
|
|||||||
return pVoronoiObj->CalcLimitOffset( 0, bLeft, 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) ;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
ResetCurveVoronoi( const ICurve& crvC)
|
ResetCurveVoronoi( const ICurve& crvC)
|
||||||
|
|||||||
+1
-1
@@ -2989,7 +2989,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
|
|||||||
m_CrvSmplS.pop_front() ;
|
m_CrvSmplS.pop_front() ;
|
||||||
}
|
}
|
||||||
// eseguo mini verifica
|
// 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
|
// assegno estrusione e spessore della curva composita
|
||||||
pCrv->SetExtrusion( m_VtExtr) ;
|
pCrv->SetExtrusion( m_VtExtr) ;
|
||||||
pCrv->SetThickness( m_dThick) ;
|
pCrv->SetThickness( m_dThick) ;
|
||||||
|
|||||||
Binary file not shown.
@@ -22,7 +22,7 @@
|
|||||||
<ProjectGuid>{9A98A202-2853-454A-84CA-DCD1714176C9}</ProjectGuid>
|
<ProjectGuid>{9A98A202-2853-454A-84CA-DCD1714176C9}</ProjectGuid>
|
||||||
<RootNamespace>EgtGeomKernel</RootNamespace>
|
<RootNamespace>EgtGeomKernel</RootNamespace>
|
||||||
<Keyword>MFCDLLProj</Keyword>
|
<Keyword>MFCDLLProj</Keyword>
|
||||||
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
<PlatformToolset>v141_xp</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
<PlatformToolset>v141_xp</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
@@ -321,7 +321,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
|||||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||||
<ClCompile Include="PolygonElevation.cpp" />
|
<ClCompile Include="PolygonElevation.cpp" />
|
||||||
<ClCompile Include="ProjectCurveSurfBez.cpp" />
|
|
||||||
<ClCompile Include="Quaternion.cpp" />
|
<ClCompile Include="Quaternion.cpp" />
|
||||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||||
@@ -430,7 +429,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
|||||||
<ClCompile Include="OffsetCurveOnX.cpp" />
|
<ClCompile Include="OffsetCurveOnX.cpp" />
|
||||||
<ClCompile Include="Polygon3d.cpp" />
|
<ClCompile Include="Polygon3d.cpp" />
|
||||||
<ClCompile Include="AdjustLoops.cpp" />
|
<ClCompile Include="AdjustLoops.cpp" />
|
||||||
<ClCompile Include="ProjectCurveSurfTm.cpp" />
|
<ClCompile Include="ProjectCurveSurf.cpp" />
|
||||||
<ClCompile Include="RemoveCurveDefects.cpp" />
|
<ClCompile Include="RemoveCurveDefects.cpp" />
|
||||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||||
<ClCompile Include="SfrCreate.cpp" />
|
<ClCompile Include="SfrCreate.cpp" />
|
||||||
|
|||||||
@@ -486,7 +486,7 @@
|
|||||||
<ClCompile Include="IntersLineCaps.cpp">
|
<ClCompile Include="IntersLineCaps.cpp">
|
||||||
<Filter>File di origine\GeoInters</Filter>
|
<Filter>File di origine\GeoInters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="ProjectCurveSurfTm.cpp">
|
<ClCompile Include="ProjectCurveSurf.cpp">
|
||||||
<Filter>File di origine\GeoProject</Filter>
|
<Filter>File di origine\GeoProject</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
|
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
|
||||||
@@ -540,9 +540,6 @@
|
|||||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
|
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
|
||||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="ProjectCurveSurfBez.cpp">
|
|
||||||
<Filter>File di origine\GeoProject</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="SbzFromCurves.cpp">
|
<ClCompile Include="SbzFromCurves.cpp">
|
||||||
<Filter>File di origine\GeoCreate</Filter>
|
<Filter>File di origine\GeoCreate</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -147,6 +147,10 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
|||||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|
||||||
|
// verifico il minimo raggio
|
||||||
|
if ( dRadius < 10 * EPS_SMALL)
|
||||||
|
return nullptr ;
|
||||||
|
|
||||||
// eseguo calcoli
|
// eseguo calcoli
|
||||||
Point3d ptCen, ptTg1, ptTg2 ;
|
Point3d ptCen, ptTg1, ptTg2 ;
|
||||||
int nSide1, nSide2 ;
|
int nSide1, nSide2 ;
|
||||||
@@ -165,6 +169,11 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
|||||||
return nullptr ;
|
return nullptr ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifico dimensione minima
|
||||||
|
double dLen = Dist( ptTg1, ptTg2) ;
|
||||||
|
if ( dLen < 2 * EPS_SMALL)
|
||||||
|
return nullptr ;
|
||||||
|
|
||||||
// orientamento tra le curve
|
// orientamento tra le curve
|
||||||
bool bCCW = ( dSinA > 0) ;
|
bool bCCW = ( dSinA > 0) ;
|
||||||
|
|
||||||
@@ -207,6 +216,10 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
|
|||||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|
||||||
|
// verifico lo smusso minimo
|
||||||
|
if ( dDist < 10 * EPS_SMALL)
|
||||||
|
return nullptr ;
|
||||||
|
|
||||||
// calcolo un riferimento sul piano perpendicolare alla normale
|
// calcolo un riferimento sul piano perpendicolare alla normale
|
||||||
Frame3d frIntr ;
|
Frame3d frIntr ;
|
||||||
if ( ! frIntr.Set( ORIG, vtNorm))
|
if ( ! frIntr.Set( ORIG, vtNorm))
|
||||||
|
|||||||
+2
-2
@@ -493,7 +493,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
|||||||
int nLbLen ;
|
int nLbLen ;
|
||||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||||
// salvo la linea, se contiene qualcosa
|
// salvo la linea, se contiene qualcosa
|
||||||
if ( vTmpCode.size() > 0) {
|
if ( ! vTmpCode.empty()) {
|
||||||
string sLine ;
|
string sLine ;
|
||||||
SetCodePoints( vTmpCode, sLine) ;
|
SetCodePoints( vTmpCode, sLine) ;
|
||||||
vLine.push_back( sLine) ;
|
vLine.push_back( sLine) ;
|
||||||
@@ -523,7 +523,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
|||||||
dMaxW = vtMove.x ;
|
dMaxW = vtMove.x ;
|
||||||
}
|
}
|
||||||
// salvo eventuale ultima linea
|
// salvo eventuale ultima linea
|
||||||
if ( vTmpCode.size() > 0) {
|
if ( ! vTmpCode.empty()) {
|
||||||
string sLine ;
|
string sLine ;
|
||||||
SetCodePoints( vTmpCode, sLine) ;
|
SetCodePoints( vTmpCode, sLine) ;
|
||||||
vLine.push_back( sLine) ;
|
vLine.push_back( sLine) ;
|
||||||
|
|||||||
+2
-2
@@ -619,7 +619,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
|||||||
int nLbLen ;
|
int nLbLen ;
|
||||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||||
// salvo la linea, se contiene qualcosa
|
// salvo la linea, se contiene qualcosa
|
||||||
if ( vTmpCode.size() > 0) {
|
if ( ! vTmpCode.empty()) {
|
||||||
string sLine ;
|
string sLine ;
|
||||||
SetCodePoints( vTmpCode, sLine) ;
|
SetCodePoints( vTmpCode, sLine) ;
|
||||||
vLine.push_back( sLine) ;
|
vLine.push_back( sLine) ;
|
||||||
@@ -646,7 +646,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
|||||||
dMaxW = vtMove.x ;
|
dMaxW = vtMove.x ;
|
||||||
}
|
}
|
||||||
// salvo eventuale ultima linea
|
// salvo eventuale ultima linea
|
||||||
if ( vTmpCode.size() > 0) {
|
if ( ! vTmpCode.empty()) {
|
||||||
string sLine ;
|
string sLine ;
|
||||||
SetCodePoints( vTmpCode, sLine) ;
|
SetCodePoints( vTmpCode, sLine) ;
|
||||||
vLine.push_back( sLine) ;
|
vLine.push_back( sLine) ;
|
||||||
|
|||||||
+5
-5
@@ -2267,7 +2267,7 @@ bool
|
|||||||
GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams)
|
GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams)
|
||||||
{
|
{
|
||||||
// nessun parametro
|
// nessun parametro
|
||||||
if ( vsParams.size() != 0)
|
if ( ! vsParams.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// recupero la superficie
|
// recupero la superficie
|
||||||
ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ;
|
ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ;
|
||||||
@@ -6632,7 +6632,7 @@ GdbExecutor::ExecuteDeselect( const string& sCmd2, const STRVECTOR& vsParams)
|
|||||||
// deselezione di tutto
|
// deselezione di tutto
|
||||||
else if ( sCmd2 == "ALL") {
|
else if ( sCmd2 == "ALL") {
|
||||||
// nessun parametro
|
// nessun parametro
|
||||||
if ( vsParams.size() != 0)
|
if ( ! vsParams.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// cancello selezione oggetti
|
// cancello selezione oggetti
|
||||||
if ( ! m_pGDB->ClearSelection())
|
if ( ! m_pGDB->ClearSelection())
|
||||||
@@ -7773,7 +7773,7 @@ bool
|
|||||||
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
|
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
|
||||||
{
|
{
|
||||||
// nessun parametro
|
// nessun parametro
|
||||||
if ( vsParams.size() != 0)
|
if ( ! vsParams.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// pulizia e reinizializzazione del DB geometrico
|
// pulizia e reinizializzazione del DB geometrico
|
||||||
m_pGDB->Clear() ;
|
m_pGDB->Clear() ;
|
||||||
@@ -7946,7 +7946,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
|||||||
// chiudo il file di uscita Tsc
|
// chiudo il file di uscita Tsc
|
||||||
else if ( sCmd2 == "CLOSE") {
|
else if ( sCmd2 == "CLOSE") {
|
||||||
// nessun parametro
|
// nessun parametro
|
||||||
if ( vsParams.size() != 0)
|
if ( ! vsParams.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// scrivo terminazioni e chiudo il file
|
// scrivo terminazioni e chiudo il file
|
||||||
return m_OutTsc.Close() ;
|
return m_OutTsc.Close() ;
|
||||||
@@ -7969,7 +7969,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
|||||||
else if ( sCmd2 == "SETGR") {
|
else if ( sCmd2 == "SETGR") {
|
||||||
Frame3d frF ;
|
Frame3d frF ;
|
||||||
// nessun parametro
|
// nessun parametro
|
||||||
if ( vsParams.size() == 0)
|
if ( vsParams.empty())
|
||||||
frF.Reset() ;
|
frF.Reset() ;
|
||||||
// un parametro ( Id del gruppo)
|
// un parametro ( Id del gruppo)
|
||||||
else if ( vsParams.size() == 1) {
|
else if ( vsParams.size() == 1) {
|
||||||
|
|||||||
+2
-2
@@ -571,7 +571,7 @@ HashGrids1d::Update( void)
|
|||||||
// Salvo stato di precedente attivazione delle griglie
|
// Salvo stato di precedente attivazione delle griglie
|
||||||
bool bGridActivePrev = m_bGridActive ;
|
bool bGridActivePrev = m_bGridActive ;
|
||||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||||
if ( m_objsToAdd.size() > 0 ) {
|
if ( ! m_objsToAdd.empty()) {
|
||||||
for ( auto pObj : m_objsToAdd) {
|
for ( auto pObj : m_objsToAdd) {
|
||||||
if ( m_bGridActive)
|
if ( m_bGridActive)
|
||||||
addGrid( *pObj) ;
|
addGrid( *pObj) ;
|
||||||
@@ -636,7 +636,7 @@ HashGrids1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
|||||||
sort( vnIds.begin(), vnIds.end()) ;
|
sort( vnIds.begin(), vnIds.end()) ;
|
||||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), 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
|
// Salvo stato di precedente attivazione delle griglie
|
||||||
bool bGridActivePrev = m_bGridActive ;
|
bool bGridActivePrev = m_bGridActive ;
|
||||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||||
if ( m_objsToAdd.size() > 0 ) {
|
if ( ! m_objsToAdd.empty()) {
|
||||||
for ( auto pObj : m_objsToAdd) {
|
for ( auto pObj : m_objsToAdd) {
|
||||||
if ( m_bGridActive)
|
if ( m_bGridActive)
|
||||||
addGrid( *pObj) ;
|
addGrid( *pObj) ;
|
||||||
@@ -690,7 +690,7 @@ HashGrids2d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
|||||||
sort( vnIds.begin(), vnIds.end()) ;
|
sort( vnIds.begin(), vnIds.end()) ;
|
||||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), 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
|
// Salvo stato di precedente attivazione delle griglie
|
||||||
bool bGridActivePrev = m_bGridActive ;
|
bool bGridActivePrev = m_bGridActive ;
|
||||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||||
if ( m_objsToAdd.size() > 0 ) {
|
if ( ! m_objsToAdd.empty()) {
|
||||||
for ( auto pObj : m_objsToAdd) {
|
for ( auto pObj : m_objsToAdd) {
|
||||||
if ( m_bGridActive)
|
if ( m_bGridActive)
|
||||||
addGrid( *pObj) ;
|
addGrid( *pObj) ;
|
||||||
@@ -733,7 +733,7 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
|||||||
sort( vnIds.begin(), vnIds.end()) ;
|
sort( vnIds.begin(), vnIds.end()) ;
|
||||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), 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)
|
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
|
||||||
{
|
{
|
||||||
// se non ci sono intersezioni, non va fatto alcunché
|
// se non ci sono intersezioni, non va fatto alcunché
|
||||||
if ( m_Info.size() == 0)
|
if ( m_Info.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||||
if ( ! bAdjCrvA && ! bAdjCrvB)
|
if ( ! bAdjCrvA && ! bAdjCrvB)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ static void
|
|||||||
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
||||||
{
|
{
|
||||||
// se non trovati, esco
|
// se non trovati, esco
|
||||||
if ( vInfo.size() == 0)
|
if ( vInfo.empty())
|
||||||
return ;
|
return ;
|
||||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||||
sort( vInfo.begin(), vInfo.end(),
|
sort( vInfo.begin(), vInfo.end(),
|
||||||
|
|||||||
+29
-24
@@ -19,20 +19,18 @@
|
|||||||
using namespace std ;
|
using namespace std ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Il punto è esterno al FatSegment se dista da questo più di Tol e la sua proiezione sta sul segmento
|
// Posizione del punto rispetto alla linea (+1=a destra, 0=nella banda di tolleranza, -1=a sinistra)
|
||||||
bool
|
static int
|
||||||
IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
|
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)
|
double dCross = CrossXY( ( ptP - ptS), vtDir) ;
|
||||||
if ( abs( CrossXY( ( ptP - ptS), vtDir)) < ( dTol + EPS_ZERO) * dLenXY)
|
double dFat = ( dTol + EPS_ZERO) * dLenXY ;
|
||||||
return false ;
|
if ( dCross > dFat)
|
||||||
// distanza con segno della proiezione del punto sul segmento dall'inizio per lunghezza segmento
|
return +1 ;
|
||||||
double dDistXY = ScalarXY( ( ptP - ptS), vtDir) ;
|
else if ( dCross < - dFat)
|
||||||
// se il punto non si proietta sul segmento entro la tolleranza
|
return -1 ;
|
||||||
if ( dDistXY < - dTol * dLenXY || dDistXY > ( dLenXY + dTol) * dLenXY)
|
else
|
||||||
return false ;
|
return 0 ;
|
||||||
// altrimenti
|
|
||||||
return true ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -44,7 +42,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
|
|||||||
m_bOverlaps = false ;
|
m_bOverlaps = false ;
|
||||||
m_nNumInters = 0 ;
|
m_nNumInters = 0 ;
|
||||||
|
|
||||||
// verifico validità linee
|
// verifico validità linee
|
||||||
if ( ! Line1.IsValid() || ! Line2.IsValid())
|
if ( ! Line1.IsValid() || ! Line2.IsValid())
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
@@ -130,30 +128,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
|||||||
if ( ! boxL1.OverlapsXY( boxL2))
|
if ( ! boxL1.OverlapsXY( boxL2))
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
// linea 1 : Start, End, Direzione e Lunghezza
|
// segmento 1 : Start, End, Direzione e Lunghezza
|
||||||
Point3d ptS1 = Line1.GetStart() ;
|
Point3d ptS1 = Line1.GetStart() ;
|
||||||
Point3d ptE1 = Line1.GetEnd() ;
|
Point3d ptE1 = Line1.GetEnd() ;
|
||||||
Vector3d vtDir1 = ptE1 - ptS1 ;
|
Vector3d vtDir1 = ptE1 - ptS1 ;
|
||||||
double dLen1XY = vtDir1.LenXY() ;
|
double dLen1XY = vtDir1.LenXY() ;
|
||||||
if ( dLen1XY < EPS_SMALL)
|
if ( dLen1XY < EPS_SMALL)
|
||||||
return ;
|
return ;
|
||||||
// linea 2 : Start, Direzione e Lunghezza
|
// segmento 2 : Start, Direzione e Lunghezza
|
||||||
Point3d ptS2 = Line2.GetStart() ;
|
Point3d ptS2 = Line2.GetStart() ;
|
||||||
Point3d ptE2 = Line2.GetEnd() ;
|
Point3d ptE2 = Line2.GetEnd() ;
|
||||||
Vector3d vtDir2 = ptE2 - ptS2 ;
|
Vector3d vtDir2 = ptE2 - ptS2 ;
|
||||||
double dLen2XY = vtDir2.LenXY() ;
|
double dLen2XY = vtDir2.LenXY() ;
|
||||||
if ( dLen2XY < EPS_SMALL)
|
if ( dLen2XY < EPS_SMALL)
|
||||||
return ;
|
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
|
// prodotto vettoriale nel piano XY tra le direzioni delle linee
|
||||||
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
|
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
|
||||||
// flag per linee parallele
|
// flag per linee parallele
|
||||||
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
|
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
|
||||||
// flag per segmenti che si allontanano significativamente
|
// flag per segmenti che si allontanano significativamente
|
||||||
bool bFarEnds = ( /*( abs( dCrossXY) > SIN_EPS_ANG_SMALL * ( dLen1XY * dLen2XY)) ||*/
|
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
|
||||||
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)) ;
|
|
||||||
|
|
||||||
// se non sono paralleli e si allontanano tra loro abbastanza
|
// se non sono paralleli e si allontanano tra loro abbastanza
|
||||||
if ( ! bParallel && bFarEnds) {
|
if ( ! bParallel && bFarEnds) {
|
||||||
@@ -168,6 +172,8 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
|||||||
nPos1 = ICurve::PP_END ; // vicino a fine
|
nPos1 = ICurve::PP_END ; // vicino a fine
|
||||||
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
|
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
|
||||||
nPos1 = ICurve::PP_MID ; // nell'interno
|
nPos1 = ICurve::PP_MID ; // nell'interno
|
||||||
|
else
|
||||||
|
return ;
|
||||||
// verifica posizione intersezione su seconda linea
|
// verifica posizione intersezione su seconda linea
|
||||||
int nPos2 = ICurve::PP_NULL ; // fuori
|
int nPos2 = ICurve::PP_NULL ; // fuori
|
||||||
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
|
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
|
nPos2 = ICurve::PP_END ; // vicino a fine
|
||||||
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
|
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
|
||||||
nPos2 = ICurve::PP_MID ; // nell'interno
|
nPos2 = ICurve::PP_MID ; // nell'interno
|
||||||
// se soluzione non accettata, esco
|
else
|
||||||
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
|
|
||||||
return ;
|
return ;
|
||||||
// limito i parametri a stare sui segmenti (0...1)
|
// limito i parametri a stare sui segmenti (0...1)
|
||||||
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 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.IciA[0].nNextTy = ICCT_NULL ;
|
||||||
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
|
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
|
||||||
m_Info.IciB[0].nNextTy = 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) &&
|
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
|
||||||
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
|
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
|
||||||
; // rimangono tutti NULL
|
; // rimangono tutti NULL
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static void
|
|||||||
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||||
{
|
{
|
||||||
// se non trovati, esco
|
// se non trovati, esco
|
||||||
if ( vInfo.size() == 0)
|
if ( vInfo.empty())
|
||||||
return ;
|
return ;
|
||||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||||
sort( vInfo.begin(), vInfo.end(),
|
sort( vInfo.begin(), vInfo.end(),
|
||||||
|
|||||||
@@ -1670,7 +1670,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
|
|||||||
|
|
||||||
// Studio le soluzioni
|
// Studio le soluzioni
|
||||||
int nIntType = T_ERROR ;
|
int nIntType = T_ERROR ;
|
||||||
if ( vdPar.size() == 0)
|
if ( vdPar.empty())
|
||||||
nIntType = T_NO_INT ;
|
nIntType = T_NO_INT ;
|
||||||
else if ( vdPar.size() == 1) {
|
else if ( vdPar.size() == 1) {
|
||||||
nIntType = T_ONE_TAN ;
|
nIntType = T_ONE_TAN ;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ static void
|
|||||||
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||||
{
|
{
|
||||||
// se non trovati, esco
|
// se non trovati, esco
|
||||||
if ( vInfo.size() == 0)
|
if ( vInfo.empty())
|
||||||
return ;
|
return ;
|
||||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||||
sort( vInfo.begin(), vInfo.end(),
|
sort( vInfo.begin(), vInfo.end(),
|
||||||
|
|||||||
@@ -42,5 +42,5 @@ Inters3Planes( const Plane3d& plPlane1, const Plane3d& plPlane2, const Plane3d&
|
|||||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES)
|
if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES)
|
||||||
return IPPT_NO ;
|
return IPPT_NO ;
|
||||||
// intersezione della linea con il terzo piano
|
// 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) ;
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-4
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_CrvLst.clear() ;
|
m_CrvLst.clear() ;
|
||||||
|
m_ptOffs = P_INVALID ;
|
||||||
|
m_vtOut = V_INVALID ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,10 +699,25 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
|||||||
// calcolo offset con Voronoi
|
// calcolo offset con Voronoi
|
||||||
ICURVEPOVECTOR vOffs ;
|
ICURVEPOVECTOR vOffs ;
|
||||||
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
|
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
|
||||||
if ( vOffs.size() == 0) {
|
if ( vOffs.empty()) {
|
||||||
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
|
// se non ho ottenuto offset e sono circa al valore limite ritento con valore leggermente diverso per le tolleranze di vroni
|
||||||
double dCorr = ( dDist > 0 ? - VRONI_OFFS_TOL : VRONI_OFFS_TOL) ;
|
double dMaxOffs ;
|
||||||
voronoiObj->CalcOffset( vOffs, dDist + dCorr, nType) ;
|
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 ++)
|
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++)
|
||||||
@@ -730,10 +747,21 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
|||||||
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||||
pCrv->ToGlob( frCopy) ;
|
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) {
|
else if ( bNeedRef) {
|
||||||
for ( auto pCrv : m_CrvLst)
|
for ( auto pCrv : m_CrvLst)
|
||||||
pCrv->ToGlob( frCopy) ;
|
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
|
// assegno estrusione e spessore come curva originale e unisco parti allineate
|
||||||
@@ -811,6 +839,20 @@ OffsetCurve::GetShorterCurve( void)
|
|||||||
return pCrv ;
|
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
|
bool
|
||||||
PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool bClosed)
|
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 ----------------------------------------
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "PointsPCA.h"
|
#include "PointsPCA.h"
|
||||||
|
#include "/EgtDev/Extern/Eigen/Dense"
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
PointsPCA::PointsPCA( void)
|
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
|
// inizializzo il rank ad un valore assurdo
|
||||||
m_nRank = - 1 ;
|
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
|
void
|
||||||
PointsPCA::AddPoint( const Point3d& ptP, double dW)
|
PointsPCA::AddPoint( const Point3d& ptP, double dW)
|
||||||
{
|
{
|
||||||
// incremento numero punti
|
// salvo i dati
|
||||||
m_dTotW += dW ;
|
m_vPntW.emplace_back( ptP, 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) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -58,29 +50,47 @@ PointsPCA::Finalize( void)
|
|||||||
m_nRank = 0 ;
|
m_nRank = 0 ;
|
||||||
|
|
||||||
// se non sono stati assegnati punti, esco
|
// se non sono stati assegnati punti, esco
|
||||||
if ( m_dTotW < EPS_ZERO)
|
if ( m_vPntW.empty())
|
||||||
return false ;
|
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 ;
|
double dScale = 1 / m_dTotW ;
|
||||||
|
|
||||||
// calcolo del baricentro
|
// calcolo del baricentro
|
||||||
|
for ( const auto& PntW : m_vPntW)
|
||||||
|
m_ptCen += PntW.second * PntW.first ;
|
||||||
m_ptCen *= dScale ;
|
m_ptCen *= dScale ;
|
||||||
|
|
||||||
// completo la matrice di covarianza
|
// matrice di covarianza
|
||||||
m_CovMat(0,0) = m_CovMat(0,0) * dScale - m_ptCen.x * m_ptCen.x ;
|
Eigen::Matrix3d CovMat ;
|
||||||
m_CovMat(1,1) = m_CovMat(1,1) * dScale - m_ptCen.y * m_ptCen.y ;
|
CovMat.setZero() ;
|
||||||
m_CovMat(2,2) = m_CovMat(2,2) * dScale - m_ptCen.z * m_ptCen.z ;
|
for ( const auto& PntW : m_vPntW) {
|
||||||
m_CovMat(0,1) = m_CovMat(0,1) * dScale - m_ptCen.x * m_ptCen.y ;
|
Point3d ptP( PntW.first.x - m_ptCen.x, PntW.first.y - m_ptCen.y, PntW.first.z - m_ptCen.z) ;
|
||||||
m_CovMat(0,2) = m_CovMat(0,2) * dScale - m_ptCen.x * m_ptCen.z ;
|
CovMat(0,0) += PntW.second * ( ptP.x * ptP.x) ;
|
||||||
m_CovMat(1,2) = m_CovMat(1,2) * dScale - m_ptCen.y * m_ptCen.z ;
|
CovMat(1,1) += PntW.second * ( ptP.y * ptP.y) ;
|
||||||
m_CovMat(1,0) = m_CovMat(0,1) ;
|
CovMat(2,2) += PntW.second * ( ptP.z * ptP.z) ;
|
||||||
m_CovMat(2,0) = m_CovMat(0,2) ;
|
CovMat(0,1) += PntW.second * ( ptP.x * ptP.y) ;
|
||||||
m_CovMat(2,1) = m_CovMat(1,2) ;
|
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 ;
|
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)
|
if ( es.info() == Eigen::NoConvergence)
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -13,8 +13,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||||
#include "/EgtDev/Extern/Eigen/Dense"
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class PointsPCA
|
class PointsPCA
|
||||||
@@ -33,9 +32,9 @@ class PointsPCA
|
|||||||
static const int MAX_RANK = 3 ;
|
static const int MAX_RANK = 3 ;
|
||||||
|
|
||||||
private :
|
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
|
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)
|
int m_nRank ; // numero delle componenti principali (MAX_RANK = 3)
|
||||||
Vector3d m_vtPC[MAX_RANK] ; // direzioni delle componenti principali
|
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)
|
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
|
||||||
{
|
{
|
||||||
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
|
// 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
|
// assegno parametro e bulge
|
||||||
m_lUPointBs.back().dU = dPar ;
|
m_lUPointBs.back().dU = dPar ;
|
||||||
m_lUPointBs.back().dB = dBulge ;
|
m_lUPointBs.back().dB = dBulge ;
|
||||||
@@ -285,10 +285,10 @@ bool
|
|||||||
PolyArc::Join( PolyArc& PA, double dOffsetPar)
|
PolyArc::Join( PolyArc& PA, double dOffsetPar)
|
||||||
{
|
{
|
||||||
// se l'altro poliarco non contiene alcunchè, esco con ok
|
// se l'altro poliarco non contiene alcunchè, esco con ok
|
||||||
if ( PA.m_lUPointBs.size() == 0)
|
if ( PA.m_lUPointBs.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
|
// 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 ;
|
return false ;
|
||||||
// cancello l'ultimo di questo
|
// cancello l'ultimo di questo
|
||||||
EraseLastUPoint() ;
|
EraseLastUPoint() ;
|
||||||
|
|||||||
+51
-14
@@ -54,7 +54,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
|||||||
// se da aggiungere in coda
|
// se da aggiungere in coda
|
||||||
if ( bEndOrStart) {
|
if ( bEndOrStart) {
|
||||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
// 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 ;
|
++ m_nRejected ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
|||||||
// altrimenti si aggiunge in testa
|
// altrimenti si aggiunge in testa
|
||||||
else {
|
else {
|
||||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
// 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 ;
|
++ m_nRejected ;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
@@ -234,10 +234,10 @@ bool
|
|||||||
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
||||||
{
|
{
|
||||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||||
if ( PL.m_lUPoints.size() == 0)
|
if ( PL.m_lUPoints.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
|
// 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 ;
|
return false ;
|
||||||
// cancello l'ultimo di questa
|
// cancello l'ultimo di questa
|
||||||
EraseLastUPoint() ;
|
EraseLastUPoint() ;
|
||||||
@@ -1085,15 +1085,8 @@ PolyLine::Invert( bool bInvertU)
|
|||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
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)
|
// elimino i punti consecutivi diventati coincidenti (almeno 2)
|
||||||
if ( m_lUPoints.size() < 2)
|
if ( m_lUPoints.size() < 2)
|
||||||
return true ;
|
return true ;
|
||||||
@@ -1104,7 +1097,7 @@ PolyLine::Flatten( double dZ)
|
|||||||
// mentre esiste un corrente
|
// mentre esiste un corrente
|
||||||
while ( currP != m_lUPoints.end()) {
|
while ( currP != m_lUPoints.end()) {
|
||||||
// se coincidono
|
// se coincidono
|
||||||
if ( AreSamePointApprox( precP->first, currP->first)) {
|
if ( AreSamePointEpsilon( precP->first, currP->first, dToler)) {
|
||||||
// elimino il punto corrente
|
// elimino il punto corrente
|
||||||
currP = m_lUPoints.erase( currP) ;
|
currP = m_lUPoints.erase( currP) ;
|
||||||
// il precedente rimane inalterato
|
// il precedente rimane inalterato
|
||||||
@@ -1119,6 +1112,50 @@ PolyLine::Flatten( double dZ)
|
|||||||
return true ;
|
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
|
bool
|
||||||
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
|
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
|
||||||
@@ -1289,7 +1326,7 @@ bool
|
|||||||
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||||
{
|
{
|
||||||
// se vuota non faccio alcunché
|
// se vuota non faccio alcunché
|
||||||
if ( m_lUPoints.size() == 0)
|
if ( m_lUPoints.empty())
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// determino le intersezioni dei lati con il piano
|
// determino le intersezioni dei lati con il piano
|
||||||
|
|||||||
@@ -0,0 +1,784 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// 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 ;
|
||||||
|
// Massimo numero di triangoli per raffinare ricerca su spigoli
|
||||||
|
const int MAX_FACET_FOR_CORNER = 1000 ;
|
||||||
|
// 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 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static bool
|
||||||
|
ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3d& frRefLine, const IntersParLinesSurfTm& intPLSTM,
|
||||||
|
double dPar, Point5ax& Pt5ax)
|
||||||
|
{
|
||||||
|
// 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 ( ! stmSurf.GetTriangle( vIntRes[nI].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 ISurf& sfSurf, const Vector3d& vtDir,
|
||||||
|
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||||
|
{
|
||||||
|
// sistemazioni per tipo di superficie
|
||||||
|
const SurfTriMesh* pSurfTm = nullptr ;
|
||||||
|
switch ( sfSurf.GetType()) {
|
||||||
|
case SRF_TRIMESH :
|
||||||
|
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
|
||||||
|
break ;
|
||||||
|
case SRF_BEZIER :
|
||||||
|
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
case SRF_FLATRGN :
|
||||||
|
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
if ( pSurfTm == nullptr)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// 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 ;
|
||||||
|
|
||||||
|
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
|
||||||
|
Frame3d frRefLine ;
|
||||||
|
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||||
|
return false ;
|
||||||
|
IntersParLinesSurfTm intPLSTM( frRefLine, *pSurfTm) ;
|
||||||
|
|
||||||
|
// 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, *pSurfTm, frRefLine, intPLSTM, 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].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 SurfTriMesh& stmSurf, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
|
||||||
|
{
|
||||||
|
// 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, stmSurf, 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 ( ! stmSurf.GetTriangle( vIntRes[nI].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 ISurf& sfSurf, const IGeoPoint3d& gpRef,
|
||||||
|
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||||
|
{
|
||||||
|
// sistemazioni per tipo di superficie
|
||||||
|
const SurfTriMesh* pSurfTm = nullptr ;
|
||||||
|
switch ( sfSurf.GetType()) {
|
||||||
|
case SRF_TRIMESH :
|
||||||
|
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
|
||||||
|
break ;
|
||||||
|
case SRF_BEZIER :
|
||||||
|
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
case SRF_FLATRGN :
|
||||||
|
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
if ( pSurfTm == 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 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, *pSurfTm, gpRef, dPar, Pt5ax))
|
||||||
|
vPt5ax.emplace_back( Pt5ax) ;
|
||||||
|
// passo al successivo
|
||||||
|
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli
|
||||||
|
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) {
|
||||||
|
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, *pSurfTm, 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 SurfTriMesh& stmSurf, 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 la superficie
|
||||||
|
Vector3d vtLine = ptP - ptMin ;
|
||||||
|
double dLineLen = vtLine.Len() ;
|
||||||
|
if ( dLineLen > EPS_SMALL) {
|
||||||
|
vtLine /= dLineLen ;
|
||||||
|
ILSIVECTOR vIntRes ;
|
||||||
|
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, 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 ( ! stmSurf.GetTriangle( vIntRes[nI].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 ISurf& sfSurf, const ICurve& crRef,
|
||||||
|
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||||
|
{
|
||||||
|
// Sistemazioni per tipo di superficie
|
||||||
|
const SurfTriMesh* pSurfTm = nullptr ;
|
||||||
|
switch ( sfSurf.GetType()) {
|
||||||
|
case SRF_TRIMESH :
|
||||||
|
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
|
||||||
|
break ;
|
||||||
|
case SRF_BEZIER :
|
||||||
|
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
case SRF_FLATRGN :
|
||||||
|
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
if ( pSurfTm == nullptr)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// 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, *pSurfTm, 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 SurfTriMesh& stmSurf, 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 la superficie
|
||||||
|
ILSIVECTOR vIntRes ;
|
||||||
|
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, 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 ( ! stmSurf.GetTriangle( vIntRes[nI].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 ISurf& sfSurf, const ISurf& sfRef,
|
||||||
|
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||||
|
{
|
||||||
|
// sistemazioni per tipo di superficie
|
||||||
|
const SurfTriMesh* pSurfTm = nullptr ;
|
||||||
|
switch ( sfSurf.GetType()) {
|
||||||
|
case SRF_TRIMESH :
|
||||||
|
pSurfTm = GetBasicSurfTriMesh( &sfSurf) ;
|
||||||
|
break ;
|
||||||
|
case SRF_BEZIER :
|
||||||
|
pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
case SRF_FLATRGN :
|
||||||
|
pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ;
|
||||||
|
break ;
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
if ( pSurfTm == nullptr)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// 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, *pSurfTm, *pRefTm, dPar, Pt5ax))
|
||||||
|
vPt5ax.emplace_back( Pt5ax) ;
|
||||||
|
// passo al successivo
|
||||||
|
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli
|
||||||
|
if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) {
|
||||||
|
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, *pSurfTm, *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 ;
|
|
||||||
}
|
|
||||||
+1
-1
@@ -135,7 +135,7 @@ bool
|
|||||||
SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
|
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é
|
// 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 ;
|
return true ;
|
||||||
// procedo ad aggiustare
|
// procedo ad aggiustare
|
||||||
for ( auto& aInfo : m_Info) {
|
for ( auto& aInfo : m_Info) {
|
||||||
|
|||||||
+2
-4
@@ -577,10 +577,8 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
|
|||||||
bool
|
bool
|
||||||
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
|
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
|
// vnPLIndMat : ogni riga corrisponde ad un chunk, in posizione 0 c'è il loop esterno e nelle successive i loop interni
|
||||||
// successive i loop interni
|
// vbInvert : riferito al vettore delle polyline, riporta true se la polyline è stata invertita
|
||||||
//INTMATRIX vnPLIndMat ;
|
|
||||||
// vettore di bool : riferito al vettore originale delle polyline, riporta true se la polyline è stata invertita
|
|
||||||
|
|
||||||
// ricavo versore normale
|
// ricavo versore normale
|
||||||
Plane3d plPlane ; double dArea ;
|
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)
|
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
|
||||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||||
INTMATRIX vnPLIndMat ;
|
INTMATRIX vnPLIndMat ;
|
||||||
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
|
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
@@ -1310,7 +1310,7 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
|
|||||||
if ( ! pStmSwept->GetLoops( vPLe))
|
if ( ! pStmSwept->GetLoops( vPLe))
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
// creo la superficie alla fine e la attacco
|
// creo la superficie alla fine e la attacco
|
||||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||||
vnPLIndMat.clear() ;
|
vnPLIndMat.clear() ;
|
||||||
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
|
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|||||||
+123
-6
@@ -22,6 +22,18 @@
|
|||||||
|
|
||||||
using namespace std ;
|
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*
|
static SurfTriMesh*
|
||||||
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
||||||
@@ -160,15 +172,15 @@ GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight)
|
|||||||
return nullptr ;
|
return nullptr ;
|
||||||
// creo la polilinea del contorno della base
|
// creo la polilinea del contorno della base
|
||||||
PolyLine PL ;
|
PolyLine PL ;
|
||||||
PL.AddUPoint( 0, ORIG) ;
|
PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||||
PL.AddUPoint( 1, Point3d( dDimX, 0, 0)) ;
|
PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ;
|
||||||
PL.AddUPoint( 2, Point3d( dDimX, dDimY, 0)) ;
|
PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ;
|
||||||
PL.AddUPoint( 3, Point3d( 0, dDimY, 0)) ;
|
PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ;
|
||||||
PL.AddUPoint( 4, ORIG) ;
|
PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||||
if ( dHeight < 0)
|
if ( dHeight < 0)
|
||||||
PL.Invert() ;
|
PL.Invert() ;
|
||||||
// punto di vertice
|
// punto di vertice
|
||||||
Point3d ptTip( 0.5 * dDimX, 0.5 * dDimY, dHeight) ;
|
Point3d ptTip( 0, 0, dHeight) ;
|
||||||
// creo e setto la superficie trimesh laterale
|
// creo e setto la superficie trimesh laterale
|
||||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||||
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
|
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
|
||||||
@@ -245,6 +257,111 @@ GetSurfTriMeshSphere( double dRadius, double dLinTol)
|
|||||||
return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, 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*
|
ISurfTriMesh*
|
||||||
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
|
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
|
||||||
|
|||||||
+314
-147
@@ -40,6 +40,7 @@
|
|||||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||||
#include "/EgtDev/Include/EGkIntervals.h"
|
#include "/EgtDev/Include/EGkIntervals.h"
|
||||||
#include "/EgtDev/Extern/Eigen/Dense"
|
#include "/EgtDev/Extern/Eigen/Dense"
|
||||||
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
@@ -51,9 +52,11 @@ static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposit
|
|||||||
static bool ParametrizeByLen( const ICurveComposite* pCurve, DBLVECTOR& vParam) ;
|
static bool ParametrizeByLen( const ICurveComposite* pCurve, DBLVECTOR& vParam) ;
|
||||||
static bool BuildCommonParam( const DBLMATRIX& mParam, DBLVECTOR& vCommonParam) ;
|
static bool BuildCommonParam( const DBLMATRIX& mParam, DBLVECTOR& vCommonParam) ;
|
||||||
|
|
||||||
|
static unordered_map<INTINT, DBLVECTOR, PairHashIntInt> m_mBernCache ; // mappa dei polinomi di bernstein
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
SurfBezier::SurfBezier( void)
|
SurfBezier::SurfBezier( void)
|
||||||
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false),
|
: m_pSTM( nullptr), m_pSTMRefined( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false),
|
||||||
m_bTrimmed( false), m_bClosedU( false), m_bClosedV( false), m_pTrimReg(nullptr), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}
|
m_bTrimmed( false), m_bClosedU( false), m_bClosedV( false), m_pTrimReg(nullptr), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -92,6 +95,20 @@ SurfBezier::Init( int nDegU, int nDegV, int nSpanU, int nSpanV, bool bIsRational
|
|||||||
m_nStatus = TO_VERIFY ;
|
m_nStatus = TO_VERIFY ;
|
||||||
m_nIsPlanar = NOT_CALCULATED ;
|
m_nIsPlanar = NOT_CALCULATED ;
|
||||||
|
|
||||||
|
// setto la dimensione dei vettori
|
||||||
|
m_vBernU.resize( m_nDegU + 1) ;
|
||||||
|
m_vBernV.resize( m_nDegV + 1) ;
|
||||||
|
if (! m_bRat)
|
||||||
|
m_ptTemp.resize(m_nDegV + 1, ORIG) ;
|
||||||
|
else {
|
||||||
|
m_ptTempW.resize(m_nDegV + 1, ORIG) ;
|
||||||
|
m_dTempW.resize( m_nDegV + 1, 0) ;
|
||||||
|
m_vPtWCtrlLoc.resize( GetLocDim()) ;
|
||||||
|
m_vWeCtrlLoc.resize( GetLocDim()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// imposto ricalcolo della grafica
|
// imposto ricalcolo della grafica
|
||||||
ResetAuxSurf() ;
|
ResetAuxSurf() ;
|
||||||
m_OGrMgr.Reset() ;
|
m_OGrMgr.Reset() ;
|
||||||
@@ -299,6 +316,123 @@ SurfBezier::GetCentroid( Point3d& ptCen) const
|
|||||||
return m_pSTM->GetCentroid( ptCen) ;
|
return m_pSTM->GetCentroid( ptCen) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
SurfBezier::GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const
|
||||||
|
{
|
||||||
|
INTINT key( nDegU, int( dU * pow(2,24))) ;
|
||||||
|
if ( m_mBernCache.find( key) == m_mBernCache.end()) {
|
||||||
|
DBLVECTOR vBern( nDegU + 1) ;
|
||||||
|
GetAllBernstein( dU, nDegU, vBern) ;
|
||||||
|
m_mBernCache[key] = vBern ;
|
||||||
|
}
|
||||||
|
vBernU = m_mBernCache[key] ;
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
SurfBezier::GetPoint( double dU, double dV, Side nUs, Side nVs,Point3d& ptPos) const
|
||||||
|
{
|
||||||
|
// la curva deve essere validata
|
||||||
|
if ( m_nStatus != OK)
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
// i parametri U e V devono essere compresi tra 0 e il corrispondente numero di Span
|
||||||
|
dU = Clamp( dU, 0., double( m_nSpanU)) ;
|
||||||
|
dV = Clamp( dV, 0., double( m_nSpanV)) ;
|
||||||
|
|
||||||
|
// determino gli intervalli di span e riduco i parametri in essi
|
||||||
|
int nBsU = min( int( dU), m_nSpanU - 1) ;
|
||||||
|
double dLocU = dU - nBsU ;
|
||||||
|
if ( abs( dLocU) < 5 * EPS_PARAM && nBsU > 0 && nUs == ISurfBezier::FROM_MINUS) {
|
||||||
|
-- nBsU ;
|
||||||
|
dLocU = 1 ;
|
||||||
|
}
|
||||||
|
else if ( abs( dLocU) > 1 - 5 * EPS_PARAM && nBsU < m_nSpanU - 1 && nUs == ISurfBezier::FROM_PLUS) {
|
||||||
|
++ nBsU ;
|
||||||
|
dLocU = 0 ;
|
||||||
|
}
|
||||||
|
int nOffsU = nBsU * m_nDegU ;
|
||||||
|
int nBsV = min( int( dV), m_nSpanV - 1) ;
|
||||||
|
double dLocV = dV - nBsV ;
|
||||||
|
if ( abs( dLocV) < 5 * EPS_PARAM && nBsV > 0 && nVs == ISurfBezier::FROM_MINUS) {
|
||||||
|
-- nBsV ;
|
||||||
|
dLocV = 1 ;
|
||||||
|
}
|
||||||
|
else if ( abs( dLocV) > 1 - 5 * EPS_PARAM && nBsV < m_nSpanV - 1 && nVs == ISurfBezier::FROM_PLUS) {
|
||||||
|
++ nBsV ;
|
||||||
|
dLocV = 0 ;
|
||||||
|
}
|
||||||
|
int nOffsV = nBsV * m_nDegV ;
|
||||||
|
|
||||||
|
// se forma polinomiale (o integrale)
|
||||||
|
if ( ! m_bRat) {
|
||||||
|
|
||||||
|
// calcolo dei polinomi di Bernstein per U di grado opportuno
|
||||||
|
GetBernstein( dLocU, m_nDegU, m_vBernU) ;
|
||||||
|
|
||||||
|
// calcolo dei punti intermedi
|
||||||
|
m_ptTemp.assign(GetLocDim(), ORIG) ;
|
||||||
|
for ( int j = 0 ; j <= m_nDegV ; ++ j) {
|
||||||
|
for ( int i = 0 ; i <= m_nDegU ; ++ i)
|
||||||
|
m_ptTemp[j] += m_vBernU[i] * m_vPtCtrl[GetInd( nOffsU + i, nOffsV + j)] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcolo dei polinomi di Bernstein per V di grado opportuno
|
||||||
|
GetBernstein( dLocV, m_nDegV, m_vBernV) ;
|
||||||
|
|
||||||
|
// calcolo del punto
|
||||||
|
ptPos = ORIG ;
|
||||||
|
for ( int j = 0 ; j <= m_nDegV ; ++ j)
|
||||||
|
ptPos += m_vBernV[j] * m_ptTemp[j] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// altrimenti forma razionale
|
||||||
|
else {
|
||||||
|
// recupero punti di controllo e pesi della patch in questione
|
||||||
|
// porto i punti in forma omogenea moltiplicandoli per i pesi
|
||||||
|
m_vPtWCtrlLoc.assign(GetLocDim(), ORIG) ;
|
||||||
|
m_vWeCtrlLoc.assign(GetLocDim(), 0) ;
|
||||||
|
for ( int j = 0 ; j <= m_nDegV ; ++ j) {
|
||||||
|
for ( int i = 0 ; i <= m_nDegU ; ++ i) {
|
||||||
|
m_vPtWCtrlLoc[GetLocInd( i, j)] = m_vWeCtrl[GetInd( nOffsU + i, nOffsV + j)] * m_vPtCtrl[GetInd( nOffsU + i, nOffsV + j)] ;
|
||||||
|
m_vWeCtrlLoc[GetLocInd( i, j)] = m_vWeCtrl[GetInd( nOffsU + i, nOffsV + j)] ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcolo dei polinomi di Bernstein di grado opportuno
|
||||||
|
GetBernstein( dLocU, m_nDegU, m_vBernU) ;
|
||||||
|
|
||||||
|
// calcolo dei punti e pesi intermedi
|
||||||
|
m_ptTempW.assign(GetLocDim(), ORIG) ;
|
||||||
|
m_dTempW.assign(GetLocDim(), 0) ;
|
||||||
|
for ( int j = 0 ; j <= m_nDegV ; ++ j) {
|
||||||
|
for ( int i = 0 ; i <= m_nDegU ; ++ i) {
|
||||||
|
m_ptTempW[j] += m_vBernU[i] * m_vPtWCtrlLoc[GetLocInd( i, j)] ;
|
||||||
|
m_dTempW[j] += m_vBernU[i] * m_vWeCtrlLoc[GetLocInd( i, j)] ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcolo dei polinomi di Bernstein per V di grado opportuno
|
||||||
|
GetBernstein( dLocV, m_nDegV, m_vBernV) ;
|
||||||
|
|
||||||
|
// calcolo del punto
|
||||||
|
double dW = 0 ;
|
||||||
|
ptPos = ORIG ;
|
||||||
|
for ( int j = 0 ; j <= m_nDegV ; ++ j) {
|
||||||
|
ptPos += m_vBernV[j] * m_ptTempW[j] ;
|
||||||
|
dW += m_vBernV[j] * m_dTempW[j] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ritrasformo da forma omogenea a forma standard
|
||||||
|
double dInvW = 1 / ( ( dW > EPS_ZERO) ? dW : EPS_ZERO) ;
|
||||||
|
ptPos *= dInvW ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
SurfBezier::GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
|
SurfBezier::GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
|
||||||
@@ -632,25 +766,24 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc)
|
|||||||
m_bTrimmed = true ;
|
m_bTrimmed = true ;
|
||||||
m_pTrimReg = sbSrc.m_pTrimReg->Clone() ;
|
m_pTrimReg = sbSrc.m_pTrimReg->Clone() ;
|
||||||
}
|
}
|
||||||
if ( sbSrc.m_pSTM != nullptr) {
|
m_pSTM = sbSrc.GetAuxSurf()->Clone() ;
|
||||||
m_pSTM = sbSrc.m_pSTM->Clone() ;
|
for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) {
|
||||||
for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) {
|
m_mCCEdge.emplace_back() ;
|
||||||
m_mCCEdge.emplace_back() ;
|
for ( int j = 0 ; j < int( sbSrc.m_mCCEdge[i].size()) ; ++j ) {
|
||||||
for ( int j = 0 ; j < int( sbSrc.m_mCCEdge[i].size()) ; ++j ) {
|
m_mCCEdge.back().emplace_back( sbSrc.m_mCCEdge[i][j]->Clone()) ;
|
||||||
m_mCCEdge.back().emplace_back( sbSrc.m_mCCEdge[i][j]->Clone()) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( sbSrc.m_bTrimmed) {
|
|
||||||
for ( int i = 0 ; i < int( sbSrc.m_vCCLoop.size()) ; ++i)
|
|
||||||
m_vCCLoop.emplace_back( sbSrc.m_vCCLoop[i]->Clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( sbSrc.m_bTrimmed) {
|
||||||
|
for ( int i = 0 ; i < int( sbSrc.m_vCCLoop.size()) ; ++i)
|
||||||
|
m_vCCLoop.emplace_back( sbSrc.m_vCCLoop[i]->Clone());
|
||||||
|
}
|
||||||
m_bClosedU = sbSrc.m_bClosedU ;
|
m_bClosedU = sbSrc.m_bClosedU ;
|
||||||
m_bClosedV = sbSrc.m_bClosedV ;
|
m_bClosedV = sbSrc.m_bClosedV ;
|
||||||
m_nTempProp[0] = sbSrc.m_nTempProp[0] ;
|
m_nTempProp[0] = sbSrc.m_nTempProp[0] ;
|
||||||
m_nTempProp[1] = sbSrc.m_nTempProp[1] ;
|
m_nTempProp[1] = sbSrc.m_nTempProp[1] ;
|
||||||
m_dTempParam[0] = sbSrc.m_dTempParam[0] ;
|
m_dTempParam[0] = sbSrc.m_dTempParam[0] ;
|
||||||
m_dTempParam[1] = sbSrc.m_dTempParam[1] ;
|
m_dTempParam[1] = sbSrc.m_dTempParam[1] ;
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,7 +961,7 @@ bool
|
|||||||
SurfBezier::Validate( void)
|
SurfBezier::Validate( void)
|
||||||
{
|
{
|
||||||
if ( m_nStatus == TO_VERIFY)
|
if ( m_nStatus == TO_VERIFY)
|
||||||
m_nStatus = ( ( m_nDegU * m_nDegV > 0 && m_vPtCtrl.size() > 0) ? OK : ERR) ;
|
m_nStatus = ( ( m_nDegU * m_nDegV > 0 && ! m_vPtCtrl.empty()) ? OK : ERR) ;
|
||||||
|
|
||||||
return ( m_nStatus == OK) ;
|
return ( m_nStatus == OK) ;
|
||||||
}
|
}
|
||||||
@@ -1475,38 +1608,6 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const
|
|||||||
return dLen ;
|
return dLen ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool
|
|
||||||
SurfBezier::UpdateEdgesFromTree( Tree& tr) const
|
|
||||||
{
|
|
||||||
POLYLINEMATRIX mPlEdges ;
|
|
||||||
tr.GetEdges3D( mPlEdges) ;
|
|
||||||
for ( int i= 0 ; i < int( mPlEdges.size()); ++i) {
|
|
||||||
for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) {
|
|
||||||
m_mCCEdge[i].emplace_back(CreateBasicCurveComposite()) ;
|
|
||||||
if ( ! m_mCCEdge[i].back()->FromPolyLine(mPlEdges[i][j]) ) {
|
|
||||||
Point3d ptStart ;
|
|
||||||
if ( ! mPlEdges[i][j].GetFirstPoint( ptStart))
|
|
||||||
continue ;
|
|
||||||
m_mCCEdge[i].back()->FromPoint( ptStart) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_bTrimmed) {
|
|
||||||
POLYLINEVECTOR vPl ;
|
|
||||||
tr.GetSplitLoops( vPl) ;
|
|
||||||
|
|
||||||
// recupero i loop nel parametrico
|
|
||||||
for( int i = 0 ; i < int( vPl.size()); ++i) {
|
|
||||||
m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ;
|
|
||||||
m_vCCLoop.back()->FromPolyLine(vPl[i]) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const SurfTriMesh*
|
const SurfTriMesh*
|
||||||
SurfBezier::GetAuxSurf( void) const
|
SurfBezier::GetAuxSurf( void) const
|
||||||
@@ -1520,10 +1621,27 @@ SurfBezier::GetAuxSurf( void) const
|
|||||||
if ( m_pSTM != nullptr)
|
if ( m_pSTM != nullptr)
|
||||||
return m_pSTM ;
|
return m_pSTM ;
|
||||||
// eseguo calcolo
|
// eseguo calcolo
|
||||||
m_pSTM = GetApproxSurf( 50 * EPS_SMALL, 100 * EPS_SMALL) ;
|
m_pSTM = GetApproxSurf( 1000 * EPS_SMALL, 100 * EPS_SMALL) ;
|
||||||
return m_pSTM ;
|
return m_pSTM ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
const SurfTriMesh*
|
||||||
|
SurfBezier::GetAuxSurfRefined( void) const
|
||||||
|
{
|
||||||
|
// la superficie deve essere validata
|
||||||
|
if ( m_nStatus != OK) {
|
||||||
|
ResetAuxSurf() ;
|
||||||
|
return nullptr ;
|
||||||
|
}
|
||||||
|
// se già calcolata, la restituisco
|
||||||
|
if ( m_pSTMRefined != nullptr)
|
||||||
|
return m_pSTMRefined ;
|
||||||
|
// eseguo calcolo
|
||||||
|
m_pSTMRefined = GetApproxSurf( 50 * EPS_SMALL, 100 * EPS_SMALL) ;
|
||||||
|
return m_pSTMRefined ;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
SurfTriMesh*
|
SurfTriMesh*
|
||||||
SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
|
SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
|
||||||
@@ -1532,10 +1650,14 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
|
|||||||
if ( m_nStatus != OK)
|
if ( m_nStatus != OK)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|
||||||
// se c'è ausiliaria e richiesta con gli stessi parametri, ne restituisco una copia
|
// se c'è ausiliaria di visualizzazione con gli stessi parametri, ne restituisco una copia
|
||||||
if ( m_pSTM != nullptr &&
|
if ( m_pSTM != nullptr &&
|
||||||
abs( dTol - 50 * EPS_SMALL) < EPS_SMALL && abs( dSideMin - 100 * EPS_SMALL) < EPS_SMALL)
|
abs( dTol - 1000 * EPS_SMALL) < EPS_SMALL && abs( dSideMin - 100 * EPS_SMALL) < EPS_SMALL)
|
||||||
return m_pSTM->Clone() ;
|
return m_pSTM->Clone() ;
|
||||||
|
// se c'è ausiliaria e richiesta con gli stessi parametri, ne restituisco una copia
|
||||||
|
if ( m_pSTMRefined != nullptr &&
|
||||||
|
abs( dTol - 50 * EPS_SMALL) < EPS_SMALL && abs( dSideMin - 100 * EPS_SMALL) < EPS_SMALL)
|
||||||
|
return m_pSTMRefined->Clone() ;
|
||||||
|
|
||||||
// costruttore della superficie
|
// costruttore della superficie
|
||||||
POLYLINEMATRIX vvPL ;
|
POLYLINEMATRIX vvPL ;
|
||||||
@@ -1549,7 +1671,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
|
|||||||
bool bTest = false ; // per debug
|
bool bTest = false ; // per debug
|
||||||
// resetto il vettore degli edge
|
// resetto il vettore degli edge
|
||||||
m_mCCEdge.clear() ;
|
m_mCCEdge.clear() ;
|
||||||
m_mCCEdge = vector<ICRVCOMPOPOVECTOR>(4) ;
|
|
||||||
m_vCCLoop.clear() ;
|
m_vCCLoop.clear() ;
|
||||||
for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) {
|
for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) {
|
||||||
Point3d ptMin = get<0>( vTrees[i]) ;
|
Point3d ptMin = get<0>( vTrees[i]) ;
|
||||||
@@ -1565,15 +1686,15 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
|
|||||||
Tree.BuildTree( dTol, dSideMin) ;
|
Tree.BuildTree( dTol, dSideMin) ;
|
||||||
//Tree.BuildTree( 1, 5) ; //debug
|
//Tree.BuildTree( 1, 5) ; //debug
|
||||||
}
|
}
|
||||||
if ( ! Tree.GetPolygons( vvPL, vvPL3d))
|
if ( ! Tree.GetPolygons( vvPL, vvPL3d, m_mCCEdge, m_vCCLoop))
|
||||||
continue ;
|
continue ;
|
||||||
//Tree.GetPolygonsBasic( vPL, true) ; // per usare i polygon basic
|
//Tree.GetPolygonsBasic( vPL, true) ; // per usare i polygon basic
|
||||||
|
|
||||||
// aggiorno la chiusura della superficie
|
// aggiorno la chiusura della superficie
|
||||||
m_bClosedU = m_bClosedU || Tree.IsClosedU() ;
|
m_bClosedU = m_bClosedU || Tree.IsClosedU() ;
|
||||||
m_bClosedV = m_bClosedV || Tree.IsClosedV() ;
|
m_bClosedV = m_bClosedV || Tree.IsClosedV() ;
|
||||||
// salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria
|
//// salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria
|
||||||
UpdateEdgesFromTree( Tree) ;
|
// UpdateEdgesFromTree( Tree) ; // ora viene fatto nella GetPolygons
|
||||||
}
|
}
|
||||||
|
|
||||||
//// per usare i polygon basic//////////////////////
|
//// per usare i polygon basic//////////////////////
|
||||||
@@ -1860,6 +1981,7 @@ SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
|
|||||||
//Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ; // per debug
|
//Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ; // per debug
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
//Tree.BuildTree( 100 * LIN_TOL_FINE, 0.1) ;
|
||||||
Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ;
|
Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ;
|
||||||
}
|
}
|
||||||
vector<Cell> vCells ;
|
vector<Cell> vCells ;
|
||||||
@@ -1896,6 +2018,9 @@ SurfBezier::ResetAuxSurf( void) const
|
|||||||
if ( m_pSTM != nullptr)
|
if ( m_pSTM != nullptr)
|
||||||
delete( m_pSTM) ;
|
delete( m_pSTM) ;
|
||||||
m_pSTM = nullptr ;
|
m_pSTM = nullptr ;
|
||||||
|
if ( m_pSTMRefined != nullptr)
|
||||||
|
delete( m_pSTMRefined) ;
|
||||||
|
m_pSTMRefined = nullptr ;
|
||||||
|
|
||||||
m_mCCEdge.clear() ;
|
m_mCCEdge.clear() ;
|
||||||
m_vCCLoop.clear() ;
|
m_vCCLoop.clear() ;
|
||||||
@@ -1938,6 +2063,8 @@ bool
|
|||||||
SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bool bModifyOrig) const
|
SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bool bModifyOrig) const
|
||||||
{
|
{
|
||||||
double dUVTest ;
|
double dUVTest ;
|
||||||
|
if (dUVCopy == nullptr && !bModifyOrig)
|
||||||
|
return false ;
|
||||||
if ( dUVCopy != nullptr) {
|
if ( dUVCopy != nullptr) {
|
||||||
*dUVCopy = dUV + dxy ;
|
*dUVCopy = dUV + dxy ;
|
||||||
dUVTest = *dUVCopy ;
|
dUVTest = *dUVCopy ;
|
||||||
@@ -1994,6 +2121,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR&
|
|||||||
// aggiungo tutti i successivi
|
// aggiungo tutti i successivi
|
||||||
BIPNTVECTOR vBPnt ;
|
BIPNTVECTOR vBPnt ;
|
||||||
|
|
||||||
|
// per il primo punto non mi interessa sapere se è passato attraverso un edge, tanto ha già le coordinate parametriche giuste
|
||||||
bThroughEdge = false ;
|
bThroughEdge = false ;
|
||||||
int nRejected = 0 ;
|
int nRejected = 0 ;
|
||||||
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
|
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
|
||||||
@@ -2143,38 +2271,38 @@ struct hash<TRINT> {
|
|||||||
// Compute individual hash values for first, second and third and combine them using XOR and bit shifting:
|
// Compute individual hash values for first, second and third and combine them using XOR and bit shifting:
|
||||||
return ((hash<int>()(get<0>(t))) ^ (hash<int>()(get<1>(t)) << 1) >> 1) ^ (hash<int>()(get<2>(t)) << 1) ;
|
return ((hash<int>()(get<0>(t))) ^ (hash<int>()(get<1>(t)) << 1) >> 1) ^ (hash<int>()(get<2>(t)) << 1) ;
|
||||||
}
|
}
|
||||||
};
|
} ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ISurfFlatRegion*
|
ISurfFlatRegion*
|
||||||
SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const
|
SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const
|
||||||
{
|
{
|
||||||
//comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti
|
// comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti
|
||||||
SurfFlatRegionByContours sfrContour ;
|
SurfFlatRegionByContours sfrContour ;
|
||||||
if ( int(vpCCOpen.size()) != 0 ) {
|
if ( int(vpCCOpen.size()) != 0 ) {
|
||||||
// recupero la regione attuale
|
// recupero la regione attuale
|
||||||
PtrOwner<ISurfFlatRegion> pNewTrim( CreateBasicSurfFlatRegion()) ;
|
PtrOwner<ISurfFlatRegion> pNewTrim( CreateBasicSurfFlatRegion()) ;
|
||||||
if ( m_bTrimmed)
|
if ( m_bTrimmed)
|
||||||
pNewTrim.Set( GetTrimRegion()->Clone()) ;
|
pNewTrim.Set( GetTrimRegion()->Clone()) ;
|
||||||
else
|
else
|
||||||
pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
|
pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
|
||||||
|
|
||||||
// costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region
|
// costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della flat region
|
||||||
unordered_map<TRINT,ICCIVECTOR> mInters ;
|
unordered_map<TRINT,ICCIVECTOR> mInters ;
|
||||||
int nInters = 0 ;
|
int nInters = 0 ;
|
||||||
bool bStartFound = false ;
|
bool bStartFound = false ;
|
||||||
bool bEndFound = false ;
|
bool bEndFound = false ;
|
||||||
// trim
|
// trim
|
||||||
for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) {
|
for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) {
|
||||||
nInters = 0 ;
|
nInters = 0 ;
|
||||||
bStartFound = false ;
|
bStartFound = false ;
|
||||||
bEndFound = false ;
|
bEndFound = false ;
|
||||||
//chunk
|
// chunk
|
||||||
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
|
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
|
||||||
// loop
|
// loop
|
||||||
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
|
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
|
||||||
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
|
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
|
||||||
// prima curva è il loop, seconda curva è il trim
|
// prima curva è il loop, seconda curva è il trim
|
||||||
IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ;
|
IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ;
|
||||||
if ( icc.GetIntersCount() != 0) {
|
if ( icc.GetIntersCount() != 0) {
|
||||||
ICCIVECTOR vICC ;
|
ICCIVECTOR vICC ;
|
||||||
@@ -2199,7 +2327,7 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( nInters != 2) {
|
if ( nInters != 2) {
|
||||||
// se un trim non fa 2 intersezioni allora devo estendere la curva allo start e/o all'end per creare le intersezioni
|
// se un trim non fa 2 intersezioni allora devo estendere la curva allo start e/o all'end per creare le intersezioni
|
||||||
Point3d ptStart ; vpCCOpen[t]->GetStartPoint( ptStart) ;
|
Point3d ptStart ; vpCCOpen[t]->GetStartPoint( ptStart) ;
|
||||||
Point3d ptEnd ; vpCCOpen[t]->GetEndPoint( ptEnd) ;
|
Point3d ptEnd ; vpCCOpen[t]->GetEndPoint( ptEnd) ;
|
||||||
PtrOwner<ICurve> pCrv( vpCCOpen[t]->Clone()) ;
|
PtrOwner<ICurve> pCrv( vpCCOpen[t]->Clone()) ;
|
||||||
@@ -2210,19 +2338,19 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
if ( ! bEndFound)
|
if ( ! bEndFound)
|
||||||
pCrv->ExtendEndByLen( dExtension) ;
|
pCrv->ExtendEndByLen( dExtension) ;
|
||||||
double dDistStart = 1e6, dDistEnd = 1e6 ;
|
double dDistStart = 1e6, dDistEnd = 1e6 ;
|
||||||
// vettore per l'intersezione di start
|
// vettore per l'intersezione di start
|
||||||
ICCIVECTOR vICCStart ;
|
ICCIVECTOR vICCStart ;
|
||||||
vICCStart.emplace_back() ;
|
vICCStart.emplace_back() ;
|
||||||
// vettore per l'intersezione di end
|
// vettore per l'intersezione di end
|
||||||
ICCIVECTOR vICCEnd ;
|
ICCIVECTOR vICCEnd ;
|
||||||
vICCEnd.emplace_back() ;
|
vICCEnd.emplace_back() ;
|
||||||
TRINT tStart, tEnd ;
|
TRINT tStart, tEnd ;
|
||||||
//chunk
|
// chunk
|
||||||
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
|
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
|
||||||
// loop
|
// loop
|
||||||
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
|
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
|
||||||
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
|
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
|
||||||
// prima curva è il loop, seconda curva è il trim
|
// prima curva è il loop, seconda curva è il trim
|
||||||
IntersCurveCurve icc( *pLoop, *pCrv) ;
|
IntersCurveCurve icc( *pLoop, *pCrv) ;
|
||||||
if ( icc.GetIntersCount() != 0) {
|
if ( icc.GetIntersCount() != 0) {
|
||||||
for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) {
|
for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) {
|
||||||
@@ -2242,29 +2370,29 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ricostruisco gli elementi per la mappa mInters
|
// ricostruisco gli elementi per la mappa mInters
|
||||||
if ( ! bStartFound && ! bEndFound) {
|
if ( ! bStartFound && ! bEndFound) {
|
||||||
// ridefinisco il taglio aperto con la sua versione estesa che arriva a toccare i loop dello spazio parametrico
|
// ridefinisco il taglio aperto con la sua versione estesa che arriva a toccare i loop dello spazio parametrico
|
||||||
vpCCOpen[t].Set( GetCurveComposite(pCrv->CopyParamRange( vICCStart[0].IciB->dU, vICCEnd[0].IciB->dU))) ;
|
vpCCOpen[t].Set( GetCurveComposite(pCrv->CopyParamRange( vICCStart[0].IciB->dU, vICCEnd[0].IciB->dU))) ;
|
||||||
// correggo il parametro dell'intersezione allo start
|
// correggo il parametro dell'intersezione allo start
|
||||||
vICCStart[0].IciB->dU = 0 ;
|
vICCStart[0].IciB->dU = 0 ;
|
||||||
if ( tStart == tEnd) {
|
if ( tStart == tEnd) {
|
||||||
// se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni
|
// se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni
|
||||||
vICCStart.emplace_back( vICCEnd[0]) ;
|
vICCStart.emplace_back( vICCEnd[0]) ;
|
||||||
mInters.insert( pair<TRINT,ICCIVECTOR>(tStart, vICCStart)) ;
|
mInters.insert( pair<TRINT,ICCIVECTOR>(tStart, vICCStart)) ;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// se ho intersezione con due loop diverse due entry diverse le inserisco
|
// se ho intersezione con due loop diverse due entry diverse le inserisco
|
||||||
mInters.insert( pair<TRINT,ICCIVECTOR>(tStart, vICCStart)) ;
|
mInters.insert( pair<TRINT,ICCIVECTOR>(tStart, vICCStart)) ;
|
||||||
mInters.insert( pair<TRINT,ICCIVECTOR>(tEnd, vICCEnd)) ;
|
mInters.insert( pair<TRINT,ICCIVECTOR>(tEnd, vICCEnd)) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// devo verificare se avevo già trovato una delle due intersezioni e se era sullo stesso loop o no
|
// devo verificare se avevo già trovato una delle due intersezioni e se era sullo stesso loop o no
|
||||||
if ( ! bStartFound) {
|
if ( ! bStartFound) {
|
||||||
pCrv->TrimStartAtParam( vICCStart[0].IciB->dU) ;
|
pCrv->TrimStartAtParam( vICCStart[0].IciB->dU) ;
|
||||||
vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ;
|
vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ;
|
||||||
// correggo il parametro dell'intersezione allo start
|
// correggo il parametro dell'intersezione allo start
|
||||||
vICCStart[0].IciB->dU = 0 ;
|
vICCStart[0].IciB->dU = 0 ;
|
||||||
if ( mInters.count( tStart) == 1)
|
if ( mInters.count( tStart) == 1)
|
||||||
mInters[tStart].emplace_back( vICCStart[0]) ;
|
mInters[tStart].emplace_back( vICCStart[0]) ;
|
||||||
@@ -2283,55 +2411,61 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo
|
// vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo
|
||||||
BOOLVECTOR vbAdded( vpCCOpen.size()) ;
|
BOOLVECTOR vbAdded( vpCCOpen.size()) ;
|
||||||
fill( vbAdded.begin(), vbAdded.end(), false) ;
|
fill( vbAdded.begin(), vbAdded.end(), false) ;
|
||||||
PtrOwner<ICurveComposite> pCCNewEdge( CreateCurveComposite()) ;
|
PtrOwner<ICurveComposite> pCCNewEdge( CreateCurveComposite()) ;
|
||||||
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
|
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
|
||||||
TRINT tiFirstInters ;
|
TRINT tiFirstInters ;
|
||||||
// parto aggiungendo il primo taglio
|
// parto aggiungendo il primo taglio
|
||||||
int nNewToAdd = 0 ;
|
int nNewToAdd = 0 ;
|
||||||
bool bFirstCurveOfEdge = true ;
|
bool bFirstCurveOfEdge = true ;
|
||||||
while ( nNewToAdd != -1) {
|
while ( nNewToAdd != -1) {
|
||||||
// aggiungo il taglio
|
// aggiungo il taglio
|
||||||
pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ;
|
pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ;
|
||||||
// aggiorno la lista degli aggiunti
|
// aggiorno la lista degli aggiunti
|
||||||
vbAdded[nNewToAdd] = true ;
|
vbAdded[nNewToAdd] = true ;
|
||||||
// di questo taglio mi salvo il chunk e loop di start e end
|
// di questo taglio mi salvo il chunk e loop di start e end
|
||||||
TRINT tiStart, tiEnd ;
|
TRINT tiStart, tiEnd ;
|
||||||
|
bool bStartFound = false ;
|
||||||
|
bool bEndFound = false ;
|
||||||
for (const auto& pair : mInters) {
|
for (const auto& pair : mInters) {
|
||||||
if ( get<2>(pair.first) == nNewToAdd ) {
|
if ( get<2>(pair.first) == nNewToAdd ) {
|
||||||
for (int p = 0 ; p < int(pair.second.size()) ; ++p) {
|
for (int p = 0 ; p < int(pair.second.size()) ; ++p) {
|
||||||
if ( pair.second[p].IciB->dU < EPS_SMALL) {
|
if ( pair.second[p].IciB->dU < EPS_SMALL) {
|
||||||
tiStart = pair.first ;
|
tiStart = pair.first ;
|
||||||
|
bStartFound = true ;
|
||||||
if ( bFirstCurveOfEdge){
|
if ( bFirstCurveOfEdge){
|
||||||
// salvo l'inizio del taglio che è la prima curva di questa curva compo
|
// salvo l'inizio del taglio che è la prima curva di questa curva compo
|
||||||
tiFirstInters = pair.first ;
|
tiFirstInters = pair.first ;
|
||||||
bFirstCurveOfEdge = false ;
|
bFirstCurveOfEdge = false ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
tiEnd = pair.first ;
|
tiEnd = pair.first ;
|
||||||
|
bEndFound = true ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( ! bEndFound || ! bStartFound)
|
||||||
// devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente
|
return nullptr ;
|
||||||
// devo quindi trovare la prossima intersezione con un taglio
|
// devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente
|
||||||
|
// devo quindi trovare la prossima intersezione con un taglio
|
||||||
int nInters = -1 ;
|
int nInters = -1 ;
|
||||||
double dNextCut = INFINITO ;
|
double dNextCut = INFINITO ;
|
||||||
double dEndCurrentCut ;
|
double dEndCurrentCut = 0 ;
|
||||||
for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) {
|
for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) {
|
||||||
// se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop
|
// se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop
|
||||||
if ( mInters[tiEnd][i].IciB->dU > EPS_SMALL)
|
if ( mInters[tiEnd][i].IciB->dU > EPS_SMALL)
|
||||||
dEndCurrentCut = mInters[tiEnd][i].IciA->dU ;
|
dEndCurrentCut = mInters[tiEnd][i].IciA->dU ;
|
||||||
}
|
}
|
||||||
// se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop
|
// se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop
|
||||||
for ( const auto& pair : mInters) {
|
for ( const auto& pair : mInters) {
|
||||||
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
|
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
|
||||||
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
|
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
|
||||||
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
|
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
|
||||||
// mi salvo questa nuova che ho trovato
|
// mi salvo questa nuova che ho trovato
|
||||||
if ( pair.second[i].IciA->dU < dNextCut && pair.second[i].IciA->dU > dEndCurrentCut) {
|
if ( pair.second[i].IciA->dU < dNextCut && pair.second[i].IciA->dU > dEndCurrentCut) {
|
||||||
dNextCut = pair.second[i].IciA->dU ;
|
dNextCut = pair.second[i].IciA->dU ;
|
||||||
nInters = get<2>(pair.first) ;
|
nInters = get<2>(pair.first) ;
|
||||||
@@ -2344,8 +2478,8 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
for ( const auto& pair : mInters) {
|
for ( const auto& pair : mInters) {
|
||||||
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
|
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
|
||||||
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
|
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
|
||||||
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
|
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
|
||||||
// mi salvo questa nuova che ho trovato
|
// mi salvo questa nuova che ho trovato
|
||||||
if ( pair.second[i].IciA->dU < dNextCut) {
|
if ( pair.second[i].IciA->dU < dNextCut) {
|
||||||
dNextCut = pair.second[i].IciA->dU ;
|
dNextCut = pair.second[i].IciA->dU ;
|
||||||
nInters = get<2>(pair.first) ;
|
nInters = get<2>(pair.first) ;
|
||||||
@@ -2355,19 +2489,19 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// se tutto va bene queste due righe sostituiscono tutto il casino qua sotto
|
// se tutto va bene queste due righe sostituiscono tutto il casino qua sotto
|
||||||
PtrOwner<ICurve> pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ;
|
PtrOwner<ICurve> pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ;
|
||||||
pCCNewEdge->AddCurve(pLoopTrimmed->CopyParamRange( dEndCurrentCut, dNextCut)) ;
|
pCCNewEdge->AddCurve(pLoopTrimmed->CopyParamRange( dEndCurrentCut, dNextCut)) ;
|
||||||
|
|
||||||
// se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento
|
// se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento
|
||||||
// alla flat region e comincio a costruire un altro bordo
|
// alla flat region e comincio a costruire un altro bordo
|
||||||
// altrimenti continuo ad aggiungere curve al bordo corrente
|
// altrimenti continuo ad aggiungere curve al bordo corrente
|
||||||
if ( nInters == get<2>(tiFirstInters) ) {
|
if ( nInters == get<2>(tiFirstInters) ) {
|
||||||
pCCNewEdge->Close() ;
|
pCCNewEdge->Close() ;
|
||||||
sfrContour.AddCurve( Release( pCCNewEdge)) ;
|
sfrContour.AddCurve( Release( pCCNewEdge)) ;
|
||||||
pCCNewEdge.Set( CreateBasicCurveComposite()) ;
|
pCCNewEdge.Set( CreateBasicCurveComposite()) ;
|
||||||
bFirstCurveOfEdge = true ;
|
bFirstCurveOfEdge = true ;
|
||||||
// trovo il prossimo taglio ancora da aggiungere
|
// trovo il prossimo taglio ancora da aggiungere
|
||||||
nNewToAdd = -1 ;
|
nNewToAdd = -1 ;
|
||||||
for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) {
|
for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) {
|
||||||
if ( ! vbAdded[b]) {
|
if ( ! vbAdded[b]) {
|
||||||
@@ -2381,9 +2515,9 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// devo verificare se devo aggiungere anche il bordo ( basta verificare se il primo loop chiuso è CCW)
|
// devo verificare se devo aggiungere anche il bordo ( basta verificare se il primo loop chiuso è CCW)
|
||||||
double dArea ;
|
double dArea ;
|
||||||
if( vpCCClosed.size() != 0) {
|
if ( ! vpCCClosed.empty()) {
|
||||||
vpCCClosed[0]->GetAreaXY( dArea) ;
|
vpCCClosed[0]->GetAreaXY( dArea) ;
|
||||||
if ( dArea < EPS_SMALL ) {
|
if ( dArea < EPS_SMALL ) {
|
||||||
PolyLine plEdge ;
|
PolyLine plEdge ;
|
||||||
@@ -2423,7 +2557,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
|||||||
PNTVECTOR vPnt ;
|
PNTVECTOR vPnt ;
|
||||||
BIPNTVECTOR vBPnt ;
|
BIPNTVECTOR vBPnt ;
|
||||||
TRIA3DVECTOR vTria ;
|
TRIA3DVECTOR vTria ;
|
||||||
IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ;
|
IntersPlaneSurfTm( plPlane, *GetAuxSurfRefined(), vPnt, vBPnt, vTria) ;
|
||||||
|
|
||||||
// concateno le curve 3d
|
// concateno le curve 3d
|
||||||
ChainCurves chainC ;
|
ChainCurves chainC ;
|
||||||
@@ -2494,8 +2628,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
|||||||
vpCCClosed.back()->FromPolyLine( vPLTria[i]) ;
|
vpCCClosed.back()->FromPolyLine( vPLTria[i]) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ora posso chiamare la costruzione dello spazio parametrico trimmato
|
// ora posso chiamare la costruzione dello spazio parametrico trimmato
|
||||||
|
|
||||||
PtrOwner<ISurfFlatRegion> pSFR( CreateTrimRegionFromCuts( vpCCOpen, vpCCClosed)) ;
|
PtrOwner<ISurfFlatRegion> pSFR( CreateTrimRegionFromCuts( vpCCOpen, vpCCClosed)) ;
|
||||||
if ( IsNull( pSFR) || ! pSFR->IsValid())
|
if ( IsNull( pSFR) || ! pSFR->IsValid())
|
||||||
return false ;
|
return false ;
|
||||||
@@ -2511,9 +2644,8 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
|||||||
double dAreaMin = 1e30 ;
|
double dAreaMin = 1e30 ;
|
||||||
bool bPos = false ;
|
bool bPos = false ;
|
||||||
for ( int c = 0 ; c < int( pSFR->GetChunkCount()); ++c) {
|
for ( int c = 0 ; c < int( pSFR->GetChunkCount()); ++c) {
|
||||||
PtrOwner<ISurfFlatRegion> pSurf( pSFR->CloneChunk( c)) ;
|
for ( int l = 0 ; l < pSFR->GetLoopCount( c); ++l) {
|
||||||
for ( int l = 0 ; l < pSurf->GetLoopCount( 0); ++l) {
|
PtrOwner<ICurve> pCrv( pSFR->GetLoop( c, l)) ;
|
||||||
PtrOwner<ICurve> pCrv( pSurf->GetLoop( 0, l)) ;
|
|
||||||
double dArea ; pCrv->GetAreaXY( dArea) ;
|
double dArea ; pCrv->GetAreaXY( dArea) ;
|
||||||
if ( abs( dArea) < dAreaMin) {
|
if ( abs( dArea) < dAreaMin) {
|
||||||
nChunkMin = c ;
|
nChunkMin = c ;
|
||||||
@@ -2575,6 +2707,9 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
|
|||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//// taglio la trimesh col piano // questa operazione richiederebbe di ricavare anche i nuovi edge 2D e edge3D, che normalmente sarebbero calcolati durante la GetAuxSurf dal tree
|
||||||
|
//m_pSTM->Cut( plPlane, bSaveOnEq) ;
|
||||||
|
|
||||||
// imposto ricalcolo della grafica
|
// imposto ricalcolo della grafica
|
||||||
m_OGrMgr.Reset() ;
|
m_OGrMgr.Reset() ;
|
||||||
|
|
||||||
@@ -2596,7 +2731,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
if ( bThroughEdge != nullptr)
|
if ( bThroughEdge != nullptr)
|
||||||
*bThroughEdge = false ;
|
*bThroughEdge = false ;
|
||||||
// dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche
|
// dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche
|
||||||
const ISurfTriMesh* pSurfTm = GetAuxSurf() ;
|
const ISurfTriMesh* pSurfTm = GetAuxSurfRefined() ;
|
||||||
int nTriaIndex = nT ;
|
int nTriaIndex = nT ;
|
||||||
if ( nT == -1) {
|
if ( nT == -1) {
|
||||||
DistPointSurfTm distPtStm0( ptI, *pSurfTm) ;
|
DistPointSurfTm distPtStm0( ptI, *pSurfTm) ;
|
||||||
@@ -2623,6 +2758,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
if ( ! m_mCCEdge[c][i]->GetOnlyPoint(pt))
|
if ( ! m_mCCEdge[c][i]->GetOnlyPoint(pt))
|
||||||
return false ;
|
return false ;
|
||||||
vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ;
|
vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ;
|
||||||
|
if ( vInters[c] == 1)
|
||||||
|
bIsPole = true ;
|
||||||
nInters += vInters[c] ;
|
nInters += vInters[c] ;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2634,9 +2771,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
|
|
||||||
// se ho tre intersezioni vuol dire che un lato è collassato in un punto e il punto di cui voglio la controimmagine è esattamente nel polo
|
// se ho tre intersezioni vuol dire che un lato è collassato in un punto e il punto di cui voglio la controimmagine è esattamente nel polo
|
||||||
// oppure sono su un lato di chiusura
|
// oppure sono su un lato di chiusura
|
||||||
if ( nInters == 3 || ( m_bClosedU && ( vInters[1] == 1 || vInters[3] == 1)) || ( m_bClosedV && ( vInters[0] == 1 || vInters[2] == 1))) {
|
if ( bIsPole || ( m_bClosedU && ( vInters[1] == 1 || vInters[3] == 1)) || ( m_bClosedV && ( vInters[0] == 1 || vInters[2] == 1))) {
|
||||||
if ( nInters == 3)
|
|
||||||
bIsPole = true ;
|
|
||||||
// visto che sono in un polo o su un lato di chiusura devo verificare di aver ricevuto il triangolo giusto
|
// visto che sono in un polo o su un lato di chiusura devo verificare di aver ricevuto il triangolo giusto
|
||||||
// se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza
|
// se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza
|
||||||
if ( ! ptIPrevOrNext.IsValid())
|
if ( ! ptIPrevOrNext.IsValid())
|
||||||
@@ -2661,7 +2796,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
pSurfTm->GetVertex( nVert[0], vPT[0]) ;
|
pSurfTm->GetVertex( nVert[0], vPT[0]) ;
|
||||||
pSurfTm->GetVertex( nVert[1], vPT[1]) ;
|
pSurfTm->GetVertex( nVert[1], vPT[1]) ;
|
||||||
pSurfTm->GetVertex( nVert[2], vPT[2]) ;
|
pSurfTm->GetVertex( nVert[2], vPT[2]) ;
|
||||||
// devo capire se il trinagolo ha un vertice su un polo
|
// devo capire se il triangolo ha un vertice su un polo
|
||||||
int nVertOnPole = -1 ;
|
int nVertOnPole = -1 ;
|
||||||
int nEdge = -1 ;
|
int nEdge = -1 ;
|
||||||
// do per scontato che al più un vertice possa essere in un polo
|
// do per scontato che al più un vertice possa essere in un polo
|
||||||
@@ -2695,13 +2830,16 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici
|
// se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici
|
||||||
double dParamH, dParamL ;
|
double dParamH = 0, dParamL = 0 ;
|
||||||
|
INTVECTOR vOn(3) ;
|
||||||
|
fill( vOn.begin(), vOn.end(), -1) ;
|
||||||
|
bool bOneVertexOnClosureButNotPole = false ;
|
||||||
if ( m_bClosedU || m_bClosedV) {
|
if ( m_bClosedU || m_bClosedV) {
|
||||||
dParamH = m_nSpanV * SBZ_TREG_COEFF ;
|
dParamH = m_nSpanV * SBZ_TREG_COEFF ;
|
||||||
dParamL = m_nSpanU * SBZ_TREG_COEFF ;
|
dParamL = m_nSpanU * SBZ_TREG_COEFF ;
|
||||||
// devo trovare il lato più lungo e confrontarlo con le dimensioni dello spazio parametrico
|
// devo trovare il lato più lungo e confrontarlo con le dimensioni dello spazio parametrico
|
||||||
Vector3d vtDir ;
|
Vector3d vtDir ;
|
||||||
double dDist ;
|
double dDist = 0 ;
|
||||||
if ( DistXY( vPtPa[0], vPtPa[1]) > DistXY( vPtPa[1], vPtPa[2]) && DistXY( vPtPa[0], vPtPa[1]) > Dist( vPtPa[0], vPtPa[2])){
|
if ( DistXY( vPtPa[0], vPtPa[1]) > DistXY( vPtPa[1], vPtPa[2]) && DistXY( vPtPa[0], vPtPa[1]) > Dist( vPtPa[0], vPtPa[2])){
|
||||||
vtDir = vPtPa[1] - vPtPa[0] ;
|
vtDir = vPtPa[1] - vPtPa[0] ;
|
||||||
dDist = DistXY( vPtPa[0], vPtPa[1]) ;
|
dDist = DistXY( vPtPa[0], vPtPa[1]) ;
|
||||||
@@ -2720,8 +2858,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
// do per scontato che se la superficie è chiusa lungo un parametro i lati di chiusura non siano dei poli
|
// do per scontato che se la superficie è chiusa lungo un parametro i lati di chiusura non siano dei poli
|
||||||
if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) {
|
if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) {
|
||||||
// trovo se dei vertici del triangolo sono sul bordo dello spazio parametrico
|
// trovo se dei vertici del triangolo sono sul bordo dello spazio parametrico
|
||||||
INTVECTOR vOn(3) ;
|
|
||||||
fill( vOn.begin(), vOn.end(), -1) ;
|
|
||||||
INTVECTOR vEdgesClosed = { 1, 3} ;
|
INTVECTOR vEdgesClosed = { 1, 3} ;
|
||||||
// scorro sui vertici
|
// scorro sui vertici
|
||||||
for ( int p = 0 ; p < 3; ++p ) {
|
for ( int p = 0 ; p < 3; ++p ) {
|
||||||
@@ -2736,12 +2872,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
// controllo che almeno un vertice sia su un edge e se è l'unico vertice, che non sia su un polo
|
// controllo che almeno un vertice sia su un edge e se è l'unico vertice, che non sia su un polo
|
||||||
if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) {
|
if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) {
|
||||||
// se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate
|
// se ho più di un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate
|
||||||
if ( vOn[0] * vOn[1] * vOn[2] < 0 ||
|
bOneVertexOnClosureButNotPole = (vOn[0] > 0 && 0 != nVertOnPole) ||
|
||||||
(vOn[0] > 0 && 0 != nVertOnPole) ||
|
(vOn[1] > 0 && 1 != nVertOnPole) ||
|
||||||
(vOn[1] > 0 && 1 != nVertOnPole) ||
|
(vOn[2] > 0 && 2 != nVertOnPole) ;
|
||||||
(vOn[2] > 0 && 2 != nVertOnPole)) {
|
if ( vOn[0] * vOn[1] * vOn[2] < 0 || bOneVertexOnClosureButNotPole) {
|
||||||
double dRightX ;
|
double dRightX = 0 ;
|
||||||
// tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico
|
// tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico
|
||||||
for ( int p = 0 ; p < 3; ++p) {
|
for ( int p = 0 ; p < 3; ++p) {
|
||||||
if ( vOn[p] == -1) {
|
if ( vOn[p] == -1) {
|
||||||
@@ -2750,7 +2886,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( int p = 0 ; p < 3; ++p) {
|
for ( int p = 0 ; p < 3; ++p) {
|
||||||
if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) {
|
//if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) {
|
||||||
|
if ( abs(vPtPa[p].x - dRightX) > SBZ_TREG_COEFF / 2) {
|
||||||
if ( vPtPa[p].x < EPS_SMALL)
|
if ( vPtPa[p].x < EPS_SMALL)
|
||||||
vPtPa[p].x = dParamL ;
|
vPtPa[p].x = dParamL ;
|
||||||
else
|
else
|
||||||
@@ -2761,8 +2898,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) {
|
else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) {
|
||||||
INTVECTOR vOn(3) ;
|
|
||||||
fill( vOn.begin(), vOn.end(), -1) ;
|
|
||||||
int nVertOnPole = -1 ;
|
int nVertOnPole = -1 ;
|
||||||
INTVECTOR vEdgesClosed = { 0, 2} ;
|
INTVECTOR vEdgesClosed = { 0, 2} ;
|
||||||
// scorro sui vertici
|
// scorro sui vertici
|
||||||
@@ -2779,11 +2914,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
// controllo che almeno un vertice sia su un edge
|
// controllo che almeno un vertice sia su un edge
|
||||||
if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) {
|
if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) {
|
||||||
// se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate
|
// se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate
|
||||||
if ( vOn[0] * vOn[1] * vOn[2] < 0 ||
|
bOneVertexOnClosureButNotPole = (vOn[0] > 0 && 0 != nVertOnPole) ||
|
||||||
(vOn[0] > 0 && 0 != nVertOnPole) ||
|
(vOn[1] > 0 && 1 != nVertOnPole) ||
|
||||||
(vOn[1] > 0 && 1 != nVertOnPole) ||
|
(vOn[2] > 0 && 2 != nVertOnPole) ;
|
||||||
(vOn[2] > 0 && 2 != nVertOnPole)) {
|
if ( vOn[0] * vOn[1] * vOn[2] < 0 || bOneVertexOnClosureButNotPole) {
|
||||||
double dRightY ;
|
double dRightY = 0 ;
|
||||||
// tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico
|
// tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico
|
||||||
for ( int p = 0 ; p < 3; ++p) {
|
for ( int p = 0 ; p < 3; ++p) {
|
||||||
if ( vOn[p] == -1) {
|
if ( vOn[p] == -1) {
|
||||||
@@ -2792,7 +2927,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( int p = 0 ; p < 3; ++p) {
|
for ( int p = 0 ; p < 3; ++p) {
|
||||||
if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) {
|
//if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) {
|
||||||
|
if ( abs(vPtPa[p].y - dRightY) > SBZ_TREG_COEFF / 2) {
|
||||||
if ( vPtPa[p].y < EPS_SMALL)
|
if ( vPtPa[p].y < EPS_SMALL)
|
||||||
vPtPa[p].y = dParamH ;
|
vPtPa[p].y = dParamH ;
|
||||||
else
|
else
|
||||||
@@ -2802,6 +2938,25 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
for ( int p = 0 ; p < 3; ++p ) {
|
||||||
|
//scorro sugli edge
|
||||||
|
for (int ed = 0 ; ed < 4 ; ++ed) {
|
||||||
|
// scorro sui tratti che compongono l'edge
|
||||||
|
for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) {
|
||||||
|
if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1)
|
||||||
|
vOn[p] = ed ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// anche se non ho un triangolo molto stretchato potrei avere il punto di polo con coordinate parametriche sballate
|
||||||
|
bOneVertexOnClosureButNotPole = ((m_bClosedU && (vOn[0] == 1 || vOn[0] == 3)) && 0 != nVertOnPole) ||
|
||||||
|
((m_bClosedU && (vOn[1] == 1 || vOn[1] == 3)) && 1 != nVertOnPole) ||
|
||||||
|
((m_bClosedU && (vOn[2] == 1 || vOn[2] == 3)) && 2 != nVertOnPole) ||
|
||||||
|
((m_bClosedV && (vOn[0] == 0 || vOn[0] == 2)) && 0 != nVertOnPole) ||
|
||||||
|
((m_bClosedV && (vOn[1] == 0 || vOn[1] == 2)) && 1 != nVertOnPole) ||
|
||||||
|
((m_bClosedV && (vOn[2] == 0 || vOn[2] == 2)) && 2 != nVertOnPole) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// devo anche tener conto della possibilità che i lati siano collassati in poli
|
// devo anche tener conto della possibilità che i lati siano collassati in poli
|
||||||
if ( bIsPole || bNearPole) {
|
if ( bIsPole || bNearPole) {
|
||||||
@@ -2809,16 +2964,28 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
|
|||||||
if ( nEdge == -1)
|
if ( nEdge == -1)
|
||||||
return false ;
|
return false ;
|
||||||
// trovo la coordinata giusta da tenere ( x o y a seconda dell'edge)
|
// trovo la coordinata giusta da tenere ( x o y a seconda dell'edge)
|
||||||
double dRightX, dRightY ;
|
double dRightX = 0, dRightY = 0 ;
|
||||||
for ( int p = 0 ; p < 3; ++p) {
|
for ( int p = 0 ; p < 3; ++p) {
|
||||||
if ( p != nVertOnPole) {
|
if ( p != nVertOnPole) {
|
||||||
if ( nEdge == 0 || nEdge == 2) {
|
if ( nEdge == 0 || nEdge == 2) {
|
||||||
dRightX = vPtPa[p].x ;
|
|
||||||
dRightY = nEdge == 0 ? dParamH : 0 ;
|
dRightY = nEdge == 0 ? dParamH : 0 ;
|
||||||
|
if ( vPtPa[p].x > dRightX )
|
||||||
|
dRightX= vPtPa[p].x ;
|
||||||
|
// se un vertice è su un lato di chiusura, visto che sono vicino ad un polo, mi accerto che un lato del triangolo sia SUL lato di chiusura
|
||||||
|
if( m_bClosedU && bOneVertexOnClosureButNotPole) {
|
||||||
|
dRightX = ( dParamL - vPtPa[p].x > vPtPa[p].x ? 0 : dParamL) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( nEdge == 1 || nEdge == 3) {
|
else if ( nEdge == 1 || nEdge == 3) {
|
||||||
|
// se un vertice è su un lato di chiusura, visto che sono vicino ad un polo, mi accerto che un lato del triangolo sia SUL lato di chiusura
|
||||||
dRightX = nEdge == 1 ? 0 : dParamL ;
|
dRightX = nEdge == 1 ? 0 : dParamL ;
|
||||||
dRightY = vPtPa[p].y ;
|
if ( vPtPa[p].y > dRightY )
|
||||||
|
dRightY = vPtPa[p].y ;
|
||||||
|
if( m_bClosedV && bOneVertexOnClosureButNotPole) {
|
||||||
|
dRightY = ( dParamH - vPtPa[p].y > vPtPa[p].y ? 0 : dParamH) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2892,7 +3059,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d
|
|||||||
// trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D
|
// trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D
|
||||||
// ripeto cercando di avvicinarmi il più possibile
|
// ripeto cercando di avvicinarmi il più possibile
|
||||||
// per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino
|
// per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino
|
||||||
DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ;
|
DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurfRefined()) ;
|
||||||
Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ;
|
Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ;
|
||||||
if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge))
|
if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge))
|
||||||
return false ;
|
return false ;
|
||||||
@@ -3005,16 +3172,16 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d
|
|||||||
bool
|
bool
|
||||||
SurfBezier::CalcPoles( void) const
|
SurfBezier::CalcPoles( void) const
|
||||||
{
|
{
|
||||||
if ( m_vbPole.size() != 0)
|
if ( ! m_vbPole.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// la funzione identifica se degli edge della superficie non trimmata sono in realtà dei poli
|
// la funzione identifica se degli edge della superficie non trimmata sono in realtà dei poli
|
||||||
for ( int i = 0 ; i < 4 ; ++i)
|
for ( int i = 0 ; i < 4 ; ++i)
|
||||||
m_vbPole.emplace_back( true) ;
|
m_vbPole.emplace_back( true) ;
|
||||||
// scorro i punti di controllo e vedo subito
|
// scorro i punti di controllo e vedo subito
|
||||||
bool bOk = false ;
|
bool bOk = false ;
|
||||||
bool bPole0 = true, bPole1 = true ;
|
bool bPole0 = true, bPole1 = true ;
|
||||||
Point3d ptU0, ptU1 ;
|
Point3d ptU0, ptU1 ;
|
||||||
// controllo l'edge 0 e 2 per vedere se tutti i punti dell'edge sono coincidenti
|
// controllo l'edge 0 e 2 per vedere se tutti i punti dell'edge sono coincidenti
|
||||||
Point3d ptP00 = GetControlPoint( 0, &bOk) ;
|
Point3d ptP00 = GetControlPoint( 0, &bOk) ;
|
||||||
Point3d ptP10 = GetControlPoint( m_nDegU * m_nSpanU, &bOk) ;
|
Point3d ptP10 = GetControlPoint( m_nDegU * m_nSpanU, &bOk) ;
|
||||||
for ( int i = 1 ; i < m_nDegV * m_nSpanV + 1 ; ++ i) {
|
for ( int i = 1 ; i < m_nDegV * m_nSpanV + 1 ; ++ i) {
|
||||||
@@ -3027,7 +3194,7 @@ SurfBezier::CalcPoles( void) const
|
|||||||
}
|
}
|
||||||
m_vbPole[1] = bPole0 ; // u = 0 corrisponde all'edge 1
|
m_vbPole[1] = bPole0 ; // u = 0 corrisponde all'edge 1
|
||||||
m_vbPole[3] = bPole1 ; // u = 1 corrisponde all'edge 3
|
m_vbPole[3] = bPole1 ; // u = 1 corrisponde all'edge 3
|
||||||
// controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti
|
// controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti
|
||||||
Point3d ptV0, ptV1 ;
|
Point3d ptV0, ptV1 ;
|
||||||
Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ;
|
Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ;
|
||||||
bPole0 = true ;
|
bPole0 = true ;
|
||||||
@@ -3057,7 +3224,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
// se nEdge non è definito ( == -1) allora restituisco tutti gli edge in ordine
|
// se nEdge non è definito ( == -1) allora restituisco tutti gli edge in ordine
|
||||||
// se bOpenOrAll è true allora restituisco solo gli edge aperti e che non sono di polo
|
// se bOpenOrAll è true allora restituisco solo gli edge aperti e che non sono di polo
|
||||||
if ( m_pSTM == nullptr)
|
if ( m_pSTM == nullptr)
|
||||||
GetAuxSurf() ;
|
GetAuxSurfRefined() ;
|
||||||
|
|
||||||
// se la superficie non è trimmata mi basta recuperare gli edge della superficie
|
// se la superficie non è trimmata mi basta recuperare gli edge della superficie
|
||||||
if ( ! m_bTrimmed) {
|
if ( ! m_bTrimmed) {
|
||||||
@@ -3120,10 +3287,10 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
bool bInters = false ;
|
bool bInters = false ;
|
||||||
// devo controllare se i loop si appoggiano a bordi chiusi
|
// devo controllare se i loop si appoggiano a bordi chiusi
|
||||||
// se ne ho più di uno che si appoggia allora devo vedere se trovo dei gruppi di loop che in realtà in 3d sono un edge unico, ma nel 2d risultano a cavallo dell'edge di chiusura
|
// se ne ho più di uno che si appoggia allora devo vedere se trovo dei gruppi di loop che in realtà in 3d sono un edge unico, ma nel 2d risultano a cavallo dell'edge di chiusura
|
||||||
PtrOwner<ICurveComposite> pLoop( m_vCCLoop[l]->Clone()) ;
|
//PtrOwner<ICurveComposite> pLoop( m_vCCLoop[l]->Clone()) ;
|
||||||
for ( int j = 0 ; j < 4 ; ++j) {
|
for ( int j = 0 ; j < 4 ; ++j) {
|
||||||
// il primo è un loop di trim, il secondo è un edge dello spazio parametrico
|
// il primo è un loop di trim, il secondo è un edge dello spazio parametrico
|
||||||
IntersCurveCurve icc( *pLoop, *vEdge[j]) ;
|
IntersCurveCurve icc( *m_vCCLoop[l], *vEdge[j]) ;
|
||||||
ICCIVECTOR vICC ;
|
ICCIVECTOR vICC ;
|
||||||
for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i ) {
|
for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i ) {
|
||||||
IntCrvCrvInfo iccInfo ;
|
IntCrvCrvInfo iccInfo ;
|
||||||
@@ -3143,7 +3310,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
// scorro i loop che fanno intersezioni con l'edge 0 ( V=1) e le riporto sull'edge opposto
|
// scorro i loop che fanno intersezioni con l'edge 0 ( V=1) e le riporto sull'edge opposto
|
||||||
for ( pair<int, ICCIVECTOR> vInters0 : vmInters[0]) {
|
for ( pair<int, ICCIVECTOR> vInters0 : vmInters[0]) {
|
||||||
// scorro le intersezioni del loop
|
// scorro le intersezioni del loop
|
||||||
for ( IntCrvCrvInfo inters0 : vInters0.second) {
|
for ( IntCrvCrvInfo& inters0 : vInters0.second) {
|
||||||
if ( ! inters0.bOverlap)
|
if ( ! inters0.bOverlap)
|
||||||
continue ;
|
continue ;
|
||||||
Point3d ptStart0 = inters0.IciA[0].ptI ;
|
Point3d ptStart0 = inters0.IciA[0].ptI ;
|
||||||
@@ -3153,9 +3320,9 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
ptEnd0.y = 0 ;
|
ptEnd0.y = 0 ;
|
||||||
// scorro le intersezioni sull'edge opposto e quando trovo un loop che tra le sue intersezioni contiene uno dei punti che ho appena portato
|
// scorro le intersezioni sull'edge opposto e quando trovo un loop che tra le sue intersezioni contiene uno dei punti che ho appena portato
|
||||||
// su qusto edge allora cancello la parte comune
|
// su qusto edge allora cancello la parte comune
|
||||||
for ( pair<int, ICCIVECTOR> vInters2 : vmInters[2] ) {
|
for ( auto& vInters2 : vmInters[2] ) {
|
||||||
// scorro le intersezioni di questo loop
|
// scorro le intersezioni di questo loop
|
||||||
for ( IntCrvCrvInfo inters2 : vInters2.second) {
|
for ( IntCrvCrvInfo& inters2 : vInters2.second) {
|
||||||
// se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora
|
// se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora
|
||||||
// devo cancellare la parte comune
|
// devo cancellare la parte comune
|
||||||
Point3d ptStart2 = inters2.IciA[0].ptI ;
|
Point3d ptStart2 = inters2.IciA[0].ptI ;
|
||||||
@@ -3246,9 +3413,9 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
|
|
||||||
if ( m_bClosedU) {
|
if ( m_bClosedU) {
|
||||||
// scorro i loop che fanno intersezioni con l'edge 1 ( U=0) e le riporto sull'edge opposto
|
// scorro i loop che fanno intersezioni con l'edge 1 ( U=0) e le riporto sull'edge opposto
|
||||||
for ( pair<int, ICCIVECTOR> vInters1 : vmInters[1]) {
|
for ( auto& vInters1 : vmInters[1]) {
|
||||||
// scorro le intersezioni del loop
|
// scorro le intersezioni del loop
|
||||||
for ( IntCrvCrvInfo inters1 : vInters1.second) {
|
for ( IntCrvCrvInfo& inters1 : vInters1.second) {
|
||||||
if ( ! inters1.bOverlap)
|
if ( ! inters1.bOverlap)
|
||||||
continue ;
|
continue ;
|
||||||
Point3d ptStart1 = inters1.IciA[0].ptI ;
|
Point3d ptStart1 = inters1.IciA[0].ptI ;
|
||||||
@@ -3260,7 +3427,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
// su qusto edge allora cancello la parte comune
|
// su qusto edge allora cancello la parte comune
|
||||||
for ( pair<int, ICCIVECTOR> vInters3 : vmInters[3] ) {
|
for ( pair<int, ICCIVECTOR> vInters3 : vmInters[3] ) {
|
||||||
// scorro le intersezioni di questo loop
|
// scorro le intersezioni di questo loop
|
||||||
for ( IntCrvCrvInfo inters3 : vInters3.second) {
|
for ( IntCrvCrvInfo& inters3 : vInters3.second) {
|
||||||
// se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora
|
// se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora
|
||||||
// devo cancellare la parte comune
|
// devo cancellare la parte comune
|
||||||
Point3d ptStart3 = inters3.IciA[0].ptI ;
|
Point3d ptStart3 = inters3.IciA[0].ptI ;
|
||||||
@@ -3402,8 +3569,8 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
|
|||||||
ICurveComposite*
|
ICurveComposite*
|
||||||
SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
|
SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
|
||||||
{
|
{
|
||||||
if ( m_mCCEdge.size() == 0 && bLineOrBezier)
|
if ( m_mCCEdge.empty() && bLineOrBezier)
|
||||||
GetAuxSurf() ;
|
GetAuxSurfRefined() ;
|
||||||
// questa funzione dà per scontato che la superficie NON sia trimmata
|
// questa funzione dà per scontato che la superficie NON sia trimmata
|
||||||
if ( nEdge < 0 || nEdge > 3 || m_bTrimmed)
|
if ( nEdge < 0 || nEdge > 3 || m_bTrimmed)
|
||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|||||||
+31
-13
@@ -25,6 +25,14 @@
|
|||||||
using namespace std ;
|
using namespace std ;
|
||||||
class Tree ;
|
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
|
class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||||
{
|
{
|
||||||
@@ -103,6 +111,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
|||||||
{ return GetControlWeight( GetInd( nIndU, nIndV), pbOk) ; }
|
{ return GetControlWeight( GetInd( nIndU, nIndV), pbOk) ; }
|
||||||
double GetControlWeight( int nInd, bool* pbOk) const override ;
|
double GetControlWeight( int nInd, bool* pbOk) const override ;
|
||||||
bool IsAPoint( void) 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,
|
bool GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
|
||||||
Point3d& ptPos,
|
Point3d& ptPos,
|
||||||
Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr,
|
Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr,
|
||||||
@@ -113,23 +122,24 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
|||||||
Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ;
|
Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ;
|
||||||
CurveComposite* GetCurveOnU( double dV) const override ;
|
CurveComposite* GetCurveOnU( double dV) const override ;
|
||||||
CurveComposite* GetCurveOnV( double dU) 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 GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
|
||||||
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
||||||
const SurfTriMesh* GetAuxSurf( void) 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 ;
|
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.
|
// 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 GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||||
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) 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
|
// 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 = 5) const override ;
|
||||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) 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
|
// 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
|
// 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
|
// 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 ;
|
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 ;
|
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).
|
// 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
|
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
|
||||||
@@ -138,8 +148,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( 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 ;
|
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
|
// 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
|
// 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 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 IsPlanar( void) const override ;
|
||||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||||
@@ -203,16 +213,17 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
|||||||
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
||||||
// restituisce il singolo edge della superficie non trimmata
|
// restituisce il singolo edge della superficie non trimmata
|
||||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||||
bool UpdateEdgesFromTree( Tree& tr) const ;
|
|
||||||
// funzione che calcola se gli edge sono collassati in poli
|
// funzione che calcola se gli edge sono collassati in poli
|
||||||
bool CalcPoles( void) const ;
|
bool CalcPoles( void) const ;
|
||||||
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) 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 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 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 :
|
private :
|
||||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||||
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria
|
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
|
Status m_nStatus ; // stato
|
||||||
int m_nDegU ; // grado in U
|
int m_nDegU ; // grado in U
|
||||||
int m_nDegV ; // grado in V
|
int m_nDegV ; // grado in V
|
||||||
@@ -220,17 +231,24 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
|||||||
int m_nSpanV ; // numero di pezze in V
|
int m_nSpanV ; // numero di pezze in V
|
||||||
bool m_bRat ; // flag di razionale/polinomiale
|
bool m_bRat ; // flag di razionale/polinomiale
|
||||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
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_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 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
|
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
|
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
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 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 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 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)
|
if ( dArea < SQ_EPS_SMALL)
|
||||||
return true ;
|
return true ;
|
||||||
// se sto costruendo il primo chunk
|
// se sto costruendo il primo chunk
|
||||||
if ( m_vExtInd.size() == 0) {
|
if ( m_vExtInd.empty()) {
|
||||||
// assegno il riferimento intrinseco
|
// assegno il riferimento intrinseco
|
||||||
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
|
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
|
||||||
return false ;
|
return false ;
|
||||||
@@ -557,7 +557,7 @@ SurfFlatRegion::Load( NgeReader& ngeIn)
|
|||||||
string sName ;
|
string sName ;
|
||||||
int j ;
|
int j ;
|
||||||
bool bOk = ngeIn.ReadString( sName, ";") &&
|
bool bOk = ngeIn.ReadString( sName, ";") &&
|
||||||
FromString( sName.substr(2), j) && i == j ;
|
FromString( sName.substr( 2), j) && i == j ;
|
||||||
int nChunk = 0, nLoop = 0 ;
|
int nChunk = 0, nLoop = 0 ;
|
||||||
bOk = ngeIn.ReadInt( nChunk, ",") &&
|
bOk = ngeIn.ReadInt( nChunk, ",") &&
|
||||||
ngeIn.ReadInt( nLoop, ";", true) ;
|
ngeIn.ReadInt( nLoop, ";", true) ;
|
||||||
@@ -1210,18 +1210,22 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
|||||||
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
||||||
// calcolo le polilinee che approssimano i loop
|
// calcolo le polilinee che approssimano i loop
|
||||||
POLYLINEVECTOR vPL ;
|
POLYLINEVECTOR vPL ;
|
||||||
vPL.resize( GetLoopCount( i)) ;
|
vPL.reserve( GetLoopCount( i)) ;
|
||||||
int j = 0 ;
|
int j = 0 ;
|
||||||
ICurve* pLoop = GetMyLoop( i, j) ;
|
ICurve* pLoop = GetMyLoop( i, j) ;
|
||||||
while ( pLoop != nullptr) {
|
while ( pLoop != nullptr) {
|
||||||
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
|
// 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 ;
|
return nullptr ;
|
||||||
|
double dLoopArea ;
|
||||||
|
if ( ! vPL.back().GetAreaXY( dLoopArea) || abs( dLoopArea) <= 25 * SQ_EPS_SMALL)
|
||||||
|
vPL.pop_back() ;
|
||||||
pLoop = GetMyLoop( i, ++j) ;
|
pLoop = GetMyLoop( i, ++j) ;
|
||||||
}
|
}
|
||||||
// se chunk abbastanza grande, creo la superficie trimesh relativa
|
// se chunk abbastanza grande, creo la superficie trimesh relativa
|
||||||
double dArea ;
|
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
|
// creo, setto la superficie trimesh ed elimino punti ripetuti
|
||||||
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
|
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
|
||||||
INTMATRIX vnPLIndMat ;
|
INTMATRIX vnPLIndMat ;
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
|||||||
|
|
||||||
// creo una nuova regione a partire da questi loop
|
// creo una nuova regione a partire da questi loop
|
||||||
PtrOwner<SurfFlatRegion> pSfr ;
|
PtrOwner<SurfFlatRegion> pSfr ;
|
||||||
if ( vpLoop.size() == 0)
|
if ( vpLoop.empty())
|
||||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||||
else
|
else
|
||||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||||
@@ -258,7 +258,7 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other)
|
|||||||
|
|
||||||
// creo una nuova regione a partire da questi loop
|
// creo una nuova regione a partire da questi loop
|
||||||
PtrOwner<SurfFlatRegion> pSfr ;
|
PtrOwner<SurfFlatRegion> pSfr ;
|
||||||
if ( vpLoop.size() == 0)
|
if ( vpLoop.empty())
|
||||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||||
else
|
else
|
||||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
|||||||
return nullptr ;
|
return nullptr ;
|
||||||
|
|
||||||
// costruisco la superficie
|
// costruisco la superficie
|
||||||
if ( vOffs.size() > 0) {
|
if ( ! vOffs.empty()) {
|
||||||
PCRV_DEQUE vLoops ;
|
PCRV_DEQUE vLoops ;
|
||||||
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
||||||
vOffs[i]->ToLoc( m_frF) ;
|
vOffs[i]->ToLoc( m_frF) ;
|
||||||
@@ -162,7 +162,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verifico di avere ancora dei loops
|
// verifico di avere ancora dei loops
|
||||||
if ( vLoops.size() > 0) {
|
if ( ! vLoops.empty()) {
|
||||||
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
||||||
if ( IsNull( pSfr)) {
|
if ( IsNull( pSfr)) {
|
||||||
MyTestAndDelete( vLoops) ;
|
MyTestAndDelete( vLoops) ;
|
||||||
|
|||||||
+142
-4
@@ -1154,7 +1154,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
if ( ! IsNull( pSfrTria)) {
|
if ( ! IsNull( pSfrTria)) {
|
||||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||||
pSfrTria->Invert() ;
|
pSfrTria->Invert() ;
|
||||||
pSfrTria->Offset( dTol, ICurve::OFF_CHAMFER) ;
|
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||||
if ( IsNull( pSfr))
|
if ( IsNull( pSfr))
|
||||||
pSfr.Set( pSfrTria) ;
|
pSfr.Set( pSfrTria) ;
|
||||||
else
|
else
|
||||||
@@ -1170,7 +1170,7 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
|||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
// Effettuo contro-offset
|
// Effettuo contro-offset
|
||||||
pSfr->Offset( -dTol, ICurve::OFF_CHAMFER) ;
|
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||||
|
|
||||||
// Recupero i contorni della regione
|
// Recupero i contorni della regione
|
||||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||||
@@ -1225,7 +1225,7 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
|||||||
if ( ! IsNull( pSfrTria)) {
|
if ( ! IsNull( pSfrTria)) {
|
||||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||||
pSfrTria->Invert() ;
|
pSfrTria->Invert() ;
|
||||||
pSfrTria->Offset( dTol, ICurve::OFF_CHAMFER) ;
|
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||||
if ( IsNull( pSfr))
|
if ( IsNull( pSfr))
|
||||||
pSfr.Set( pSfrTria) ;
|
pSfr.Set( pSfrTria) ;
|
||||||
else
|
else
|
||||||
@@ -1242,7 +1242,7 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
|||||||
return true ;
|
return true ;
|
||||||
|
|
||||||
// Effettuo contro-offset
|
// Effettuo contro-offset
|
||||||
pSfr->Offset( -dTol, ICurve::OFF_CHAMFER) ;
|
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||||
|
|
||||||
// Recupero i contorni della regione
|
// Recupero i contorni della regione
|
||||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||||
@@ -2091,6 +2091,17 @@ SurfTriMesh::CreateByFlatContour( const PolyLine& PL)
|
|||||||
return AdjustTopology() ;
|
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
|
bool
|
||||||
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat)
|
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat)
|
||||||
@@ -4063,6 +4074,133 @@ SurfTriMesh::GetPartVolume( int nPart, double& dVolume) const
|
|||||||
return true ;
|
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
|
bool
|
||||||
SurfTriMesh::RemovePart( int nPart)
|
SurfTriMesh::RemovePart( int nPart)
|
||||||
|
|||||||
+5
-3
@@ -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.
|
// Contenuto : Dichiarazione della classe Superficie TriMesh.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -251,7 +251,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
|||||||
bool RemoveTriangle( int nId) override ;
|
bool RemoveTriangle( int nId) override ;
|
||||||
bool AdjustTopology( void) override ;
|
bool AdjustTopology( void) override ;
|
||||||
bool CreateByFlatContour( const PolyLine& PL) 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 CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) override ;
|
||||||
bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ;
|
bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ;
|
||||||
bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;
|
bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;
|
||||||
@@ -340,6 +340,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
|||||||
bool RemovePart( int nPart) override ;
|
bool RemovePart( int nPart) override ;
|
||||||
bool GetPartArea( int nPart, double& dArea) const override ;
|
bool GetPartArea( int nPart, double& dArea) const override ;
|
||||||
bool GetPartVolume( int nPart, double& dVolume) const override ;
|
bool GetPartVolume( int nPart, double& dVolume) const override ;
|
||||||
|
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
|
||||||
SurfTriMesh* ClonePart( int nPart) const override ;
|
SurfTriMesh* ClonePart( int nPart) const override ;
|
||||||
bool SetTFlag( int nId, int nTFlag) override ;
|
bool SetTFlag( int nId, int nTFlag) override ;
|
||||||
bool GetTFlag( int nId, int& nFlag) const override ;
|
bool GetTFlag( int nId, int& nFlag) const override ;
|
||||||
@@ -365,6 +366,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
|||||||
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
|
LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error")
|
||||||
return *this ; }
|
return *this ; }
|
||||||
bool Clear( void) ;
|
bool Clear( void) ;
|
||||||
|
bool CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat) ;
|
||||||
bool ExistsTriangle( int nT) const
|
bool ExistsTriangle( int nT) const
|
||||||
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
|
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
|
||||||
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
|
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
|||||||
|
|
||||||
// Divido il loop di partenza in sotto-loop
|
// Divido il loop di partenza in sotto-loop
|
||||||
int nIterationCount = 0 ;
|
int nIterationCount = 0 ;
|
||||||
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
|
while ( ! cvOpenChain.empty()) { // per ogni catena aperta...
|
||||||
bool bLoopSplitted = false ;
|
bool bLoopSplitted = false ;
|
||||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||||
if ( vnDegVec[nLastOpenLoopN] == 1) {
|
if ( vnDegVec[nLastOpenLoopN] == 1) {
|
||||||
@@ -287,7 +287,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
|||||||
}
|
}
|
||||||
// Recupero i concatenamenti
|
// Recupero i concatenamenti
|
||||||
INTVECTOR vIds ;
|
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 ;
|
CHAINVECTOR vChain ;
|
||||||
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
||||||
Chain chTemp ;
|
Chain chTemp ;
|
||||||
@@ -713,7 +713,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( vInnerLoop.size() == 0 || bDouble) {
|
if ( vInnerLoop.empty() || bDouble) {
|
||||||
// Eseguo triangolazione
|
// Eseguo triangolazione
|
||||||
PNTVECTOR vPt ;
|
PNTVECTOR vPt ;
|
||||||
INTVECTOR vTr ;
|
INTVECTOR vTr ;
|
||||||
|
|||||||
+3
-3
@@ -613,7 +613,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
|||||||
++ it ;
|
++ it ;
|
||||||
}
|
}
|
||||||
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
|
// 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) ;
|
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
@@ -676,7 +676,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loop aperti, devo chiuderli
|
// Loop aperti, devo chiuderli
|
||||||
else if ( cvOpenChain.size() > 0) {
|
else if ( ! cvOpenChain.empty()) {
|
||||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
|
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
|
||||||
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
|
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
|
||||||
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
|
// 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 ;
|
BOOLVECTOR vbInOut ;
|
||||||
vbInOut.push_back( true) ;
|
vbInOut.push_back( true) ;
|
||||||
// Divido il loop di partenza in sotto-loop
|
// Divido il loop di partenza in sotto-loop
|
||||||
while ( cvOpenChain.size() > 0) {
|
while ( ! cvOpenChain.empty()) {
|
||||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||||
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
|
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
|
||||||
// Estremi del loop aperto
|
// Estremi del loop aperto
|
||||||
|
|||||||
@@ -644,7 +644,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
|
|||||||
{
|
{
|
||||||
// recupero i loop della faccia
|
// recupero i loop della faccia
|
||||||
POLYLINEVECTOR vPL ;
|
POLYLINEVECTOR vPL ;
|
||||||
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
|
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// calcolo il centro del loop esterno (è il primo)
|
// calcolo il centro del loop esterno (è il primo)
|
||||||
PolygonPlane PolyPlane ;
|
PolygonPlane PolyPlane ;
|
||||||
@@ -682,7 +682,7 @@ SurfTriMesh::GetFacetArea( int nF, double& dArea) const
|
|||||||
{
|
{
|
||||||
// recupero i loop della faccia
|
// recupero i loop della faccia
|
||||||
POLYLINEVECTOR vPL ;
|
POLYLINEVECTOR vPL ;
|
||||||
if ( ! GetFacetLoops( nF, vPL) || vPL.size() == 0)
|
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// sommo le aree dei diversi loop (quelli interni hanno area negativa)
|
// sommo le aree dei diversi loop (quelli interni hanno area negativa)
|
||||||
dArea = 0 ;
|
dArea = 0 ;
|
||||||
|
|||||||
@@ -539,10 +539,10 @@ bool
|
|||||||
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
|
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
|
||||||
{
|
{
|
||||||
// Se la catena da aggiungere è vuota, non devo fare alcunchè
|
// Se la catena da aggiungere è vuota, non devo fare alcunchè
|
||||||
if ( ChainToAdd.size() == 0)
|
if ( ChainToAdd.empty())
|
||||||
return true ;
|
return true ;
|
||||||
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
||||||
if ( OrigChain.size() == 0)
|
if ( OrigChain.empty())
|
||||||
return false ;
|
return false ;
|
||||||
// Se la catena originale è chiusa non posso aggiungere nulla
|
// Se la catena originale è chiusa non posso aggiungere nulla
|
||||||
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
|
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
|
||||||
|
|||||||
@@ -20,6 +20,15 @@
|
|||||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
struct PairHashInt64 {
|
||||||
|
size_t operator()(const 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 {
|
struct Inters {
|
||||||
@@ -155,7 +164,7 @@ class Cell
|
|||||||
~Cell( void) {}
|
~Cell( void) {}
|
||||||
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_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_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)
|
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) ;
|
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
|
||||||
@@ -163,7 +172,7 @@ class Cell
|
|||||||
}
|
}
|
||||||
Cell( const Point3d& ptBL, const Point3d& ptTR)
|
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_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_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) {}
|
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||||
bool IsSame( const Cell& cOtherCell) const
|
bool IsSame( const Cell& cOtherCell) const
|
||||||
{ return ( m_nId == cOtherCell.m_nId) ; }
|
{ return ( m_nId == cOtherCell.m_nId) ; }
|
||||||
@@ -194,9 +203,11 @@ class Cell
|
|||||||
void SetProcessed( bool bProcessed = true)
|
void SetProcessed( bool bProcessed = true)
|
||||||
{ m_bProcessed = bProcessed ; }
|
{ m_bProcessed = bProcessed ; }
|
||||||
static bool minorX( const Cell& c1, const Cell& c2)
|
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)
|
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 :
|
public :
|
||||||
int m_nId ; // Id della cella
|
int m_nId ; // Id della cella
|
||||||
@@ -209,9 +220,9 @@ class Cell
|
|||||||
double m_dSplit ; // parametro a cui è stata splittata la cella
|
double m_dSplit ; // parametro a cui è stata splittata la cella
|
||||||
int m_nChild1 ; // prima cella figlio
|
int m_nChild1 ; // prima cella figlio
|
||||||
int m_nChild2 ; // seconda 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
|
// 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à
|
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_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)
|
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
|
// 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
|
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
|
// 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 :
|
private :
|
||||||
Point3d m_ptPbl ; // punto bottom left
|
Point3d m_ptPbl ; // punto bottom left
|
||||||
@@ -240,18 +252,14 @@ class Tree
|
|||||||
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
|
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
|
// 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 BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
|
||||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons) ;
|
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops) ;
|
||||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ;
|
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||||
bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ;
|
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
// ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||||
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 = {}) ;
|
|
||||||
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
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 GetEdges3D ( vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
|
||||||
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
|
bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) 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 ; };
|
{ for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i) vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ; 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
|
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
|
||||||
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
|
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
|
||||||
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
|
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
|
||||||
@@ -261,7 +269,6 @@ class Tree
|
|||||||
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
|
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||||
|
|
||||||
private :
|
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, 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
|
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
|
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1
|
||||||
@@ -279,7 +286,7 @@ class Tree
|
|||||||
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
|
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
|
// 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 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
|
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 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.
|
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
|
||||||
@@ -294,21 +301,19 @@ 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 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 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 AdjustCuts( void) ;
|
||||||
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
|
bool UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) ;
|
||||||
bool CloseOpenCuts( void) ;
|
|
||||||
bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ;
|
|
||||||
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 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 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 :
|
private :
|
||||||
const SurfBezier* m_pSrfBz ; // superficie di bezier
|
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
|
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
|
bool m_bTrimmed ; // superficie trimmata
|
||||||
//INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
|
unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
vector<tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||||
//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
|
|
||||||
bool m_bBilinear ; // superficie bilineare
|
bool m_bBilinear ; // superficie bilineare
|
||||||
bool m_bMulti ; // superficie multi-patch
|
bool m_bMulti ; // superficie multi-patch
|
||||||
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
||||||
@@ -319,14 +324,11 @@ class Tree
|
|||||||
int m_nDegV ; // grado della superficie nel parametro V
|
int m_nDegV ; // grado della superficie nel parametro V
|
||||||
int m_nSpanU ; // numero di span lungo il parametro U
|
int m_nSpanU ; // numero di span lungo il parametro U
|
||||||
int m_nSpanV ; // numero di span lungo il parametro V
|
int m_nSpanV ; // numero di span lungo il parametro V
|
||||||
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
|
unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||||
POLYLINEMATRIX m_vPolygonsCorr ; // matrice dei poligoni del tree, corretti per i punti che sono nei poli
|
mutable unordered_map<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)
|
||||||
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
|
|
||||||
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
||||||
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
||||||
bool m_bTestMode ; // bool che indica se la test mode è attiva
|
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.
|
vector<pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||||
} ;
|
} ;
|
||||||
+413
-27
@@ -22,20 +22,27 @@
|
|||||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||||
#include "CurveComposite.h"
|
#include "/EgtDev/Extern/fist/Include/api_fist.h"
|
||||||
#include "IntersCrvCompoCrvCompo.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
|
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 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_EARCUT_HPP = false ;
|
||||||
|
static bool FORCE_FIST = false ;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// In : PolyLine
|
// In : PolyLine
|
||||||
@@ -49,8 +56,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
|||||||
vPt.clear() ;
|
vPt.clear() ;
|
||||||
vTr.clear() ;
|
vTr.clear() ;
|
||||||
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
|
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
|
||||||
if ( PL.GetPointNbr() < 4)
|
if ( PL.GetPointNbr() < 4 || ! PL.IsClosed())
|
||||||
return false ;
|
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
|
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
|
||||||
double dArea ;
|
double dArea ;
|
||||||
Plane3d plPlane ;
|
Plane3d plPlane ;
|
||||||
@@ -117,6 +129,11 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
|||||||
// se una sola polilinea mi riconduco al caso precedente
|
// se una sola polilinea mi riconduco al caso precedente
|
||||||
if ( vPL.size() == 1)
|
if ( vPL.size() == 1)
|
||||||
return Make( vPL[0], vPt, vTr) ;
|
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
|
// verifico che la polilinea esterna sia chiusa e piana e calcolo il piano medio del poligono
|
||||||
double dArea ;
|
double dArea ;
|
||||||
Plane3d plExtPlane ;
|
Plane3d plExtPlane ;
|
||||||
@@ -134,7 +151,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
|||||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea2, 50 * EPS_SMALL) ||
|
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea2, 50 * EPS_SMALL) ||
|
||||||
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
|
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// forzo esecuzione triangolazione con earcut.hpp
|
// forzo esecuzione triangolazione con earcut.hpp
|
||||||
if ( FORCE_EARCUT_HPP) {
|
if ( FORCE_EARCUT_HPP) {
|
||||||
@@ -236,32 +253,30 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
|
|||||||
vPt.clear() ;
|
vPt.clear() ;
|
||||||
vTr.clear() ;
|
vTr.clear() ;
|
||||||
// se non ho PolyLine, allora non faccio nulla
|
// se non ho PolyLine, allora non faccio nulla
|
||||||
if ( int( vPLORIG.size()) == 0)
|
if ( vPLORIG.empty())
|
||||||
return true ;
|
return true ;
|
||||||
|
|
||||||
POLYLINEVECTOR vPL ;
|
POLYLINEVECTOR vPL ;
|
||||||
Vector3d vtN ;
|
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 ;
|
INTMATRIX vnPLIndMat ;
|
||||||
BOOLVECTOR vbInvert ;
|
BOOLVECTOR vbInvert ;
|
||||||
if( vnPLIndMatPre.size() == 0){
|
if ( vnPLIndMatPre.empty()) {
|
||||||
if ( ! CalcRegionPolyLines( vPLORIG, vtN, vnPLIndMat, vbInvert))
|
if ( ! CalcRegionPolyLines( vPLORIG, vtN, vnPLIndMat, vbInvert))
|
||||||
return false ;
|
return false ;
|
||||||
vPL = vPLORIG ;
|
vPL = vPLORIG ;
|
||||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
for ( int i = 0 ; i < int( vbInvert.size()) ; i++) {
|
||||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
if ( vbInvert[i])
|
||||||
if( vbInvert[vnPLIndMat[i][j]])
|
vPL[i].Invert() ;
|
||||||
vPL.back().Invert() ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ho già calcolato e riordinato tutto, devo solo fare una copia delle polyline
|
// 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
|
// non serve fare le eventuali inversioni delle polyline, perché se è già stata calcolata la matrice dei chunck allora sono già state invertire
|
||||||
vPL = vPLORIG ;
|
vPL = vPLORIG ;
|
||||||
vnPLIndMat = vnPLIndMatPre ;
|
vnPLIndMat = vnPLIndMatPre ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
|
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
|
||||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
|
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
|
||||||
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
|
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)
|
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
|
||||||
vTr.push_back( nSize + vTr_tmp[t]) ;
|
vTr.push_back( nSize + vTr_tmp[t]) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +464,7 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
|||||||
vTr.push_back( vPol[i]) ;
|
vTr.push_back( vPol[i]) ;
|
||||||
vTr.push_back( vPol[vNext[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
|
// of neighboring verts past it. Decrement vertex count
|
||||||
vNext[vPrev[i]] = vNext[i] ;
|
vNext[vPrev[i]] = vNext[i] ;
|
||||||
vPrev[vNext[i]] = vPrev[i] ;
|
vPrev[vNext[i]] = vPrev[i] ;
|
||||||
@@ -578,7 +593,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
|
|||||||
// Reset earity of diagonal endpoints
|
// Reset earity of diagonal endpoints
|
||||||
vEar[vPrev[i]] = EAS_NULL ;
|
vEar[vPrev[i]] = EAS_NULL ;
|
||||||
vEar[vNext[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
|
// of neighboring verts past it. Decrement vertex count
|
||||||
vNext[vPrev[i]] = vNext[i] ;
|
vNext[vPrev[i]] = vNext[i] ;
|
||||||
vPrev[vNext[i]] = vPrev[i] ;
|
vPrev[vNext[i]] = vPrev[i] ;
|
||||||
@@ -716,7 +731,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
|
|||||||
// Reset earity of diagonal endpoints
|
// Reset earity of diagonal endpoints
|
||||||
vEar[vPrev[i]] = EAS_NULL ;
|
vEar[vPrev[i]] = EAS_NULL ;
|
||||||
vEar[vNext[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
|
// of neighboring verts past it. Decrement vertex count
|
||||||
vNext[vPrev[i]] = vNext[i] ;
|
vNext[vPrev[i]] = vNext[i] ;
|
||||||
vPrev[vNext[i]] = vPrev[i] ;
|
vPrev[vNext[i]] = vPrev[i] ;
|
||||||
@@ -810,7 +825,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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 ;
|
bIsEar = false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1155,14 +1170,14 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
|||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// non ho trovato alcunch�, errore
|
// non ho trovato alcunchè, errore
|
||||||
if ( nI == - 1)
|
if ( nI == - 1)
|
||||||
return false ;
|
return false ;
|
||||||
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
|
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
|
||||||
if ( AreSamePointApprox( ptInt, vPt[nI]))
|
if ( AreSamePointApprox( ptInt, vPt[nI]))
|
||||||
return true ;
|
return true ;
|
||||||
// devo ora verificare che il segmento che unisce i punti non intersechi altri lati del contorno esterno
|
// 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 ;
|
int nJ = nI ;
|
||||||
Point3d ptPa = ptP ;
|
Point3d ptPa = ptP ;
|
||||||
Point3d ptPb = vPt[nI] ;
|
Point3d ptPb = vPt[nI] ;
|
||||||
@@ -1178,7 +1193,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
|||||||
double dMinTan = INFINITO ;
|
double dMinTan = INFINITO ;
|
||||||
double dMinSqDist = SQ_INFINITO ;
|
double dMinSqDist = SQ_INFINITO ;
|
||||||
for ( int i = 0 ; i < nNumPt ; ++ i) {
|
for ( int i = 0 ; i < nNumPt ; ++ i) {
|
||||||
// salto il punto gi� trovato
|
// salto il punto già trovato
|
||||||
if ( i == nJ)
|
if ( i == nJ)
|
||||||
continue ;
|
continue ;
|
||||||
// verifico se sta nel triangolo
|
// verifico se sta nel triangolo
|
||||||
@@ -1214,7 +1229,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
|||||||
bool
|
bool
|
||||||
Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const Point3d& ptCorn, const Point3d& ptNext)
|
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
|
// se corner convesso
|
||||||
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
|
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
|
||||||
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
|
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
|
||||||
@@ -1229,13 +1244,384 @@ Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const
|
|||||||
bool
|
bool
|
||||||
ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi)
|
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)
|
if ( nNewStart == 0)
|
||||||
return true ;
|
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()))
|
if ( nNewStart >= int( vPi.size()))
|
||||||
return false ;
|
return false ;
|
||||||
// ciclo di aggiustamento
|
// ciclo di aggiustamento
|
||||||
rotate( vPi.begin(), vPi.begin() + nNewStart, vPi.end()) ;
|
rotate( vPi.begin(), vPi.begin() + nNewStart, vPi.end()) ;
|
||||||
return true ;
|
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.
|
||||||
|
|
||||||
|
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) ;
|
||||||
|
|
||||||
|
while ( nTB != -1 && ! vbIsValidTria[nTB]) {
|
||||||
|
// aggiungo alla catena
|
||||||
|
vChain.emplace_back( nTB) ;
|
||||||
|
|
||||||
|
// calcolo il successivo
|
||||||
|
nTA = nTB ;
|
||||||
|
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
|
||||||
|
vChainEdges.emplace_back( nEA) ;
|
||||||
|
|
||||||
|
// verifico di non aver trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||||
|
// e quindi di non essere entrato in un loop
|
||||||
|
if ( nTB == vChain[vChain.size()-2]) {
|
||||||
|
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||||
|
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
|
||||||
|
// aggiorno per iterazione successiva
|
||||||
|
if ( vChain.size() == 2) {
|
||||||
|
vChain.pop_back() ;
|
||||||
|
vChainEdges.pop_back() ;
|
||||||
|
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ;
|
||||||
|
vChainEdges[0] = nEA ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// elimino gli ultimi due triangoli che sono appena stati flippati e ricalcolo adiacenza del triangolo
|
||||||
|
// precedente
|
||||||
|
vChain.pop_back() ;
|
||||||
|
vChain.pop_back() ;
|
||||||
|
vChainEdges.pop_back() ;
|
||||||
|
vChainEdges.pop_back() ;
|
||||||
|
int nTTest1 = nTA ;
|
||||||
|
int nTTest2 = nTB ;
|
||||||
|
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTTest1, nTTest2, nTB, nEB) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
|
||||||
|
if ( nTB == -1) {
|
||||||
|
bRemovedTrg = true ;
|
||||||
|
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||||
|
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(), nTB, vChainEdges.back(), nEB) ;
|
||||||
|
vbIsValidTria[vChain.back()] = true ;
|
||||||
|
int nTrgTest1 = vChain.back() ;
|
||||||
|
int nTrgTest2 = nTB ;
|
||||||
|
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) {
|
||||||
|
// triangolo corrente
|
||||||
|
int nTA = vChain[i] ;
|
||||||
|
int nEA = vChainEdges[i] ;
|
||||||
|
// 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 ;
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -497,7 +497,7 @@ VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
|||||||
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
|
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
|
||||||
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
||||||
int nPos = ic + jc * m_nNx[0] ;
|
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() ;
|
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][0].dMin * m_MapFrame.VersZ()) ;
|
||||||
b3Loc.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * 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) {
|
for ( int i = 0 ; i <= m_nNx[0] ; ++ i) {
|
||||||
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
int ic = ( ( i != m_nNx[0]) ? i : m_nNx[0] - 1) ;
|
||||||
int nPos = ic + jc * m_nNx[0] ;
|
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() ;
|
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][0].dMin * frUse.VersZ()) ;
|
||||||
b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ;
|
b3Ref.Add( ptP + m_Values[0][nPos][m_Values[0][nPos].size()-1].dMax * frUse.VersZ()) ;
|
||||||
|
|||||||
+4
-4
@@ -4013,7 +4013,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
|
|||||||
bool bNotEmpty = false ;
|
bool bNotEmpty = false ;
|
||||||
for ( nj = 0 ; nj < 2 ; ++ nj) {
|
for ( nj = 0 ; nj < 2 ; ++ nj) {
|
||||||
int nDex = nj * int( m_nNx[0]) + ni ;
|
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 ;
|
bNotEmpty = true ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
@@ -4026,7 +4026,7 @@ VolZmap::GetFirstVoxIJK( int& i, int& j, int& k) const
|
|||||||
bool bNotEmpty = false ;
|
bool bNotEmpty = false ;
|
||||||
for ( mj = 0 ; mj < 2 ; ++ mj) {
|
for ( mj = 0 ; mj < 2 ; ++ mj) {
|
||||||
int nDex = mj * int( m_nNx[1]) + mi ;
|
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 ;
|
bNotEmpty = true ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
@@ -4056,7 +4056,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
|
|||||||
bool bNotEmpty = false ;
|
bool bNotEmpty = false ;
|
||||||
for ( nj = int( m_nNy[0]) - 1 ; nj > int( m_nNy[0]) - 3 ; -- nj) {
|
for ( nj = int( m_nNy[0]) - 1 ; nj > int( m_nNy[0]) - 3 ; -- nj) {
|
||||||
int nDex = nj * int( m_nNx[0]) + ni ;
|
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 ;
|
bNotEmpty = true ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
@@ -4069,7 +4069,7 @@ VolZmap::GetLastVoxIJK( int& i, int& j, int& k) const
|
|||||||
bool bNotEmpty = false ;
|
bool bNotEmpty = false ;
|
||||||
for ( mj = int( m_nNy[1]) - 1 ; mj > int( m_nNy[1]) - 3 ; -- mj) {
|
for ( mj = int( m_nNy[1]) - 1 ; mj > int( m_nNy[1]) - 3 ; -- mj) {
|
||||||
int nDex = mj * int( m_nNx[1]) + mi ;
|
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 ;
|
bNotEmpty = true ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-3
@@ -55,13 +55,13 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco)
|
// Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco)
|
||||||
if ( !bSkipSwap && nGrid == 1) {
|
if ( ! bSkipSwap && nGrid == 1) {
|
||||||
swap( vtNmi.x, vtNmi.z) ;
|
swap( vtNmi.x, vtNmi.z) ;
|
||||||
swap( vtNmi.y, vtNmi.z) ;
|
swap( vtNmi.y, vtNmi.z) ;
|
||||||
swap( vtNma.x, vtNma.z) ;
|
swap( vtNma.x, vtNma.z) ;
|
||||||
swap( vtNma.y, vtNma.z) ;
|
swap( vtNma.y, vtNma.z) ;
|
||||||
}
|
}
|
||||||
else if ( !bSkipSwap && nGrid == 2) {
|
else if ( ! bSkipSwap && nGrid == 2) {
|
||||||
swap( vtNmi.y, vtNmi.z) ;
|
swap( vtNmi.y, vtNmi.z) ;
|
||||||
swap( vtNmi.x, vtNmi.z) ;
|
swap( vtNmi.x, vtNmi.z) ;
|
||||||
swap( vtNma.y, vtNma.z) ;
|
swap( vtNma.y, vtNma.z) ;
|
||||||
@@ -4544,11 +4544,44 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|||||||
double dLongLen = vtMoveLong.Len() ;
|
double dLongLen = vtMoveLong.Len() ;
|
||||||
double dOrtLen = vtMoveOrt.Len() ;
|
double dOrtLen = vtMoveOrt.Len() ;
|
||||||
|
|
||||||
|
// Parametri di contenimento
|
||||||
|
Vector3d vtPerp = vtToolDir ^ Z_AX ;
|
||||||
|
bool bPerpOk = vtPerp.Normalize() ;
|
||||||
|
if ( vtPerp * vtMove < 0)
|
||||||
|
vtPerp.Invert() ;
|
||||||
|
int nSkip = 0 ;
|
||||||
|
|
||||||
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
||||||
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
||||||
|
|
||||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||||
|
|
||||||
|
// salto il controllo degli spilloni sotto il piano limite in basso o sopra il piano limite in alto
|
||||||
|
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL &&
|
||||||
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptITip) * vtToolDir < -EPS_SMALL) {
|
||||||
|
++ nSkip ;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
if ( ( ptC + Z_AX * m_dMinZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL &&
|
||||||
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI - vtMoveLong) * vtToolDir > EPS_SMALL) {
|
||||||
|
++ nSkip ;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// salto il controllo degli spilloni prima del piano di fianco verticale di inizio o dopo il piano di fianco verticale di fine
|
||||||
|
if ( bPerpOk &&
|
||||||
|
( ptC + Z_AX * m_dMinZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL &&
|
||||||
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptI + vtPerp * dRad) * vtPerp < -EPS_SMALL) {
|
||||||
|
++ nSkip ;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
if ( bPerpOk &&
|
||||||
|
( ptC + Z_AX * m_dMinZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL &&
|
||||||
|
( ptC + Z_AX * m_dMaxZ[nGrid] - ptF - vtPerp * dRad) * vtPerp > EPS_SMALL) {
|
||||||
|
++ nSkip ;
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
|
||||||
Point3d ptInt1, ptInt2 ;
|
Point3d ptInt1, ptInt2 ;
|
||||||
Vector3d vtN1, vtN2 ;
|
Vector3d vtN1, vtN2 ;
|
||||||
|
|
||||||
@@ -4592,6 +4625,10 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//string sLog = "Skipped dexel = " + ToString( nSkip) + " / " + ToString( ( nEndI - nStartI + 1) * ( nEndJ - nStartJ + 1)) ;
|
||||||
|
//LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+277
-46
@@ -20,6 +20,7 @@
|
|||||||
#include "RemoveCurveDefects.h"
|
#include "RemoveCurveDefects.h"
|
||||||
#include "Voronoi.h"
|
#include "Voronoi.h"
|
||||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||||
|
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||||
|
|
||||||
using namespace std ;
|
using namespace std ;
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
|||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_vpCrvs.size() == 0) {
|
if ( m_vpCrvs.empty()) {
|
||||||
// se prima curva considerata assegno il frame al Voronoi
|
// se prima curva considerata assegno il frame al Voronoi
|
||||||
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
||||||
}
|
}
|
||||||
@@ -160,7 +161,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
|||||||
// recupero il piano
|
// recupero il piano
|
||||||
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
|
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
|
||||||
Vector3d vtN = pSfr->GetNormVersor() ;
|
Vector3d vtN = pSfr->GetNormVersor() ;
|
||||||
if ( m_vpCrvs.size() == 0) {
|
if ( m_vpCrvs.empty()) {
|
||||||
// assegno il frame al Voronoi
|
// assegno il frame al Voronoi
|
||||||
m_Frame.Set( ptCen, vtN) ;
|
m_Frame.Set( ptCen, vtN) ;
|
||||||
}
|
}
|
||||||
@@ -442,6 +443,9 @@ Voronoi::GetBisectorCurve( int i)
|
|||||||
Point3d ptS, ptE, ptC ;
|
Point3d ptS, ptE, ptC ;
|
||||||
double dParS, dParE ;
|
double dParS, dParE ;
|
||||||
m_vroni->GetDegenerateHyperEllipticBisectorData( i, ptS.v, ptE.v, ptC.v, dParS, dParE) ;
|
m_vroni->GetDegenerateHyperEllipticBisectorData( i, ptS.v, ptE.v, ptC.v, dParS, dParE) ;
|
||||||
|
// se estremi coincidenti ignoro ( da vroni non possono arrivare circonferenze)
|
||||||
|
if ( AreSamePointApprox( ptS, ptE))
|
||||||
|
return nullptr ;
|
||||||
// creo arco
|
// creo arco
|
||||||
CurveArc* pArc = CreateBasicCurveArc() ;
|
CurveArc* pArc = CreateBasicCurveArc() ;
|
||||||
if ( pArc == nullptr)
|
if ( pArc == nullptr)
|
||||||
@@ -570,7 +574,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
|||||||
if ( m_vroni->IsWMATEdge( i)) {
|
if ( m_vroni->IsWMATEdge( i)) {
|
||||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||||
vCrvs.emplace_back( Release( pCrv)) ;
|
vCrvs.emplace_back( Release( pCrv)) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +594,7 @@ bool
|
|||||||
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||||
{
|
{
|
||||||
vOffs.clear() ;
|
vOffs.clear() ;
|
||||||
|
|
||||||
if ( ! IsValid())
|
if ( ! IsValid())
|
||||||
return false ;
|
return false ;
|
||||||
|
|
||||||
@@ -610,23 +614,23 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
|||||||
|
|
||||||
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
|
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
|
||||||
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
|
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
|
||||||
|
|
||||||
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
|
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
|
||||||
|
|
||||||
// eventuale inversione
|
// eventuale inversione
|
||||||
if ( dOffs > EPS_SMALL)
|
if ( dOffs > EPS_SMALL)
|
||||||
vResult[i]->Invert() ;
|
vResult[i]->Invert() ;
|
||||||
|
|
||||||
// sistemo il punto di inizio
|
// sistemo il punto di inizio
|
||||||
if ( vResult[i]->IsClosed())
|
if ( vResult[i]->IsClosed())
|
||||||
AdjustOffsetStart( vResult[i]) ;
|
AdjustOffsetStart( vResult[i]) ;
|
||||||
|
|
||||||
// sistemo i raccordi
|
// sistemo i raccordi
|
||||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||||
IdentifyFillets( vResult[i], dOffs) ;
|
IdentifyFillets( vResult[i], dOffs) ;
|
||||||
AdjustCurveFillets( vResult[i], dOffs, nType) ;
|
AdjustCurveFillets( vResult[i], dOffs, nType) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// porto nel frame globale
|
// porto nel frame globale
|
||||||
vResult[i]->ToGlob( m_Frame) ;
|
vResult[i]->ToGlob( m_Frame) ;
|
||||||
// unisco le parti allineate
|
// unisco le parti allineate
|
||||||
@@ -641,6 +645,199 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||||
|
{
|
||||||
|
// calcola, se possibile, le curve di offset del valore richiesto come curve singole, andando a recuperare i tratti del
|
||||||
|
// medial axis corrispondenti. L'offset invece restituirebbe curve chiuse formate da tratti praticamente sovrapposti.
|
||||||
|
|
||||||
|
vOffs.clear() ;
|
||||||
|
|
||||||
|
if ( abs( dOffs) < EPS_SMALL)
|
||||||
|
return true ;
|
||||||
|
|
||||||
|
if ( ! IsValid())
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ( ! m_bVDComputed)
|
||||||
|
CalcVoronoi() ;
|
||||||
|
|
||||||
|
// individuo il lato richiesto
|
||||||
|
bool bLeft = ( dOffs < 0) ;
|
||||||
|
bool bRight = ! bLeft ;
|
||||||
|
for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) {
|
||||||
|
if ( ! m_vpCrvs[i]->IsClosed()) {
|
||||||
|
// se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra
|
||||||
|
bLeft = true ;
|
||||||
|
bRight = true ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
|
||||||
|
|
||||||
|
// seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto
|
||||||
|
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||||
|
ICURVEPOVECTOR vCrvs ;
|
||||||
|
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||||
|
// verifico se bisettore di medial axis
|
||||||
|
if ( m_vroni->IsWMATEdge( i)) {
|
||||||
|
// verifico i parametri
|
||||||
|
double dParS, dParE ;
|
||||||
|
m_vroni->GetBisectorParams( i, dParS, dParE) ;
|
||||||
|
if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) {
|
||||||
|
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||||
|
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
|
||||||
|
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
|
||||||
|
if ( bLeft && bRight) {
|
||||||
|
// recupero i siti di riferimento
|
||||||
|
int nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2 ;
|
||||||
|
m_vroni->GetBisectorSites( i, nOrigCrv1, nOrigSubCrv1, nOrigCrv2, nOrigSubCrv2) ;
|
||||||
|
if ( nOrigCrv1 != -1) {
|
||||||
|
// verifico il lato rispetto al primo sito
|
||||||
|
pCrv->SetTempProp( nOrigSubCrv1 + 1, 0) ;
|
||||||
|
pCrv->SetTempProp( nOrigCrv1, 1) ;
|
||||||
|
int nSide = GetOffsetCurveSide( pCrv) ;
|
||||||
|
if ( nSide != nSideRef)
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
if ( nOrigCrv2 != -1) {
|
||||||
|
// verifico il lato rispetto al secondo sito
|
||||||
|
pCrv->SetTempProp( nOrigSubCrv2 + 1, 0) ;
|
||||||
|
pCrv->SetTempProp( nOrigCrv2, 1) ;
|
||||||
|
int nSide = GetOffsetCurveSide( pCrv) ;
|
||||||
|
if ( nSide != nSideRef)
|
||||||
|
continue ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vCrvs.emplace_back( Release( pCrv)) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// concateno le curve ottenute
|
||||||
|
if ( vCrvs.size() == 1)
|
||||||
|
vOffs.emplace_back( Release( vCrvs[0])) ;
|
||||||
|
else if ( ! vCrvs.empty()) {
|
||||||
|
ChainCurves chainC ;
|
||||||
|
chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ;
|
||||||
|
for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) {
|
||||||
|
Point3d ptS, ptE ;
|
||||||
|
Vector3d vtS, vtE ;
|
||||||
|
if ( ! vCrvs[i]->GetStartPoint( ptS) || ! vCrvs[i]->GetStartDir( vtS) ||
|
||||||
|
! vCrvs[i]->GetEndPoint( ptE) || ! vCrvs[i]->GetEndDir( vtE))
|
||||||
|
return false ;
|
||||||
|
if ( ! chainC.AddCurve( i + 1, ptS, vtS, ptE, vtE))
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTVECTOR vIds ;
|
||||||
|
while ( chainC.GetChainFromNear( ORIG, false, vIds)) {
|
||||||
|
// creo una curva composita
|
||||||
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||||
|
if ( IsNull( pCrvCompo))
|
||||||
|
return false ;
|
||||||
|
for ( int i = 0 ; i < int( vIds.size()) ; ++ i) {
|
||||||
|
// recupero l'indice della curva
|
||||||
|
int nInd = abs( vIds[i]) - 1 ;
|
||||||
|
// verifico se necessaria inversione
|
||||||
|
if ( vIds[i] < 0)
|
||||||
|
vCrvs[nInd]->Invert() ;
|
||||||
|
// aggiungo alla composita
|
||||||
|
if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd])))
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if ( pCrvCompo->IsValid()) {
|
||||||
|
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||||
|
vOffs.emplace_back( Release( pCrvCompo)) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||||
|
m_vroni->apiFreeBisectorBuffer() ;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||||
|
{
|
||||||
|
// calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto
|
||||||
|
|
||||||
|
vResult.clear() ;
|
||||||
|
|
||||||
|
if ( abs( dOffs) < EPS_SMALL)
|
||||||
|
return true ;
|
||||||
|
|
||||||
|
if ( ! IsValid())
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// verifico se necessario ricalcolo Voronoi
|
||||||
|
UpdateVoronoi( dOffs) ;
|
||||||
|
|
||||||
|
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
|
||||||
|
// la chiusura solo sulla prima curva. Eventualmente da estendere)
|
||||||
|
bool bLeft = true, bRight = true ;
|
||||||
|
if ( m_vpCrvs[0]->IsClosed()) {
|
||||||
|
bLeft = dOffs < 0 ;
|
||||||
|
bRight = ! bLeft ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcolo medial axis
|
||||||
|
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||||
|
|
||||||
|
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||||
|
// verifico se il lato appartiene al medial axis
|
||||||
|
if ( m_vroni->IsWMATEdge( i)) {
|
||||||
|
// verifico se coinvolto dall'offset
|
||||||
|
double dParS, dParE ;
|
||||||
|
m_vroni->GetBisectorParams( i, dParS, dParE) ;
|
||||||
|
if ( dParS > dParE)
|
||||||
|
swap( dParS, dParE) ;
|
||||||
|
if ( abs( dOffs) < dParS || abs( dOffs) > dParE)
|
||||||
|
continue ;
|
||||||
|
|
||||||
|
// calcolo il punto sul bisettore in corrispondenza dell'offset
|
||||||
|
Point3d pt ;
|
||||||
|
m_vroni->GetBisectorPointAtParam( i, abs( dOffs), pt.v) ;
|
||||||
|
pt.ToGlob( m_Frame) ;
|
||||||
|
|
||||||
|
// calcolo il vettore tangente
|
||||||
|
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||||
|
if ( IsNull( pCrv))
|
||||||
|
return false ;
|
||||||
|
double dPar ;
|
||||||
|
Point3d ptTemp ;
|
||||||
|
Vector3d vtDir ;
|
||||||
|
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||||
|
return false ;
|
||||||
|
vtDir.Normalize() ;
|
||||||
|
|
||||||
|
vResult.emplace_back( pt, vtDir) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// libero la memoria di vroni utilizzata per calcolare bisettori
|
||||||
|
m_vroni->apiFreeBisectorBuffer() ;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool
|
bool
|
||||||
Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids)
|
Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids)
|
||||||
@@ -719,8 +916,9 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
|||||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
|
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
|
||||||
|
|
||||||
// recupero le curve di offset da vroni
|
// recupero le curve di offset da vroni
|
||||||
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||||
for ( int i = 0 ; i < nOffsCnt ; i++) {
|
for ( int i = 0 ; i < nOffsCnt ; i++) {
|
||||||
|
Point3d ptSChain = P_INVALID ;
|
||||||
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
|
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
|
||||||
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
|
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
|
||||||
|
|
||||||
@@ -732,45 +930,75 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
|||||||
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
|
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
|
||||||
|
|
||||||
if ( j == 0)
|
if ( j == 0)
|
||||||
pCrvOffs->AddPoint( ptS) ;
|
pCrvOffs->AddPoint( ptS) ;
|
||||||
|
|
||||||
bool bOk = false ;
|
// se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze)
|
||||||
if ( nType == t_site::SEG)
|
// ma controllo se appartiene ad una catena di tratti infinitesimi
|
||||||
bOk = pCrvOffs->AddLine( ptE) ;
|
if ( AreSamePointApprox( ptS, ptE)) {
|
||||||
else {
|
if ( ptSChain.IsValid()) {
|
||||||
// se estremi coincidenti passo alla curva successiva ( da vroni non possono arrivare circonferenze)
|
if ( ! AreSamePointApprox( ptSChain, ptE)) {
|
||||||
if ( AreSamePointApprox( ptS, ptE))
|
if ( ! pCrvOffs->AddLine( ptE))
|
||||||
continue ;
|
return false ;
|
||||||
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
|
ptSChain = P_INVALID ;
|
||||||
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
|
|
||||||
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// se la curva è stata aggiunta
|
|
||||||
if ( bOk) {
|
|
||||||
// setto come info la sottocurva da cui si è generata
|
|
||||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
|
||||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
|
||||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
|
||||||
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
|
|
||||||
// aperta e chiusa)
|
|
||||||
if ( nOrigCrv == -1) {
|
|
||||||
int nOrigCrvCnt = 1 ;
|
|
||||||
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
|
|
||||||
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
|
|
||||||
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
|
|
||||||
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
|
|
||||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// assegno come inizio di possibile catena
|
||||||
|
ptSChain = ptS ;
|
||||||
|
}
|
||||||
|
continue ;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ptSChain = P_INVALID ;
|
||||||
|
|
||||||
|
if ( nType == t_site::SEG) {
|
||||||
|
if ( ! pCrvOffs->AddLine( ptE))
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
|
||||||
|
if ( ! pArc->SetC2P( ptC, ptS, ptE)) {
|
||||||
|
// se raggio minore di EPS_SMALL approssimo con linea
|
||||||
|
if ( AreSamePointApprox( ptC, ptS)) {
|
||||||
|
if ( ! pCrvOffs->AddLine( ptE))
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// verifico orientamento
|
||||||
|
double dAng = pArc->GetAngCenter() ;
|
||||||
|
if ( ( nType == CCW && dAng < - EPS_ANG_SMALL) || ( nType == CW && dAng > EPS_ANG_SMALL))
|
||||||
|
pArc->ToExplementary() ;
|
||||||
|
// aggiungo alla composita
|
||||||
|
if ( ! pCrvOffs->AddCurve( Release( pArc)))
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setto come info la sottocurva da cui si è generata
|
||||||
|
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||||
|
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||||
|
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||||
|
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
|
||||||
|
// aperta e chiusa)
|
||||||
|
if ( nOrigCrv == -1) {
|
||||||
|
int nOrigCrvCnt = 1 ;
|
||||||
|
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
|
||||||
|
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
|
||||||
|
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
|
||||||
|
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
|
||||||
|
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
|
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
|
||||||
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
||||||
|
|
||||||
// aggiungo la curva alla lista degli offset
|
// aggiungo la curva alla lista degli offset
|
||||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
|
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
|
||||||
OffsList.push_back( Release( pCrvOffs)) ;
|
OffsList.push_back( Release( pCrvOffs)) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,7 +1048,7 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
|||||||
|
|
||||||
if ( ! bJunctions) {
|
if ( ! bJunctions) {
|
||||||
// controllo la curva complessiva
|
// controllo la curva complessiva
|
||||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ;
|
||||||
if ( nSide == nSideRef)
|
if ( nSide == nSideRef)
|
||||||
vResult.emplace_back( pCompo->Clone()) ;
|
vResult.emplace_back( pCompo->Clone()) ;
|
||||||
}
|
}
|
||||||
@@ -833,7 +1061,7 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
|||||||
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
|
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
|
||||||
bKeep = false ;
|
bKeep = false ;
|
||||||
else {
|
else {
|
||||||
int nSide = GetOffsetCurveSide( pCompo, i) ;
|
int nSide = GetOffsetCurveSide( pCompo->GetCurve( i)) ;
|
||||||
bKeep = ( nSide == nSideRef) ;
|
bKeep = ( nSide == nSideRef) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,13 +1093,16 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
int
|
int
|
||||||
Voronoi::GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const
|
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
|
||||||
{
|
{
|
||||||
Point3d ptM ; pOffs->GetCurve( nCrv)->GetMidPoint( ptM) ;
|
if ( pCrv == nullptr)
|
||||||
|
return -1 ;
|
||||||
|
|
||||||
|
Point3d ptM ; pCrv->GetMidPoint( ptM) ;
|
||||||
|
|
||||||
// recupero curva e sottocurva di riferimento
|
// recupero curva e sottocurva di riferimento dalle temp prop
|
||||||
int nOrigSubCrv ; pOffs->GetCurveTempProp( nCrv, nOrigSubCrv) ;
|
int nOrigSubCrv = pCrv->GetTempProp( 0) ;
|
||||||
int nOrigCrv ; pOffs->GetCurveTempProp( nCrv, nOrigCrv, 1) ;
|
int nOrigCrv = pCrv->GetTempProp( 1) ;
|
||||||
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
|
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
|
||||||
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
|
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
|
||||||
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
|
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ class Voronoi
|
|||||||
bool GetVroniPlane( Plane3d& plPlane) const ;
|
bool GetVroniPlane( Plane3d& plPlane) const ;
|
||||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) ;
|
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) ;
|
||||||
bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ;
|
bool CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) ;
|
||||||
|
bool CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs) ;
|
||||||
|
bool CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) ;
|
||||||
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
|
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
|
||||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
||||||
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
|
bool CalcLimitOffset( int nCrv, bool bLeft, double& dOffs) ;
|
||||||
@@ -81,7 +83,7 @@ class Voronoi
|
|||||||
bool UpdateVoronoi( double dOffs) ;
|
bool UpdateVoronoi( double dOffs) ;
|
||||||
ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ;
|
ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ;
|
||||||
bool AdjustOffsetStart( ICurveComposite* pCompo) const ;
|
bool AdjustOffsetStart( ICurveComposite* pCompo) const ;
|
||||||
int GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const ;
|
int GetOffsetCurveSide( const ICurve* pCrv) const ;
|
||||||
ICurve* GetBisectorCurve( int i) ;
|
ICurve* GetBisectorCurve( int i) ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib")
|
#pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib")
|
||||||
#pragma comment(lib, EGTEXTDIR "vroni/Lib/vroni" 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 "EgtGeneral" EGTLIBVER ".lib")
|
||||||
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
|
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
|
||||||
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")
|
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")
|
||||||
|
|||||||
Reference in New Issue
Block a user