Commit d27c282b authored by Jan Möbius's avatar Jan Möbius
Browse files

Added patch to speed up add_face function. Thanks to Stephen Webb

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@406 fdac6126-5c0c-442c-9429-916003d36597
parent 025b9629
...@@ -109,40 +109,26 @@ void PolyConnectivity::adjust_outgoing_halfedge(VertexHandle _vh) ...@@ -109,40 +109,26 @@ void PolyConnectivity::adjust_outgoing_halfedge(VertexHandle _vh)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
namespace
{
template <class _Handle>
struct NextCacheEntryT : public std::pair<_Handle, _Handle>
{
typedef std::pair<_Handle, _Handle> Base;
NextCacheEntryT(_Handle _heh0, _Handle _heh1)
: Base(_heh0, _heh1)
{
assert(_heh0.is_valid());
assert(_heh1.is_valid());
}
};
}
PolyConnectivity::FaceHandle PolyConnectivity::FaceHandle
PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
{ {
VertexHandle vh; VertexHandle vh;
uint i, ii, n(_vhs_size), id; uint i, ii, n(_vhs_size), id;
std::vector<HalfedgeHandle> halfedge_handles(n);
std::vector<bool> is_new(n), needs_adjust(n, false);
HalfedgeHandle inner_next, inner_prev, HalfedgeHandle inner_next, inner_prev,
outer_next, outer_prev, outer_next, outer_prev,
boundary_next, boundary_prev, boundary_next, boundary_prev,
patch_start, patch_end; patch_start, patch_end;
// cache for set_next_halfedge and vertex' set_halfedge
typedef NextCacheEntryT<HalfedgeHandle> NextCacheEntry;
typedef std::vector<NextCacheEntry> NextCache;
NextCache next_cache; // Check sufficient working storage available
next_cache.reserve(3*n); if (edgeData_.size() < n)
{
edgeData_.resize(n);
next_cache_.resize(6*n);
}
next_cache_count_ = 0;
// don't allow degenerated faces // don't allow degenerated faces
assert (n > 2); assert (n > 2);
...@@ -155,11 +141,13 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) ...@@ -155,11 +141,13 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
return InvalidFaceHandle; return InvalidFaceHandle;
} }
halfedge_handles[i] = find_halfedge(_vertex_handles[i], // Initialise edge attributes
_vertex_handles[ii]); edgeData_[i].halfedge_handle = find_halfedge(_vertex_handles[i],
is_new[i] = !halfedge_handles[i].is_valid(); _vertex_handles[ii]);
edgeData_[i].is_new = !edgeData_[i].halfedge_handle.is_valid();
edgeData_[i].needs_adjust = false;
if (!is_new[i] && !is_boundary(halfedge_handles[i])) if (!edgeData_[i].is_new && !is_boundary(edgeData_[i].halfedge_handle))
{ {
omerr() << "PolyMeshT::add_face: complex edge\n"; omerr() << "PolyMeshT::add_face: complex edge\n";
return InvalidFaceHandle; return InvalidFaceHandle;
...@@ -169,10 +157,11 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) ...@@ -169,10 +157,11 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
// re-link patches if necessary // re-link patches if necessary
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
{ {
if (!is_new[i] && !is_new[ii]) if (!edgeData_[i].is_new && !edgeData_[ii].is_new)
{ {
inner_prev = halfedge_handles[i]; inner_prev = edgeData_[i].halfedge_handle;
inner_next = halfedge_handles[ii]; inner_next = edgeData_[ii].halfedge_handle;
if (next_halfedge_handle(inner_prev) != inner_next) if (next_halfedge_handle(inner_prev) != inner_next)
{ {
...@@ -202,32 +191,34 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) ...@@ -202,32 +191,34 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
patch_end = prev_halfedge_handle(inner_next); patch_end = prev_halfedge_handle(inner_next);
// relink // relink
next_cache.push_back(NextCacheEntry(boundary_prev, patch_start)); next_cache_[next_cache_count_++] = std::make_pair(boundary_prev, patch_start);
next_cache.push_back(NextCacheEntry(patch_end, boundary_next)); next_cache_[next_cache_count_++] = std::make_pair(patch_end, boundary_next);
next_cache.push_back(NextCacheEntry(inner_prev, inner_next)); next_cache_[next_cache_count_++] = std::make_pair(inner_prev, inner_next);
} }
} }
} }
// create missing edges // create missing edges
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
if (is_new[i]) if (edgeData_[i].is_new)
halfedge_handles[i] = new_edge(_vertex_handles[i], _vertex_handles[ii]); edgeData_[i].halfedge_handle = new_edge(_vertex_handles[i], _vertex_handles[ii]);
// create the face // create the face
FaceHandle fh(new_face()); FaceHandle fh(new_face());
set_halfedge_handle(fh, halfedge_handles[n-1]); set_halfedge_handle(fh, edgeData_[n-1].halfedge_handle);
// setup halfedges // setup halfedges
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
{ {
vh = _vertex_handles[ii]; vh = _vertex_handles[ii];
inner_prev = halfedge_handles[i];
inner_next = halfedge_handles[ii]; inner_prev = edgeData_[i].halfedge_handle;
inner_next = edgeData_[ii].halfedge_handle;
id = 0; id = 0;
if (is_new[i]) id |= 1; if (edgeData_[i].is_new) id |= 1;
if (is_new[ii]) id |= 2; if (edgeData_[ii].is_new) id |= 2;
if (id) if (id)
{ {
...@@ -239,13 +230,13 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) ...@@ -239,13 +230,13 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
{ {
case 1: // prev is new, next is old case 1: // prev is new, next is old
boundary_prev = prev_halfedge_handle(inner_next); boundary_prev = prev_halfedge_handle(inner_next);
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next)); next_cache_[next_cache_count_++] = std::make_pair(boundary_prev, outer_next);
set_halfedge_handle(vh, outer_next); set_halfedge_handle(vh, outer_next);
break; break;
case 2: // next is new, prev is old case 2: // next is new, prev is old
boundary_next = next_halfedge_handle(inner_prev); boundary_next = next_halfedge_handle(inner_prev);
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next)); next_cache_[next_cache_count_++] = std::make_pair(outer_prev, boundary_next);
set_halfedge_handle(vh, boundary_next); set_halfedge_handle(vh, boundary_next);
break; break;
...@@ -253,35 +244,36 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size) ...@@ -253,35 +244,36 @@ PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
if (!halfedge_handle(vh).is_valid()) if (!halfedge_handle(vh).is_valid())
{ {
set_halfedge_handle(vh, outer_next); set_halfedge_handle(vh, outer_next);
next_cache.push_back(NextCacheEntry(outer_prev, outer_next)); next_cache_[next_cache_count_++] = std::make_pair(outer_prev, outer_next);
} }
else else
{ {
boundary_next = halfedge_handle(vh); boundary_next = halfedge_handle(vh);
boundary_prev = prev_halfedge_handle(boundary_next); boundary_prev = prev_halfedge_handle(boundary_next);
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next)); next_cache_[next_cache_count_++] = std::make_pair(boundary_prev, outer_next);
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next)); next_cache_[next_cache_count_++] = std::make_pair(outer_prev, boundary_next);
} }
break; break;
} }
// set inner link // set inner link
next_cache.push_back(NextCacheEntry(inner_prev, inner_next)); next_cache_[next_cache_count_++] = std::make_pair(inner_prev, inner_next);
} }
else needs_adjust[ii] = (halfedge_handle(vh) == inner_next); else edgeData_[ii].needs_adjust = (halfedge_handle(vh) == inner_next);
// set face handle // set face handle
set_face_handle(halfedge_handles[i], fh); set_face_handle(edgeData_[i].halfedge_handle, fh);
} }
// process next halfedge cache // process next halfedge cache
NextCache::const_iterator ncIt(next_cache.begin()), ncEnd(next_cache.end()); for (i = 0; i < next_cache_count_; ++i)
for (; ncIt != ncEnd; ++ncIt) set_next_halfedge_handle(next_cache_[i].first, next_cache_[i].second);
set_next_halfedge_handle(ncIt->first, ncIt->second);
// adjust vertices' halfedge handle // adjust vertices' halfedge handle
for (i=0; i<n; ++i) for (i=0; i<n; ++i)
if (needs_adjust[i]) if (edgeData_[i].needs_adjust)
adjust_outgoing_halfedge(_vertex_handles[i]); adjust_outgoing_halfedge(_vertex_handles[i]);
return fh; return fh;
......
...@@ -689,6 +689,20 @@ protected: ...@@ -689,6 +689,20 @@ protected:
void collapse_edge(HalfedgeHandle _hh); void collapse_edge(HalfedgeHandle _hh);
/// Helper for halfedge collapse /// Helper for halfedge collapse
void collapse_loop(HalfedgeHandle _hh); void collapse_loop(HalfedgeHandle _hh);
private: // Working storage for add_face()
struct AddFaceEdgeInfo
{
HalfedgeHandle halfedge_handle;
bool is_new;
bool needs_adjust;
};
std::vector<AddFaceEdgeInfo> edgeData_; //
std::vector<std::pair<HalfedgeHandle, HalfedgeHandle> > next_cache_; // cache for set_next_halfedge and vertex' set_halfedge
uint next_cache_count_;
}; };
}//namespace OpenMesh }//namespace OpenMesh
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment