EgtGeomKernel :
- risolti vari bug - ridotto il calcolo del tree alle bbox delle curve di trim
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "DistPointCrvComposite.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Cell::Cell( void)
|
||||
@@ -77,10 +78,10 @@ Tree::Tree( void)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches)
|
||||
: m_bBilinear( false), m_bMulti( false), m_bClosed( false), m_bSplitPatches( bSplitPatches)
|
||||
Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d ptMin, const Point3d ptMax)
|
||||
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false), m_bSplitPatches( true)
|
||||
{
|
||||
SetSurf( pSrfBz, m_bSplitPatches) ;
|
||||
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -90,8 +91,20 @@ Tree::~Tree( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches)
|
||||
Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d ptMin, const Point3d ptMax)
|
||||
{
|
||||
// pulisco i vettori membri
|
||||
m_vnLeaves.clear() ;
|
||||
m_vnParents.clear() ;
|
||||
m_mVert.clear() ;
|
||||
m_vLoop.clear() ;
|
||||
m_mChunk.clear() ;
|
||||
m_vPlApprox.clear() ;
|
||||
m_vChunk.clear() ;
|
||||
m_vPolygons.clear() ;
|
||||
|
||||
|
||||
|
||||
m_pSrfBz = pSrfBz ;
|
||||
m_bSplitPatches = bSplitPatches ;
|
||||
// le coordinate delle celle sono nello spazio parametrico
|
||||
@@ -113,9 +126,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches)
|
||||
INTVECTOR vChunk ;
|
||||
|
||||
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
|
||||
Frame3d frSurf ;
|
||||
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
|
||||
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico perché le curve di loop sono già state riscalate!!!!!!
|
||||
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
|
||||
double dAngTolDeg = 5 ;
|
||||
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
|
||||
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
|
||||
@@ -157,125 +169,225 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches)
|
||||
return dArea1 > dArea2 ;}) ;
|
||||
}
|
||||
// salvo i vertici 3d della cella root
|
||||
Point3d ptBottom ( 0, 0) ;
|
||||
Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ;
|
||||
Cell cRoot( ptBottom, ptTop) ;
|
||||
bool bLimited = false ;
|
||||
if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) {
|
||||
ptTop = ptMax ;
|
||||
bLimited = true ;
|
||||
}
|
||||
m_mTree.clear() ;
|
||||
Cell cRoot( ptMin, ptTop) ;
|
||||
m_mTree.insert( std::pair< int, Cell>( -1, cRoot)) ;
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
bool bOk = false ;
|
||||
if ( ! bLimited) {
|
||||
ptP00 = m_pSrfBz->GetControlPoint( 0, &bOk) ;
|
||||
ptP10 = m_pSrfBz->GetControlPoint( nDegU * nSpanU, &bOk) ;
|
||||
ptP11 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV + 1) - 1, &bOk) ;
|
||||
ptP01 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
|
||||
}
|
||||
else {
|
||||
m_pSrfBz->GetPointD1D2( ptMin.x / SBZ_TREG_COEFF, ptMin.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
|
||||
m_pSrfBz->GetPointD1D2( ptMax.x / SBZ_TREG_COEFF, ptMin.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
|
||||
m_pSrfBz->GetPointD1D2( ptMax.x / SBZ_TREG_COEFF, ptMax.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
|
||||
m_pSrfBz->GetPointD1D2( ptMin.x / SBZ_TREG_COEFF, ptMax.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
|
||||
}
|
||||
PNTVECTOR vVert ;
|
||||
ptP00 = m_pSrfBz->GetControlPoint( 0, &bOk) ;
|
||||
vVert.push_back( ptP00) ;
|
||||
ptP10 = m_pSrfBz->GetControlPoint( nDegU * nSpanU, &bOk) ;
|
||||
vVert.push_back( ptP10) ;
|
||||
ptP11 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV + 1) - 1, &bOk) ;
|
||||
vVert.push_back( ptP11) ;
|
||||
ptP01 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
|
||||
vVert.push_back( ptP01) ;
|
||||
m_mVert.insert( std::pair<int, PNTVECTOR>( -1, vVert)) ;
|
||||
// se richiesto divido preliminarmente le patches
|
||||
m_vnParents.clear() ;
|
||||
if ( bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
|
||||
int nId = -1 ;
|
||||
for ( int i = 1 ; i < nSpanU ; ++i) {
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
Split( nId, i * SBZ_TREG_COEFF) ;
|
||||
++ nId ;
|
||||
++ nId ;
|
||||
if ( i * SBZ_TREG_COEFF > ptMin.x && i * SBZ_TREG_COEFF < ptTop.x){
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
Split( nId, i * SBZ_TREG_COEFF) ;
|
||||
++ nId ;
|
||||
++ nId ;
|
||||
}
|
||||
}
|
||||
INTVECTOR vLeaves ;
|
||||
GetHeightLeaves( -1, vLeaves) ;
|
||||
for ( int nId : vLeaves) {
|
||||
for ( int j = nSpanV - 1 ; j > 0 ; --j) {
|
||||
m_mTree[nId].SetSplitDirVert( false) ;
|
||||
Split( nId, j * SBZ_TREG_COEFF) ;
|
||||
nId = m_mTree[nId].m_nChild2 ;
|
||||
if ( j * SBZ_TREG_COEFF > ptMin.y && j * SBZ_TREG_COEFF < ptTop.y){
|
||||
m_mTree[nId].SetSplitDirVert( false) ;
|
||||
Split( nId, j * SBZ_TREG_COEFF) ;
|
||||
nId = m_mTree[nId].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
vLeaves.clear() ;
|
||||
GetHeightLeaves( -1, vLeaves) ;
|
||||
m_vnParents = vLeaves ;
|
||||
}
|
||||
// se non ho già splittato le patches, controllo se la superficie è chiusa. In tal caso la splitto sul parametro su cui è chiusa
|
||||
else {
|
||||
// verifico se la superficie è chiusa ed eventualmente sistemo le adiacenze
|
||||
if ( ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) ||
|
||||
( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11))) {
|
||||
m_bClosed = true ;
|
||||
if ( AreSamePointApprox( ptP00, ptP01)) {
|
||||
m_mTree[-1].m_nTop = -1 ;
|
||||
m_mTree[-1].m_nBottom = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( false) ;
|
||||
// controllo se la superficie è chiusa. In tal caso la splitto sul parametro su cui è chiusa
|
||||
// verifico se la superficie è chiusa ed eventualmente sistemo le adiacenze
|
||||
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) ||
|
||||
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
|
||||
m_bClosed = true ;
|
||||
if ( AreSamePointApprox( ptP00, ptP01)) {
|
||||
m_mTree[-1].m_nTop = -1 ;
|
||||
m_mTree[-1].m_nBottom = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( false) ;
|
||||
Split( -1) ;
|
||||
// qui devo fare il controllo capped
|
||||
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
bool bOk = false ;
|
||||
bool bCapped0 = true, bCapped1 = true ;
|
||||
Point3d ptV0, ptV1 ;
|
||||
// controllo se tutti i punti sull'isoparametrica sono uguali
|
||||
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
|
||||
ptV0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptV0) ;
|
||||
ptV1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP10, ptV1) ;
|
||||
}
|
||||
if ( bCapped0 && bCapped1) {
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
if ( AreSamePointApprox( ptP00, ptP10)) {
|
||||
if( (int) m_mTree.size() == 1) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
// qui devo fare il controllo capped
|
||||
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
bool bOk = false ;
|
||||
bool bCapped0 = true, bCapped1 = true ;
|
||||
Point3d ptV0, ptV1 ;
|
||||
Point3d ptU0, ptU1 ;
|
||||
// controllo se tutti i punti sull'isoparametrica sono uguali
|
||||
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
|
||||
ptV0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptV0) ;
|
||||
ptV1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP10, ptV1) ;
|
||||
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
|
||||
ptU0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptU0) ;
|
||||
ptU1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP01, ptU1) ;
|
||||
}
|
||||
if ( bCapped0 && bCapped1) {
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
m_mTree[0].SetSplitDirVert( false) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
m_mTree[1].SetSplitDirVert( false) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
if ( AreSamePointApprox( ptP00, ptP10)) {
|
||||
if( (int) m_mTree.size() == 1) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
bool bOk = false ;
|
||||
bool bCapped0 = true, bCapped1 = true ;
|
||||
Point3d ptU0, ptU1 ;
|
||||
// controllo se tutti i punti sull'isoparametrica sono uguali
|
||||
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
|
||||
ptU0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptU0) ;
|
||||
ptU1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP01, ptU1) ;
|
||||
}
|
||||
if ( bCapped0 && bCapped1) {
|
||||
m_mTree[0].SetSplitDirVert( false) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( false) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4) {
|
||||
m_mTree[0].m_nLeft = -1 ;
|
||||
m_mTree[0].m_nRight = -1 ;
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
m_mTree[1].m_nRight = -1 ;
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4) {
|
||||
m_mTree[0].m_nLeft = -1 ;
|
||||
m_mTree[0].m_nRight = -1 ;
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
m_mTree[1].m_nRight = -1 ;
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calcolo e salvo la distanza reale tra i vertici della cella root
|
||||
double dLen0 = Dist( ptP00, ptP10) ;
|
||||
double dLen1 = Dist( ptP10, ptP11) ;
|
||||
double dLen2 = Dist( ptP01, ptP11) ;
|
||||
double dLen3 = Dist( ptP00, ptP01) ;
|
||||
// calcolo e salvo la lunghezza reale delle curve di bezier di bordo
|
||||
PtrOwner<CurveComposite> pCrvV0( m_pSrfBz->GetCurveOnU( 0)) ;
|
||||
PtrOwner<CurveComposite> pCrvV1( m_pSrfBz->GetCurveOnU( 1)) ;
|
||||
PtrOwner<CurveComposite> pCrvU0( m_pSrfBz->GetCurveOnV( 0)) ;
|
||||
PtrOwner<CurveComposite> pCrvU1( m_pSrfBz->GetCurveOnV( 1)) ;
|
||||
double dLen0 ; pCrvV0->GetApproxLength( dLen0) ;
|
||||
double dLen1 ; pCrvU1->GetApproxLength( dLen1) ;
|
||||
double dLen2 ; pCrvV1->GetApproxLength( dLen2) ;
|
||||
double dLen3 ; pCrvU0->GetApproxLength( dLen3) ;
|
||||
m_vDim.clear() ;
|
||||
m_vDim.push_back( ( dLen0 != 0 ? dLen0 : 1)) ;
|
||||
m_vDim.push_back( ( dLen1 != 0 ? dLen1 : 1)) ;
|
||||
m_vDim.push_back( ( dLen2 != 0 ? dLen2 : 1)) ;
|
||||
m_vDim.push_back( ( dLen3 != 0 ? dLen3 : 1)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AddOrMergeBBox ( const BBox3d& bBox3dA , std::vector<BBox3d>& vBBox, const bool& bAdd = true, const int& nInd = 0) {
|
||||
Point3d ptMin = bBox3dA.GetMin() ;
|
||||
Point3d ptMax = bBox3dA.GetMax() ;
|
||||
if ( (int)vBBox.size() == 0) {
|
||||
vBBox.push_back( bBox3dA) ;
|
||||
return true ;
|
||||
}
|
||||
bool bAdded = false ;
|
||||
for ( int b = 0 ; b < (int)vBBox.size() ; ++b) {
|
||||
BBox3d bBox3dB = vBBox[b] ;
|
||||
BBox3d b3Int ;
|
||||
// se sono celle diverse e ho un'intersezione faccio il merge
|
||||
if ( ! ( AreSamePointExact( ptMin, bBox3dB.GetMin()) && AreSamePointExact( ptMax, bBox3dB.GetMax())) &&
|
||||
bBox3dA.FindIntersectionXY( bBox3dB, b3Int)) {
|
||||
vBBox[b].Add( bBox3dA) ;
|
||||
if ( ! bAdd ) {
|
||||
vBBox.erase( vBBox.begin() + nInd) ;
|
||||
-- b ;
|
||||
}
|
||||
// se ho fatto un merge devo controllare se ora la nuova bbox ha delle intersezioni
|
||||
AddOrMergeBBox( vBBox[b], vBBox, false, b) ;
|
||||
bAdded = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( ! bAdded && bAdd)
|
||||
vBBox.push_back( bBox3dA) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::GetIndependentTrees( std::vector<std::tuple<Point3d,Point3d>>& vTrees)
|
||||
{
|
||||
if ( ! m_bTrimmed ) {
|
||||
vTrees.push_back( std::tuple<Point3d, Point3d>( ORIG, ORIG));
|
||||
}
|
||||
else {
|
||||
// se ho dei loop di trim trovo le loro BBox3d per costruire l'albero solo all'interno di queste BBox
|
||||
bool bIsRoot = false ;
|
||||
std::vector<BBox3d> vBBox ;
|
||||
for ( int a = 0 ; a < (int)m_vPlApprox.size(); ++a ) {
|
||||
PolyLine plLoop = std::get<0>( m_vPlApprox[a]) ;
|
||||
// calcolo la BBox3d
|
||||
BBox3d bBox3dA ;
|
||||
Point3d pt ;
|
||||
plLoop.GetFirstPoint( pt) ;
|
||||
bBox3dA.Add( pt) ;
|
||||
while ( plLoop.GetNextPoint( pt))
|
||||
bBox3dA.Add( pt) ;
|
||||
// controllo se ho intersezioni con altre bbox
|
||||
// se ho intersezioni unisco le bbox, altrimenti le lascio indipendenti
|
||||
AddOrMergeBBox( bBox3dA, vBBox) ;
|
||||
}
|
||||
// controllo se dopo aver unito le bbox ho ottenuto Root
|
||||
Point3d ptTR( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF) ;
|
||||
for (int c = 0 ; c < (int)vBBox.size(); ++ c) {
|
||||
BBox3d bBox3d = vBBox[c] ;
|
||||
if ( AreSamePointEpsilon( bBox3d.GetMin(), ORIG, 10) && AreSamePointEpsilon( bBox3d.GetMax(), ptTR, 10)){
|
||||
bIsRoot = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// restituisco le celle parent di partenza a partire dalle bbox che ho ottenuto
|
||||
if ( ! bIsRoot ) {
|
||||
for (int i = 0 ; i < (int)vBBox.size() ; ++ i) {
|
||||
Point3d ptMin = vBBox[i].GetMin() ;
|
||||
Point3d ptMax = vBBox[i].GetMax() ;
|
||||
vTrees.push_back( std::tuple<Point3d,Point3d>( ptMin, ptMax)) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
vTrees.push_back( std::tuple<Point3d, Point3d>( ORIG, ORIG));
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::Split( const int& nId, const double& dSplitValue)
|
||||
@@ -283,7 +395,7 @@ Tree::Split( const int& nId, const double& dSplitValue)
|
||||
// controllo che lo split non venga fatto sul lato della cella
|
||||
if ( ( m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && dSplitValue < m_mTree[nId].GetTopRight().x - EPS_SMALL) ||
|
||||
( ! m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && dSplitValue < m_mTree[nId].GetTopRight().y - EPS_SMALL)) {
|
||||
// per lo split a parametro libero dovrò impedire che si facciano split troppo vicini al bordo!!!!!!!!!!!!!!!!!!!
|
||||
// quando si implementerà lo split a parametro libero bisognerà impedire che si facciano split troppo vicini al bordo della cella!!!!!!!!!!!!!!!!!!!
|
||||
m_mTree[nId].m_dSplit = dSplitValue ;
|
||||
Cell cChild1, cChild2 ;
|
||||
cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
|
||||
@@ -1219,7 +1331,7 @@ Tree::GetPolygons( std::vector<POLYLINEVECTOR>& vPolygons) {
|
||||
return false ;
|
||||
POLYLINEVECTOR vPolygonsBasic ;
|
||||
GetPolygonsBasic( vPolygonsBasic) ;
|
||||
// scorro sui poligoni delle celle non trimmate
|
||||
// scorro sulle celle e costruisco i poligoni
|
||||
int nCells = (int)vPolygonsBasic.size() ;
|
||||
for ( int i = 0 ; i < nCells ; ++i) {
|
||||
|
||||
@@ -1418,12 +1530,11 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim) const
|
||||
|
||||
nCells.push_back( nId) ;
|
||||
|
||||
// se sono in un vertice o su un lato devo controllare di aver trovato la cella giusta
|
||||
Point3d ptBr( m_mTree.at( nId).GetTopRight().x , m_mTree.at( nId).GetBottomLeft().y) ;
|
||||
Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x , m_mTree.at( nId).GetTopRight().y) ;
|
||||
if ( AreSamePointApprox( ptToAssign, ptTl) ||
|
||||
AreSamePointApprox( ptToAssign, m_mTree.at( nId).GetBottomLeft()) ||
|
||||
AreSamePointApprox( ptToAssign, ptBr) ||
|
||||
AreSamePointApprox( ptToAssign, m_mTree.at( nId).GetTopRight()))
|
||||
if ( abs( ptToAssign.x - ptTl.x) < EPS_SMALL || abs( ptToAssign.x - ptBr.x) < EPS_SMALL ||
|
||||
abs( ptToAssign.y - ptTl.y) < EPS_SMALL || abs( ptToAssign.y - ptBr.y) < EPS_SMALL)
|
||||
{
|
||||
Point3d ptToAssignPlus ;
|
||||
double dParam ;
|
||||
@@ -1432,11 +1543,11 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim) const
|
||||
clTrim.GetPointTang( dParam + EPS_SMALL, ICurve::FROM_MINUS, ptToAssignPlus, vDir) ;
|
||||
if ( abs( vDir.x) > 1 - EPS_SMALL || abs( vDir.y) > 1 - EPS_SMALL) {
|
||||
vDir.Rotate( Z_AX, -90) ;
|
||||
ptToAssignPlus = ptToAssignPlus + vDir * EPS_SMALL ;
|
||||
ptToAssignPlus = ptToAssignPlus + vDir * 2 * EPS_SMALL ;
|
||||
}
|
||||
nCells = FindCell( ptToAssignPlus, clTrim) ;
|
||||
if ( nCells.empty()) {
|
||||
ptToAssignPlus = ptToAssignPlus - 2 * vDir * EPS_SMALL ;
|
||||
ptToAssignPlus = ptToAssignPlus - 4 * vDir * EPS_SMALL ;
|
||||
nCells = FindCell( ptToAssignPlus, clTrim) ;
|
||||
}
|
||||
}
|
||||
@@ -1473,16 +1584,16 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
bool
|
||||
Tree::TraceLoopLabelCell( void)
|
||||
{
|
||||
double dLinTol = - EPS_SMALL ; // questo è riferito allo spazio parametrico, quando è già stato riporatato al range 0..1 !!!!!!
|
||||
// il valore è negativo perché voglio considerare contenuto anche un punto che sta su un lato
|
||||
// il valore è negativo perché voglio considerare contenuto anche un punto che sta su un lato
|
||||
double dLinTol = - EPS_SMALL ;
|
||||
POLYLINEVECTOR vplPolygons ;
|
||||
GetPolygonsBasic( vplPolygons) ;
|
||||
// percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle
|
||||
for ( int i = 0 ; i < (int) m_vPlApprox.size() ; ++ i) {
|
||||
PolyLine plLoop = std::get<0>(m_vPlApprox[i]) ;
|
||||
// calcolo se il loop è CCW o CW
|
||||
// controllo se il loop è CCW o CW
|
||||
bool bCCW = std::get<1>(m_vPlApprox[i]) ;
|
||||
// trovo in quale cella è il ptStart
|
||||
// trovo in quale cella è il ptStart
|
||||
Point3d ptStart ;
|
||||
plLoop.GetFirstPoint( ptStart) ;
|
||||
PNTULIST lPt = plLoop.GetUPointList() ;
|
||||
@@ -1493,9 +1604,14 @@ Tree::TraceLoopLabelCell( void)
|
||||
clFirst.Set( ptFirst->first, ptSecond->first) ;
|
||||
// individuo la cella da cui parte il loop
|
||||
INTVECTOR nCells = FindCell( ptStart, clFirst) ;
|
||||
int nId = nCells.back() ;
|
||||
int nId ;
|
||||
if ( ! nCells.empty())
|
||||
nId = nCells.back() ;
|
||||
else
|
||||
// il loop è fuori dalla cella root che sto analizzando
|
||||
continue ;
|
||||
int nFirstCell = nId ;
|
||||
// trovo quali punti della polyline sono nella cella e l'intersezione
|
||||
// trovo quali punti della polyline sono nella cella e l'intersezione
|
||||
PNTVECTOR vptInters ;
|
||||
vptInters.push_back( ptStart) ;
|
||||
// qui mi devo salvare quanti elementi ho già nel vettore m_vInters della cella
|
||||
@@ -1512,18 +1628,15 @@ Tree::TraceLoopLabelCell( void)
|
||||
INTVECTOR :: iterator iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
|
||||
int nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ;
|
||||
bool bEraseNextPoint = false ;
|
||||
//// per debug
|
||||
//int c = 0 ;
|
||||
Cell cUnderWork ;
|
||||
while ( plLoop.GetNextPoint( ptCurr)) {
|
||||
//++ c ;
|
||||
// sto uscendo dalla cella, quindi cerco l'intersezione
|
||||
Point3d ptTStart, ptTEnd ;
|
||||
plLoop.GetPrevPoint( ptTStart) ;
|
||||
plLoop.GetNextPoint( ptTEnd) ;
|
||||
CurveLine clTrim ;
|
||||
clTrim.Set( ptTStart, ptTEnd) ;
|
||||
while( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) { /// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva
|
||||
// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva
|
||||
while( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) {
|
||||
// sto uscendo dalla cella, quindi cerco l'intersezione
|
||||
if ( bEraseNextPoint) {
|
||||
vptInters.pop_back() ;
|
||||
bEraseNextPoint = false ;
|
||||
@@ -1552,8 +1665,6 @@ Tree::TraceLoopLabelCell( void)
|
||||
m_mTree[nId].m_vInters.back().bCCW = bCCW ;
|
||||
// salvo il chunk del loop
|
||||
m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ;
|
||||
// per debug
|
||||
cUnderWork = m_mTree[nId] ;
|
||||
}
|
||||
// aggiungo la fine del segmento nel vettore delle intersezioni
|
||||
vptInters.push_back( ptCurr) ;
|
||||
@@ -1620,7 +1731,7 @@ Tree::TraceLoopLabelCell( void)
|
||||
GetRightNeigh( nCell, vNeigh) ;
|
||||
// proseguo finché non sono sull'elemento più alto di vFirst e tutti i suoi vicini sono processati/categorizzati
|
||||
bool bAllDone = false ;
|
||||
while ( nCell != nLastLeft && ! bAllDone) {
|
||||
while ( ! bAllDone) {
|
||||
// categorizzo la cella
|
||||
m_mTree[nCell].m_nFlag2 = 1 ;
|
||||
CategorizeCell( nCell) ;
|
||||
@@ -1640,7 +1751,8 @@ Tree::TraceLoopLabelCell( void)
|
||||
if ( ! bProceeded) {
|
||||
m_mTree[nCell].SetProcessed() ;
|
||||
}
|
||||
else { //categorizzo la cella
|
||||
else {
|
||||
//categorizzo la cella
|
||||
m_mTree[nCell].m_nFlag2 = 1 ;
|
||||
CategorizeCell( nCell) ;
|
||||
}
|
||||
@@ -2015,7 +2127,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
|
||||
m_mTree[nId].m_vInters.back().nIn = 7 ;
|
||||
}
|
||||
else {
|
||||
nId = vNeigh[0] ;
|
||||
nId = vNeigh1[0] ;
|
||||
m_mTree[nId].m_vInters.emplace_back() ;
|
||||
m_mTree[nId].m_vInters.back().nIn = 4 ;
|
||||
}
|
||||
@@ -2064,8 +2176,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
|
||||
m_mTree[nId].m_vInters.back().nIn = 4 ;
|
||||
}
|
||||
else {
|
||||
GetRightNeigh( nId, vNeigh) ;
|
||||
nId = vNeigh[0] ;
|
||||
nId = vNeigh1[0] ;
|
||||
m_mTree[nId].m_vInters.emplace_back() ;
|
||||
m_mTree[nId].m_vInters.back().nIn = 5 ;
|
||||
}
|
||||
@@ -2114,7 +2225,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
|
||||
m_mTree[nId].m_vInters.back().nIn = 5 ;
|
||||
}
|
||||
else {
|
||||
nId = vNeigh.back() ;
|
||||
nId = vNeigh1.back() ;
|
||||
m_mTree[nId].m_vInters.emplace_back() ;
|
||||
m_mTree[nId].m_vInters.back().nIn = 6 ;
|
||||
}
|
||||
@@ -2369,7 +2480,7 @@ Tree::CreateCellPolygons( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPoly
|
||||
c = 0 ;
|
||||
plTrimmedPoly.Clear() ;
|
||||
nEdgeIn = -1 ;
|
||||
// devo verificare se tra i loop che sono finiti in vToCheck in realtà qualcuno l'ho usato per fare un poligono/////////////////////////////////////
|
||||
// devo verificare se tra i loop che sono finiti in vToCheck in realtà qualcuno l'ho usato per fare un poligono
|
||||
for ( int k = 0 ; k < (int)vToCheck.size() ; ++ k) {
|
||||
for ( int i = 0 ; i < (int)vAddedLoops.size() ; ++ i) {
|
||||
if ( vToCheck[k] == vAddedLoops[i]) {
|
||||
@@ -2395,6 +2506,7 @@ Tree::CreateIslandAndHoles( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPo
|
||||
PolyLine plTrimmedPoly ;
|
||||
|
||||
// loop interni in una cella intersecata
|
||||
int nChunkBiggestCW = -1 ;
|
||||
if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) {
|
||||
PolyLine plInLoop ;
|
||||
Inters inA ;
|
||||
@@ -2407,6 +2519,8 @@ Tree::CreateIslandAndHoles( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPo
|
||||
if ( inA.nIn == -1) {
|
||||
// per ogni loop CW verifico che ci sia un loop CCW dello stesso chunk ( che quindi lo contiene)
|
||||
if ( ! inA.bCCW) {
|
||||
if ( nChunkBiggestCW == -1)
|
||||
nChunkBiggestCW = inA.nChunk ;
|
||||
bContained = false ;
|
||||
Inters inB = m_mTree[nId].m_vInters[0] ;
|
||||
for( int c = 0 ; c < nInters ; ++ c){
|
||||
@@ -2443,7 +2557,8 @@ Tree::CreateIslandAndHoles( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPo
|
||||
vCellPolygons.push_back( plInLoop) ;
|
||||
vPolygons.push_back( vCellPolygons) ;
|
||||
++ nPoly ;
|
||||
vnParentChunk.push_back( inA.nChunk) ;
|
||||
// imposto il chunk del loop CW più grande ( il primo che ho incontrato)
|
||||
vnParentChunk.push_back( nChunkBiggestCW) ;
|
||||
vCellPolygons.clear() ;
|
||||
plInLoop.Clear() ;
|
||||
}
|
||||
@@ -2577,20 +2692,37 @@ Tree::CheckIfBefore( const int& nEdge1, const Point3d& ptP1, const int& nEdge2,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::CheckIfBefore( const int& nEdge, const Point3d& ptP1, const Point3d& ptP2) const
|
||||
Tree::CheckIfBefore( const int& nEdge, const Point3d& ptP1, const Point3d& ptP2, const int& nEdge2) const
|
||||
{
|
||||
// i punti devono essere sullo stesso lato nEdge
|
||||
// nEdge2 è di backup, in caso nEdge sia un vertice, per capire di quale lato si tratta
|
||||
int nEdgeRef ;
|
||||
if ( nEdge != nEdge2 && nEdge2 != -1) {
|
||||
if ( std::min(nEdge, nEdge2) < 4)
|
||||
nEdgeRef = std::min(nEdge, nEdge2) ;
|
||||
else if ( AreSameEdge( nEdge, 0) && AreSameEdge( nEdge2, 0))
|
||||
nEdgeRef = 0 ;
|
||||
else if ( AreSameEdge( nEdge, 1) && AreSameEdge( nEdge2, 1))
|
||||
nEdgeRef = 1 ;
|
||||
else if ( AreSameEdge( nEdge, 2) && AreSameEdge( nEdge2, 2))
|
||||
nEdgeRef = 2 ;
|
||||
else if ( AreSameEdge( nEdge, 3) && AreSameEdge( nEdge2, 3))
|
||||
nEdgeRef = 3 ;
|
||||
}
|
||||
else
|
||||
nEdgeRef = nEdge ;
|
||||
// sul lato nEdge controllo se ptP1 viene prima di ptP2.
|
||||
// i lati vengono percorsi in senso antiorario
|
||||
if ( AreSameEdge( nEdge, 0)) {
|
||||
if ( AreSameEdge( nEdgeRef, 0)) {
|
||||
return ptP1.x > ptP2.x ;
|
||||
}
|
||||
else if ( AreSameEdge( nEdge, 1)) {
|
||||
else if ( AreSameEdge( nEdgeRef, 1)) {
|
||||
return ptP1.y > ptP2.y ;
|
||||
}
|
||||
else if ( AreSameEdge( nEdge, 2)) {
|
||||
else if ( AreSameEdge( nEdgeRef, 2)) {
|
||||
return ptP1.x < ptP2.x ;
|
||||
}
|
||||
else if ( AreSameEdge( nEdge, 3)) {
|
||||
else if ( AreSameEdge( nEdgeRef, 3)) {
|
||||
return ptP1.y < ptP2.y ;
|
||||
}
|
||||
return false ;
|
||||
@@ -3049,13 +3181,13 @@ Tree::CategorizeCell( const int& nId)
|
||||
bool bIntersIn ;
|
||||
for ( int k = 0 ; k < (int) m_mTree[vNeigh[0]].m_vInters.size() ; ++ k) {
|
||||
if ( AreSameEdge( m_mTree[vNeigh[0]].m_vInters[k].nIn, 3)) {
|
||||
if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt[0], ptInters)) {
|
||||
if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt[0], ptInters, 3)) {
|
||||
ptInters = m_mTree[vNeigh[0]].m_vInters[k].vpt[0] ;
|
||||
bIntersIn = true ;
|
||||
}
|
||||
}
|
||||
if ( AreSameEdge( m_mTree[vNeigh[0]].m_vInters[k].nOut, 3)) {
|
||||
if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt.back(), ptInters)) {
|
||||
if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt.back(), ptInters, 3)) {
|
||||
ptInters = m_mTree[vNeigh[0]].m_vInters[k].vpt.back() ;
|
||||
bIntersIn = false ;
|
||||
}
|
||||
@@ -3103,6 +3235,7 @@ Tree::CheckIfBetween( const Inters& inA, const Inters& inB) const
|
||||
}
|
||||
else if ( nEdge == 7)
|
||||
nEdge = 0 ;
|
||||
// creo la sequenza di Edges da scorrere per trovare i possibili validNextStart
|
||||
while ( ! AreSameEdge( nEdge, inA.nIn) || (int) vEdges.size() == 0) {
|
||||
vEdges.push_back( nEdge) ;
|
||||
if ( nEdge == 3)
|
||||
@@ -3115,16 +3248,16 @@ Tree::CheckIfBetween( const Inters& inA, const Inters& inB) const
|
||||
bool bFound = false ;
|
||||
for ( int i : vEdges) {
|
||||
if ( AreSameEdge( inB.nIn, i)) {
|
||||
if ( AreSameEdge( inB.nIn, inA.nIn) && AreSameEdge( inA.nIn, inA.nOut)) {
|
||||
if ( AreSameEdge( inB.nIn, inA.nIn) && AreSameEdge( inA.nIn, inA.nOut) && AreSameEdge( inB.nIn, inA.nOut)) {
|
||||
nEdge = inA.nIn ;
|
||||
//se l'inizio di A è prima della fine, allora devo controllare che B sia compreso tra Out e In ( esterno)
|
||||
if ( CheckIfBefore( nEdge, inA.vpt[0], inA.vpt.back())) {
|
||||
if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0]) || CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0]))
|
||||
if ( CheckIfBefore( nEdge, inA.vpt[0], inA.vpt.back(), inA.nOut)) {
|
||||
if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0], inA.nOut ) || CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0], inA.nOut))
|
||||
bFound = true ;
|
||||
}
|
||||
// se l'inizio di A è dopo la fine, allora devo controllare che B sia compreso tra In e Out ( interno)
|
||||
else {
|
||||
if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0]) && CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0]))
|
||||
if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0], inA.nOut) && CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0], inA.nOut))
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
@@ -3138,17 +3271,18 @@ Tree::CheckIfBetween( const Inters& inA, const Inters& inB) const
|
||||
}
|
||||
else if ( AreSameEdge( inB.nIn, inA.nIn)) {
|
||||
//devo controllare il loop b sia prima dell'inizio di A
|
||||
if ( CheckIfBefore( inA.nIn, inB.vpt[0], inA.vpt[0]))
|
||||
if ( CheckIfBefore( inA.nIn, inB.vpt[0], inA.vpt[0], inB.nIn))
|
||||
bFound = true ;
|
||||
}
|
||||
else
|
||||
// devo controllare che inB sia prima di OutB
|
||||
if ( AreSameEdge( inB.nOut, inB.nIn) && CheckIfBefore( inB.nOut, inB.vpt[0], inB.vpt.back())) {
|
||||
if ( AreSameEdge( inB.nOut, inB.nIn) && CheckIfBefore( inB.nOut, inB.vpt[0], inB.vpt.back(), inB.nIn)) {
|
||||
bFound = true ;
|
||||
}
|
||||
else if ( ! AreSameEdge( inB.nOut,inB.nIn))
|
||||
bFound = true ;
|
||||
}
|
||||
// se incontro prima l'uscita dell'ingresso, sicuramente InB NON è un validNextStart
|
||||
if ( AreSameEdge( inB.nOut, i) && ! bFound && CheckIfBefore( i, inA.vpt[0], inB.vpt.back()) && CheckIfBefore( i, inA.vpt.back(), inB.vpt.back()))
|
||||
break ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user