Skip to content

Commit

Permalink
Speed up the tile mesher when using constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
gwaldron committed Oct 4, 2023
1 parent 81dc981 commit 38e86dd
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 17 deletions.
50 changes: 38 additions & 12 deletions src/osgEarth/TileMesher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,9 @@ TileMesher::createMeshWithConstraints(
std::unordered_set<weemesh::triangle_t*> insiders;
std::unordered_set<weemesh::triangle_t*> insiders_to_remove;
std::unordered_set<weemesh::triangle_t*> outsiders_to_possibly_remove;
weemesh::vert_t centroid;
const double one_third = 1.0 / 3.0;
std::vector<weemesh::triangle_t*> tris;

for (auto& edit : edits)
{
Expand All @@ -593,26 +596,49 @@ TileMesher::createMeshWithConstraints(

// Note: the part was already transformed in a previous step.

if (part->isPolygon() && part->getBounds().intersects(localBounds))
auto& bb = part->getBounds();
if (part->isPolygon() && bb.intersects(localBounds))
{
for (auto& tri_iter : mesh._triangles)
if (edit.removeExterior)
{
weemesh::triangle_t& tri = tri_iter.second;
weemesh::vert_t c = (tri.p0 + tri.p1 + tri.p2) * (1.0 / 3.0);
// expensive path, much check ALL triangles when removing exterior.
for (auto& tri_iter : mesh._triangles)
{
weemesh::triangle_t* tri = &tri_iter.second;

bool inside = part->contains2D(c.x(), c.y());
bool inside = part->contains2D(tri->centroid.x(), tri->centroid.y());

if (inside)
{
insiders.insert(&tri);
if (edit.removeInterior)
if (inside)
{
insiders_to_remove.insert(&tri);
insiders.insert(tri);
if (edit.removeInterior)
{
insiders_to_remove.insert(tri);
}
}
else if (edit.removeExterior)
{
outsiders_to_possibly_remove.insert(tri);
}
}
else if (edit.removeExterior)
}
else
{
// fast path when we are NOT removing exterior tris.
mesh.get_triangles(bb.xMin(), bb.yMin(), bb.xMax(), bb.yMax(), tris);

for (auto tri : tris)
{
outsiders_to_possibly_remove.insert(&tri);
bool inside = part->contains2D(tri->centroid.x(), tri->centroid.y());

if (inside)
{
insiders.insert(tri);
if (edit.removeInterior)
{
insiders_to_remove.insert(tri);
}
}
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/osgEarth/rtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ template<class DATATYPE, class ELEMTYPE, int NUMDIMS,
/// \param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
/// \param a_context User context to pass as parameter to a_resultCallback
/// \return Returns the number of entries found
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], std::function<bool(const DATATYPE&)> callback) const;
using DefaultCallbackType = std::function<bool(const DATATYPE&)>;
template<typename CALLBACK_TYPE = DefaultCallbackType>
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS],
CALLBACK_TYPE callback = [&](const DATATYPE&) { return true; }) const;

/// Remove all entries from tree
void RemoveAll();
Expand Down Expand Up @@ -361,7 +364,8 @@ template<class DATATYPE, class ELEMTYPE, int NUMDIMS,
void FreeListNode(ListNode* a_listNode);
bool Overlap(Rect* a_rectA, Rect* a_rectB) const;
void ReInsert(Node* a_node, ListNode** a_listNode);
bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::function<bool(const DATATYPE&)> callback) const;
template<typename CALLBACK_TYPE>
bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, CALLBACK_TYPE callback) const;
void RemoveAllRec(Node* a_node);
void Reset();
void CountRec(Node* a_node, int& a_count);
Expand Down Expand Up @@ -541,7 +545,8 @@ void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMD


RTREE_TEMPLATE
int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], std::function<bool(const DATATYPE&)> callback) const
template<typename CALLBACK_TYPE>
int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], CALLBACK_TYPE callback) const
{
#ifdef _DEBUG
for (int index = 0; index < NUMDIMS; ++index)
Expand Down Expand Up @@ -1612,7 +1617,8 @@ void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)

// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
RTREE_TEMPLATE
bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::function<bool(const DATATYPE&)> callback) const
template<typename CALLBACK_TYPE>
bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, CALLBACK_TYPE callback) const
{
ASSERT(a_node);
ASSERT(a_node->m_level >= 0);
Expand Down Expand Up @@ -1643,7 +1649,7 @@ bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::func
DATATYPE& id = a_node->m_branch[index].m_data;
++a_foundCount;

if (callback && !callback(id))
if (!callback(id))
{
return false; // Don't continue searching
}
Expand Down
16 changes: 16 additions & 0 deletions src/osgEarth/weemesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ namespace weemesh
{
UID uid; // unique id
vert_t p0, p1, p2; // vertices
vert_t centroid;
unsigned i0, i1, i2; // indices
vert_t::value_type a_min[2]; // bbox min
vert_t::value_type a_max[2]; // bbox max
Expand Down Expand Up @@ -276,6 +277,8 @@ namespace weemesh
++_num_edits;
}

const double one_third = 1.0 / 3.0;

// add new triangle to the mesh from 3 indices
UID add_triangle(int i0, int i1, int i2)
{
Expand All @@ -295,6 +298,7 @@ namespace weemesh
tri.a_min[1] = std::min(tri.p0.y(), std::min(tri.p1.y(), tri.p2.y()));
tri.a_max[0] = std::max(tri.p0.x(), std::max(tri.p1.x(), tri.p2.x()));
tri.a_max[1] = std::max(tri.p0.y(), std::max(tri.p1.y(), tri.p2.y()));
tri.centroid = (tri.p0 + tri.p1 + tri.p2) * one_third;

// "2d_degenerate" means that either a) at least 2 points are coincident, or
// b) at least two edges are basically coincident (in the XY plane)
Expand Down Expand Up @@ -365,6 +369,18 @@ namespace weemesh
return index;
}

// fetch a pointer to each triangle that intersects the bounding box
unsigned get_triangles(vert_t::value_type xmin, vert_t::value_type ymin, vert_t::value_type xmax, vert_t::value_type ymax,
std::vector<triangle_t*>& output)
{
output.clear();
vert_t::value_type a_min[2] = { xmin, ymin };
vert_t::value_type a_max[2] = { xmax, ymax };
_spatial_index.Search(a_min, a_max, [&](const UID& uid) {
output.emplace_back(&_triangles[uid]); return true; });
return output.size();
}

// insert a point into the mesh, cutting triangles as necessary
void insert(const vert_t& vert, int marker)
{
Expand Down

0 comments on commit 38e86dd

Please sign in to comment.