EgtGeomKernel :

- aggiunta la funzione per creare una sfera come superficie bezier
- aggiunta la funzione per tagliare una superificie bezier con un piano.
This commit is contained in:
Daniele Bariletti
2024-02-20 12:28:45 +01:00
parent 8d0c04e092
commit c303b1273d
5 changed files with 647 additions and 137 deletions
+176 -3
View File
@@ -49,6 +49,14 @@ Tree::~Tree( void)
{
}
//----------------------------------------------------------------------------
Tree::Tree( const Point3d ptBl, const Point3d ptTr)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false)
{
Cell cRoot( ptBl, ptTr) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
}
//----------------------------------------------------------------------------
void
Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax)
@@ -931,6 +939,7 @@ Tree::Balance()
void
Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
{
// le celle restituite sono ordinate per x crescente
if ( vTopNeighs.empty()) {
if ( m_mTree.at( nId).m_nTop == -2)
return ;
@@ -1000,6 +1009,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
vector<Cell> vCells ;
for ( int k : vTopNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vTopNeighs.clear() ;
for ( Cell c : vCells)
@@ -1011,6 +1021,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
void
Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
{
// le celle restituite sono ordinate per x crescente
if ( vBottomNeighs.empty()) {
if ( m_mTree.at( nId).m_nBottom == -2)
return ;
@@ -1080,6 +1091,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
vector<Cell> vCells ;
for ( int k : vBottomNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vBottomNeighs.clear() ;
for ( Cell c : vCells)
@@ -1090,6 +1102,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
void
Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
{
// le celle restituite sono ordinate per y crescente
if ( vLeftNeighs.empty()) {
if ( m_mTree.at( nId).m_nLeft == -2)
return ;
@@ -1159,6 +1172,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
vector<Cell> vCells ;
for ( int k : vLeftNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vLeftNeighs.clear() ;
for ( Cell c : vCells)
@@ -1169,6 +1183,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
void
Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
{
// le celle restituite sono ordinate per y crescente
if ( vRightNeighs.empty()) {
if ( m_mTree.at( nId).m_nRight == -2)
return ;
@@ -1238,6 +1253,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
vector<Cell> vCells ;
for ( int k : vRightNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vRightNeighs.clear() ;
for ( Cell c : vCells)
@@ -1418,9 +1434,16 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells)
{
if ( m_vPolygons.empty()) {
// condizioni per il calcolo dei poligoni di base
if ( m_vPolygons.empty() || // se non li ho mai calcolati
( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle
( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size())) { // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle
// se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie
if ( vCells.empty())
vCells = m_vnLeaves ;
PNTVECTOR vVertices ;
INTVECTOR vNeigh ;
// setto le celle che sono sul LeftEdge e sul TopEdge
@@ -1440,7 +1463,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
bool bBottomRight , bTopLeft ;
// scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline della cella anche i vertici, delle celle adiacenti,
// che sono sui lati della cella corrente
for ( int nId : m_vnLeaves) {
for ( int nId : vCells) {
vVertices.clear() ;
vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ;
@@ -3521,3 +3544,153 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges)
{
INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge
// recupero le celle sui quattro bordi
vEdges.emplace_back() ;
GetRootNeigh( 0, vEdges[0]) ;
// le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR,
// quindi devo invertire gli Edge 0 e 1
reverse( vEdges[0].begin(), vEdges[0].end()) ;
vEdges.emplace_back() ;
GetRootNeigh( 1, vEdges[1]) ;
reverse( vEdges[1].begin(), vEdges[1].end()) ;
vEdges.emplace_back() ;
GetRootNeigh( 2, vEdges[2]) ;
vEdges.emplace_back() ;
GetRootNeigh( 3, vEdges[3]) ;
// recupero i poligoni base delle celle sui bordi
POLYLINEMATRIX mPL ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[0], vEdges[0]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[1], vEdges[1]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[2], vEdges[2]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[3], vEdges[3]) ;
// scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato
for ( int i = 0 ; i < int( mPL.size()) ; ++i) {
vPLEdges.emplace_back() ;
int nPtCount = 0 ;
// scorro sui poligoni delle celle di un lato
for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) {
Point3d pt ; mPL[i][c].GetFirstPoint( pt) ;
// a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato
if ( i == 0 && AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) ) {
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
}
else if ( i == 1 && AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) ) {
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
}
else if ( i == 2 && AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) ) {
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
}
else if ( i == 3 && AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) ) {
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts)
{
// questa funzione dà per scontato di stare lavorando sulla root di uno spazio parametrico di cui si sta solamente calcolando
// il Contour. La funzione da chiamare dopo questa è la CreateCellContour.
// i tagli sono sempre delle linee che tagliano da parte a parte la cella, quindi sono curve aperte
if ( m_mTree.size() > 1)
return false ;
int nRoot = -1 ;
for ( int i = 0 ; i < int( vCuts.size()); ++i) {
PolyLine pl = vCuts.at( i) ;
m_mTree.at( nRoot).m_vInters.emplace_back() ;
Point3d pt ; pl.GetFirstPoint( pt) ;
int nEdgeIn ; OnWhichEdge( nRoot, pt, nEdgeIn) ;
m_mTree.at( nRoot).m_vInters.back().nIn = nEdgeIn ;
PNTVECTOR vInters ;
vInters.emplace_back( pt) ;
while ( pl.GetNextPoint( pt))
vInters.emplace_back( pt) ;
pl.GetLastPoint( pt) ;
int nEdgeOut ; OnWhichEdge( nRoot, pt, nEdgeOut) ;
m_mTree.at( nRoot).m_vInters.back().nOut = nEdgeOut ;
}
// chiamo una funzione per renderli coerenti
AdjustCuts() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::AdjustCuts( void)
{
// li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR
sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ;
// ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione
bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ;
for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) {
if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) {
reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ;
bPreviousWasStart = m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ;
}
else
bPreviousWasStart = ! m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
{
// questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli
if ( m_mTree.size() > 1)
return false ;
int nRoot = -1 ;
// preparo tutto per poter chiamare la createCellPolygon
m_vnLeaves.push_back( nRoot) ;
INTVECTOR vToCheck( (int) m_mTree.at(nRoot).m_vInters.size()) ;
generate_n( vToCheck.begin(), (int) m_mTree.at(nRoot).m_vInters.size(), generator()) ;
int nPoly = 0 ;
INTVECTOR vnParentChunk ;
PolyLine pl ;
pl.AddUPoint(0, m_mTree.at(nRoot).GetTopRight()) ;
pl.AddUPoint(1, m_mTree.at(nRoot).GetTopLeft()) ;
pl.AddUPoint(2, m_mTree.at(nRoot).GetBottomLeft()) ;
pl.AddUPoint(3, m_mTree.at(nRoot).GetBottomRight()) ;
pl.Close() ;
// ora posso creare il poligono della cella con i tagli
while( (int)vToCheck.size() != 0) {
int nPolyBefore = nPoly ;
CreateCellPolygons( 0, vPolygons, vToCheck, nPoly, vnParentChunk, pl) ;
if ( nPolyBefore == nPoly)
break ;
}
return true ;
}