EgtGeomKernel :

- corretta e migliorata la fuzione di cut per superfici di Bezier.
Manca :
- da migliorare i tagli multipli alle superfici di Bezier.
This commit is contained in:
Daniele Bariletti
2024-02-22 17:39:44 +01:00
parent c303b1273d
commit 156d0eea4b
4 changed files with 491 additions and 127 deletions
+129 -30
View File
@@ -30,7 +30,8 @@ using namespace std ;
//----------------------------------------------------------------------------
Tree::Tree( void)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
Cell cRoot( ptBl, ptTr) ;
@@ -39,7 +40,8 @@ Tree::Tree( void)
//----------------------------------------------------------------------------
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_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
}
@@ -51,7 +53,8 @@ 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)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
Cell cRoot( ptBl, ptTr) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
@@ -227,16 +230,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
// 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
bool bPole0 = true, bPole1 = true ;
Point3d ptU0, ptU1 ;
// controllo se tutti i punti di controllo 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) ;
ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ;
ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ;
}
if ( bCapped0 && bCapped1) {
m_vbPole[1] = bPole0 ;
m_vbPole[3] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ;
@@ -256,16 +261,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
// 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 ;
bool bPole0 = true, bPole1 = true ;
Point3d ptV0, ptV1 ;
// 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) ;
ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ;
ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ;
}
if ( bCapped0 && bCapped1) {
m_vbPole[0] = bPole0 ;
m_vbPole[3] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( false) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( false) ;
@@ -1434,12 +1441,13 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells)
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells)
{
// 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
m_vPolygons.clear() ;
// 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 ;
@@ -1463,6 +1471,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells)
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
// N.B. :i poligoni sono costruiti a partire dal ptBL !!!
for ( int nId : vCells) {
vVertices.clear() ;
vNeigh.clear() ;
@@ -3582,34 +3591,64 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges)
// 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) ;
Point3d pt3d ;
// 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()) ) {
if ( i == 0) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ;
++ nPtCount ;
// 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) ;
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) {
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
vPLEdges.back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ;
++ nPtCount ;
}
else if ( i == 1 && AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) ) {
else if ( i == 1 ) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) {
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ;
++ nPtCount ;
}
else if ( i == 2 && AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) ) {
else if ( i == 2) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) {
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ;
++ nPtCount ;
}
else if ( i == 3 && AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) ) {
else if ( i == 3) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) {
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ;
++ nPtCount ;
}
}
}
@@ -3631,14 +3670,69 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts)
PolyLine pl = vCuts.at( i) ;
m_mTree.at( nRoot).m_vInters.emplace_back() ;
Point3d pt ; pl.GetFirstPoint( pt) ;
int nEdgeIn ; OnWhichEdge( nRoot, pt, nEdgeIn) ;
int nEdgeIn ;
// se non trovo il primo punto esattamente su un lato, estendo il primo tratto della polyline all'inditro finchè trovo un'intersezione con un lato
// questa intersezione diventa il nuovo primo punto del vettore intersezione
if ( ! OnWhichEdge(nRoot, pt, nEdgeIn) ) {
Point3d ptSecond ; pl.GetNextPoint( ptSecond) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecond, pt - ptSecond, 1e6) ;
PtrOwner<ICurveLine> pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ;
PtrOwner<ICurveLine> pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ;
PtrOwner<ICurveLine> pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ;
PtrOwner<ICurveLine> pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ;
IntersCurveCurve icc0( *pCL, *pCL0) ;
IntersCurveCurve icc1( *pCL, *pCL1) ;
IntersCurveCurve icc2( *pCL, *pCL2) ;
IntersCurveCurve icc3( *pCL, *pCL3) ;
IntCrvCrvInfo iccInfo ;
if (icc0.GetCrossIntersCount() != 0)
icc0.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc1.GetCrossIntersCount() != 0)
icc1.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc2.GetCrossIntersCount() != 0)
icc2.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc3.GetCrossIntersCount() != 0)
icc3.GetIntCrvCrvInfo( 0, iccInfo) ;
pt = iccInfo.IciA[0].ptI ;
if ( ! OnWhichEdge(nRoot, pt, nEdgeIn))
return false ;
}
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) ;
int nEdgeOut ;
// se non trovo l'ultimo punto esattamente su un lato, estendo l'ultimo tratto della polyline in avnti finchè trovo un'intersezione con un lato
// questa intersezione diventa il nuovo ultimo punto del vettore intersezione
if ( ! OnWhichEdge(nRoot, pt, nEdgeOut) ) {
Point3d ptSecondToLast ; pl.GetNextPoint( ptSecondToLast) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecondToLast, pt - ptSecondToLast, 1e6) ;
PtrOwner<ICurveLine> pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ;
PtrOwner<ICurveLine> pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ;
PtrOwner<ICurveLine> pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ;
PtrOwner<ICurveLine> pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ;
IntersCurveCurve icc0( *pCL, *pCL0) ;
IntersCurveCurve icc1( *pCL, *pCL1) ;
IntersCurveCurve icc2( *pCL, *pCL2) ;
IntersCurveCurve icc3( *pCL, *pCL3) ;
IntCrvCrvInfo iccInfo ;
if (icc0.GetCrossIntersCount() != 0)
icc0.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc1.GetCrossIntersCount() != 0)
icc1.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc2.GetCrossIntersCount() != 0)
icc2.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc3.GetCrossIntersCount() != 0)
icc3.GetIntCrvCrvInfo( 0, iccInfo) ;
pt = iccInfo.IciA[0].ptI ;
vInters.pop_back() ;
vInters.emplace_back( pt) ;
if ( ! OnWhichEdge(nRoot, pt, nEdgeOut))
return false ;
}
m_mTree.at( nRoot).m_vInters.back().vpt = vInters ;
m_mTree.at( nRoot).m_vInters.back().nOut = nEdgeOut ;
}
// chiamo una funzione per renderli coerenti
@@ -3650,6 +3744,8 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts)
bool
Tree::AdjustCuts( void)
{
if ( int( m_mTree.at( -1).m_vInters.size()) == 1)
return true ;
// 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
@@ -3657,6 +3753,9 @@ Tree::AdjustCuts( void)
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()) ;
int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ;
m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ;
m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ;
bPreviousWasStart = m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ;
}
else