Skip to content

Commit

Permalink
-fix for bug 15186. The AutoFixFourTriangle points was not smart enou…
Browse files Browse the repository at this point in the history
…gh to handle a case with adjacent points that were connected
  • Loading branch information
alemon-aquaveo committed Jul 1, 2024
1 parent 8acb351 commit fc807f9
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 58 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/XmsGrid-CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [macos-latest]
platform: [macos-13]
python-version: ['3.10']
build_type: [Release, Debug]

Expand Down Expand Up @@ -73,6 +73,10 @@ jobs:
RELEASE_PYTHON: 'False'

steps:
# Get Correct Version of Xcode
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 14.3.1
# Checkout Sources
- name: Checkout Source
uses: actions/checkout@v2
Expand Down
15 changes: 15 additions & 0 deletions test_files/bug15186.xmc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ASCII XmUGrid Version 2
LOCATIONS 6
POINT 0 987.0 94.0 0.0
POINT 1 968.0 144.0 0.0
POINT 2 959.0 140.0 0.0
POINT 3 994.0 168.0 0.0
POINT 4 910.0 102.0 0.0
POINT 5 898.0 186.0 0.0
CELL_STREAM 30
CELL 0 TRIANGLE 3 2 4 0
CELL 1 TRIANGLE 3 2 0 1
CELL 2 TRIANGLE 3 3 1 0
CELL 3 TRIANGLE 3 5 2 1
CELL 4 TRIANGLE 3 1 3 5
CELL 5 TRIANGLE 3 4 2 5
18 changes: 18 additions & 0 deletions test_files/bug15186a.xmc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ASCII XmUGrid Version 2
LOCATIONS 7
POINT 0 76.8 52.6 0.0
POINT 1 64.0 18.9 0.0
POINT 2 60.2 40.1 0.0
POINT 3 30.9 19.7 0.0
POINT 4 94.6 68.4 0.0
POINT 5 10.1 2.9 0.0
POINT 6 42.0 48.6 0.0
CELL_STREAM 40
CELL 0 TRIANGLE 3 3 5 1
CELL 1 TRIANGLE 3 3 1 2
CELL 2 TRIANGLE 3 4 0 1
CELL 3 TRIANGLE 3 6 3 2
CELL 4 TRIANGLE 3 0 4 6
CELL 5 TRIANGLE 3 5 3 6
CELL 6 TRIANGLE 3 0 2 1
CELL 7 TRIANGLE 3 2 0 6
201 changes: 144 additions & 57 deletions xmsgrid/triangulate/detail/TrAutoFixFourTrianglePts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <xmsgrid/triangulate/TrTin.h>

// 6. Non-shared code headers
#include <xmsgrid/triangulate/triangles.h>

//----- Forward declarations ---------------------------------------------------

Expand Down Expand Up @@ -57,22 +58,19 @@ class TrAutoFixFourTrianglePtsImpl : public TrAutoFixFourTrianglePts
m_noDelete.insert(a_ptIdx.begin(), a_ptIdx.end());
}

void FillAdjTrisIfNeeded();
void GetPtsAndTrisToDelete();
std::pair<int, int> EdgeOppositePt(int a_ptIdx, int a_tri, VecInt& a_tris);
void MakeTwoNewTriangles(VecPt3d& a_pts, std::map<int, int> a_edges, int a_tris[2][3]);
void ReplaceTriangle(int& a_tIdx, int a_newTri[3], VecInt& a_tris);
void MakeTwoNewTriangles(VecPt3d& a_pts, std::map<int, int>& a_edges, VecInt2d& a_tris);
void ReplaceTriangle(int& a_tIdx, VecInt& a_newTri, VecInt& a_tris);
void RenumberPts();
void RenumberTris();
void RemovePts();
void RemoveTris();
void ClearAdjTrisIfCreated();

private:
private:
BSHP<TrTin> m_tin; ///< tin
BSHP<Observer> m_observer; ///< Observer
bool m_removeAdjTris; ///< flag to remove adjacent tris when done
SetInt m_ptsToDelete; ///< points in the TIN that will be deleted
SetInt m_trisToDelete; ///< triangles that will be deleted
SetInt m_noDelete; ///< indexes of points that can't be deleted
Expand All @@ -82,7 +80,11 @@ class TrAutoFixFourTrianglePtsImpl : public TrAutoFixFourTrianglePts

//----- Class / Function definitions -------------------------------------------

////////////////////////////////////////////////////////////////////////////////
static double iTriArea(VecInt& a_tri, VecPt3d& a_pts)
{
return trArea(a_pts[a_tri[0]], a_pts[a_tri[1]], a_pts[a_tri[2]]);
} // iTriArea
////////////////////////////////////////////////////////////////////////////////
/// \class TrAutoFixFourTrianglePtsImpl
/// \brief Used to delete points that are connected to 4 triangles and then
/// retriangulate the void.
Expand All @@ -94,7 +96,6 @@ TrAutoFixFourTrianglePtsImpl::TrAutoFixFourTrianglePtsImpl()
: TrAutoFixFourTrianglePts()
, m_tin()
, m_observer()
, m_removeAdjTris(false)
, m_ptsToDelete()
, m_trisToDelete()
{
Expand All @@ -113,41 +114,56 @@ TrAutoFixFourTrianglePtsImpl::~TrAutoFixFourTrianglePtsImpl()
void TrAutoFixFourTrianglePtsImpl::Fix(BSHP<TrTin> a_tin)
{
m_tin = a_tin;
FillAdjTrisIfNeeded();
GetPtsAndTrisToDelete();
RenumberPts();
RenumberTris();
RemovePts();
RemoveTris();
ClearAdjTrisIfCreated();
} // TrOuterTriangleDeleterImpl::Fix
//------------------------------------------------------------------------------
/// \brief Makes sure the adjacent triangles exist in the TIN
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::FillAdjTrisIfNeeded()
{
VecInt2d& adjTris(m_tin->TrisAdjToPts());
if (adjTris.empty())
{
m_tin->BuildTrisAdjToPts();
m_removeAdjTris = true;
}
} // TrAutoFixFourTrianglePtsImpl::FillAdjTrisIfNeeded
//------------------------------------------------------------------------------
/// \brief Finds and removes the points connected to 4 triangles
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::GetPtsAndTrisToDelete()
{
VecInt2d& adjTris(m_tin->TrisAdjToPts());
VecInt& tris(m_tin->Triangles());
VecPt3d& pts(m_tin->Points());
int npts = static_cast<int>(adjTris.size());
VecInt vPtsToDelete(pts.size(), 0);
VecInt vNoDeletePts(pts.size(), 0);
VecInt vTrisToDelete(m_tin->NumTriangles(), 0);
int npts = static_cast<int>(pts.size());
auto itEnd = m_noDelete.end();
for (int i = 0; i < npts; ++i)
bool done = false;
for (size_t i=0; i<vNoDeletePts.size(); ++i)
{
if (m_noDelete.find((int)i) != m_noDelete.end())
vNoDeletePts[i] = 1;
}
while (!done)
{
auto it = m_noDelete.find(i);
if (4 == adjTris[i].size() && it == itEnd)
m_tin->BuildTrisAdjToPts();
VecInt2d& adjTris(m_tin->TrisAdjToPts());
bool tin_changed = false;
for (int i = 0; i < npts; ++i)
{
if (vPtsToDelete[i] || vNoDeletePts[i])
continue;

if (4 != adjTris[i].size())
continue;

bool skip = false;
for (int j = 0; !skip && j < 4; ++j)
{
if (vTrisToDelete[adjTris[i][j]])
skip = true;
}
if (skip)
continue;

tin_changed = true;
vPtsToDelete[i] = 1;
vTrisToDelete[adjTris[i][2]] = 1;
vTrisToDelete[adjTris[i][3]] = 1;
m_ptsToDelete.insert(i);
m_trisToDelete.insert(adjTris[i][2]);
m_trisToDelete.insert(adjTris[i][3]);
Expand All @@ -156,11 +172,16 @@ void TrAutoFixFourTrianglePtsImpl::GetPtsAndTrisToDelete()
{
mapii.insert(EdgeOppositePt(i, adjTris[i][t], tris));
}
int newTris[2][3];
VecInt2d newTris(2, VecInt(3, -1));
MakeTwoNewTriangles(pts, mapii, newTris);
ReplaceTriangle(adjTris[i][0], newTris[0], tris);
ReplaceTriangle(adjTris[i][1], newTris[1], tris);
VecInt deletedTri(3, i);
ReplaceTriangle(adjTris[i][2], deletedTri, tris);
ReplaceTriangle(adjTris[i][3], deletedTri, tris);
}
if (!tin_changed)
done = true;
}
} // TrAutoFixFourTrianglePtsImpl::RemovePts
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -199,8 +220,8 @@ std::pair<int, int> TrAutoFixFourTrianglePtsImpl::EdgeOppositePt(int a_ptIdx,
/// triangles
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::MakeTwoNewTriangles(VecPt3d& a_pts,
std::map<int, int> a_edges,
int a_tris[2][3])
std::map<int, int>& a_edges,
VecInt2d& a_tris/*[2][3]*/)
{
int bound[4];
auto e = a_edges.begin();
Expand All @@ -209,27 +230,44 @@ void TrAutoFixFourTrianglePtsImpl::MakeTwoNewTriangles(VecPt3d& a_pts,
bound[t] = e->first;
e = a_edges.find(e->second);
}

// is 0,2 closer or 1,3 closer
Pt3d &p0(a_pts[bound[0]]), &p1(a_pts[bound[1]]), &p2(a_pts[bound[2]]), &p3(a_pts[bound[3]]);
double d2_02 = MdistSq(p0.x, p0.y, p2.x, p2.y);
double d2_13 = MdistSq(p1.x, p1.y, p3.x, p3.y);
if (d2_02 < d2_13)
VecInt t0 = {bound[0], bound[1], bound[2]};
double area0 = iTriArea(t0, a_pts);
VecInt t1 = {bound[0], bound[2], bound[3]};
double area1 = iTriArea(t1, a_pts);
VecInt t2 = {bound[0], bound[1], bound[3]};
double area2 = iTriArea(t2, a_pts);
VecInt t3 = {bound[1], bound[2], bound[3]};
double area3 = iTriArea(t3, a_pts);
if (d2_02 < d2_13 && area0 > 0.0 && area1 > 0.0)
{
a_tris[0] = t0;
a_tris[1] = t1;
//a_tris[0][0] = bound[0];
//a_tris[0][1] = bound[1];
//a_tris[0][2] = bound[2];
//a_tris[1][0] = bound[0];
//a_tris[1][1] = bound[2];
//a_tris[1][2] = bound[3];
}
else if (area2 > 0.0 && area3 > 0.0)
{
a_tris[0][0] = bound[0];
a_tris[0][1] = bound[1];
a_tris[0][2] = bound[2];
a_tris[1][0] = bound[0];
a_tris[1][1] = bound[2];
a_tris[1][2] = bound[3];
a_tris[0] = t2;
a_tris[1] = t3;
// a_tris[0][0] = bound[0];
//a_tris[0][1] = bound[1];
//a_tris[0][2] = bound[3];
//a_tris[1][0] = bound[1];
//a_tris[1][1] = bound[2];
//a_tris[1][2] = bound[3];
}
else
{
a_tris[0][0] = bound[0];
a_tris[0][1] = bound[1];
a_tris[0][2] = bound[3];
a_tris[1][0] = bound[1];
a_tris[1][1] = bound[2];
a_tris[1][2] = bound[3];
XM_ASSERT(false); // creating bad triangles
}
} // TrAutoFixFourTrianglePtsImpl::MakeTwoNewTriangles
//------------------------------------------------------------------------------
Expand All @@ -238,7 +276,7 @@ void TrAutoFixFourTrianglePtsImpl::MakeTwoNewTriangles(VecPt3d& a_pts,
/// \param[in] a_newTri : Point indexes that define a new triangle
/// \param[in,out] a_tris : The triangles in the TIN
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::ReplaceTriangle(int& a_tIdx, int a_newTri[3], VecInt& a_tris)
void TrAutoFixFourTrianglePtsImpl::ReplaceTriangle(int& a_tIdx, VecInt& a_newTri/*[3]*/, VecInt& a_tris)
{
int tIdx = a_tIdx * 3;
for (int i = 0; i < 3; ++i)
Expand Down Expand Up @@ -274,9 +312,6 @@ void TrAutoFixFourTrianglePtsImpl::RenumberPts()
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::RenumberTris()
{
if (m_removeAdjTris)
return;

int ntri = static_cast<int>(m_tin->Triangles().size() / 3);
VecInt oldToNewTris(ntri);
auto it = m_trisToDelete.begin();
Expand Down Expand Up @@ -328,17 +363,6 @@ void TrAutoFixFourTrianglePtsImpl::RemoveTris()
for (; it != itEnd; ++it)
tris.erase(tris.begin() + *it);
} // TrAutoFixFourTrianglePtsImpl::RemoveTris
//------------------------------------------------------------------------------
/// \brief Clears the adjacent triangles if this class created them
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsImpl::ClearAdjTrisIfCreated()
{
VecInt2d& adjTris(m_tin->TrisAdjToPts());
adjTris.clear();
if (m_removeAdjTris)
return;
m_tin->BuildTrisAdjToPts();
} // TrAutoFixFourTrianglePtsImpl::ClearAdjTrisIfCreated

////////////////////////////////////////////////////////////////////////////////
/// \class TrAutoFixFourTrianglePts
Expand Down Expand Up @@ -375,6 +399,8 @@ using namespace xms;

#include <xmscore/testing/TestTools.h>
#include <xmsgrid/triangulate/TrTriangulatorPoints.h>
#include <xmsgrid/ugrid/XmUGrid.h>
#include <xmsgrid/ugrid/XmUGridUtils.h>

////////////////////////////////////////////////////////////////////////////////
/// \class TrAutoFixFourTrianglePtsUnitTests
Expand All @@ -398,5 +424,66 @@ void TrAutoFixFourTrianglePtsUnitTests::test1()
TS_ASSERT_EQUALS(4, tin->Points().size());

} // TrOuterTriangleDeleterTests::test1
//------------------------------------------------------------------------------
/// \brief helper function
//------------------------------------------------------------------------------
static BSHP<TrTin> iTinFromUGrid(std::shared_ptr<XmUGrid> a_ug)
{
VecPt3d pp = a_ug->GetLocations();
BSHP<VecPt3d> pts(new VecPt3d());
pts->swap(pp);
int nCell = a_ug->GetCellCount();
BSHP<VecInt> tris(new VecInt(nCell * 3, -1));
VecInt& tt(*tris);
int cnt = -1;
for (int i = 0; i < a_ug->GetCellCount(); ++i)
{
VecInt cell_pts = a_ug->GetCellPoints(i);
tt[++cnt] = cell_pts[0];
tt[++cnt] = cell_pts[1];
tt[++cnt] = cell_pts[2];
}
BSHP<TrTin> tin = TrTin::New();
tin->SetPoints(pts);
tin->SetTriangles(tris);
return tin;
} // iUgToTin
//------------------------------------------------------------------------------
/// \brief Tests TrAutoFixFourTrianglePts.
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsUnitTests::test_bug15186()
{
std::string testFilesPath(XMS_TEST_PATH);
std::string fname = testFilesPath + "bug15186.xmc";
std::shared_ptr<XmUGrid> ug = XmReadUGridFromAsciiFile(fname);
BSHP<TrTin> tin = iTinFromUGrid(ug);

VecInt bPts;
tin->GetBoundaryPoints(bPts);
TrAutoFixFourTrianglePtsImpl p;
p.SetUndeleteablePtIdxs(bPts);
p.Fix(tin);

TS_ASSERT_EQUALS(4, tin->Points().size());
} // TrOuterTriangleDeleterTests::test_bug15186
//------------------------------------------------------------------------------
/// \brief Tests TrAutoFixFourTrianglePts.
//------------------------------------------------------------------------------
void TrAutoFixFourTrianglePtsUnitTests::test_bug15186a()
{
std::string testFilesPath(XMS_TEST_PATH);
std::string fname = testFilesPath + "bug15186a.xmc";
std::shared_ptr<XmUGrid> ug = XmReadUGridFromAsciiFile(fname);
BSHP<TrTin> tin = iTinFromUGrid(ug);

VecInt bPts;
tin->GetBoundaryPoints(bPts);
TrAutoFixFourTrianglePtsImpl p;
p.SetUndeleteablePtIdxs(bPts);
p.Fix(tin);
TS_ASSERT_EQUALS(5, tin->Points().size());
VecInt tris = tin->Triangles();
VecInt base_tris = {0, 1, 4, 0, 4, 3, 0, 2, 1, 2, 4, 1};
TS_ASSERT_EQUALS_VEC(base_tris, tris);
} // TrOuterTriangleDeleterTests::test_bug15186a
#endif // CXX_TEST
2 changes: 2 additions & 0 deletions xmsgrid/triangulate/detail/TrAutoFixFourTrianglePts.t.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class TrAutoFixFourTrianglePtsUnitTests : public CxxTest::TestSuite
{
public:
void test1();
void test_bug15186();
void test_bug15186a();
}; // class TrAutoFixFourTrianglePtsUnitTests

#endif

0 comments on commit fc807f9

Please sign in to comment.