diff --git a/Doc/changelog.docu b/Doc/changelog.docu
index 56f07847..820466d7 100644
--- a/Doc/changelog.docu
+++ b/Doc/changelog.docu
@@ -9,6 +9,11 @@
| 6.0 (?/?/?) |
+Core
+
+- Added a couple of methods to enable more efficient adding of batches of vertices (Without resizing property vectors)
+
+
IO
- Obj reader: added texCoord3d functions to objloader
diff --git a/src/OpenMesh/Core/Mesh/ArrayKernel.hh b/src/OpenMesh/Core/Mesh/ArrayKernel.hh
index b83b2e1e..388c9267 100644
--- a/src/OpenMesh/Core/Mesh/ArrayKernel.hh
+++ b/src/OpenMesh/Core/Mesh/ArrayKernel.hh
@@ -209,6 +209,15 @@ public:
public:
+ /**
+ * \brief Add a new vertex.
+ *
+ * If you are rebuilding a mesh that you previously erased using clean() or
+ * clean_keep_reservation() you probably want to use new_vertex_dirty()
+ * instead.
+ *
+ * \sa new_vertex_dirty()
+ */
inline VertexHandle new_vertex()
{
vertices_.push_back(Vertex());
@@ -217,6 +226,24 @@ public:
return handle(vertices_.back());
}
+ /**
+ * Same as new_vertex() but uses PropertyContainer::resize_if_smaller() to
+ * resize the vertex property container.
+ *
+ * If you are rebuilding a mesh that you erased with clean() or
+ * clean_keep_reservation() using this method instead of new_vertex() saves
+ * reallocation and reinitialization of property memory.
+ *
+ * \sa new_vertex()
+ */
+ inline VertexHandle new_vertex_dirty()
+ {
+ vertices_.push_back(Vertex());
+ vprops_resize_if_smaller(n_vertices());//TODO:should it be push_back()?
+
+ return handle(vertices_.back());
+ }
+
inline HalfedgeHandle new_edge(VertexHandle _start_vh, VertexHandle _end_vh)
{
// assert(_start_vh != _end_vh);
@@ -294,23 +321,26 @@ public:
std_API_Container_FHandlePointer& fh_to_update,
bool _v=true, bool _e=true, bool _f=true);
- /** \brief Clear the whole mesh
- *
- * This will remove all properties and elements from the mesh
- */
+ /// \brief Does the same as clean() and in addition erases all properties.
void clear();
- /** \brief Reset the whole mesh
+ /** \brief Remove all vertices, edges and faces and deallocates their memory.
*
- * This will remove all elements from the mesh but keeps the properties
+ * In contrast to clear() this method does neither erases the properties
+ * nor clears the property vectors. Depending on how you add any new entities
+ * to the mesh after calling this method, your properties will be initialized
+ * with old values.
+ *
+ * \sa clean_keep_reservation()
*/
void clean();
- /** \brief Reset the whole mesh
+ /** \brief Remove all vertices, edges and faces but keep memory allocated.
*
- * This will remove all elements from the mesh but keeps the properties.
- * In contrast to clean() the memory used for the elements will remain
- * allocated.
+ * This method behaves like clean() (also regarding the properties) but
+ * leaves the memory used for vertex, edge and face storage allocated. This
+ * leads to no reduction in memory consumption but allows for faster
+ * performance when rebuilding the mesh.
*/
void clean_keep_reservation();
@@ -479,6 +509,16 @@ public:
StatusInfo& status(VertexHandle _vh)
{ return property(vertex_status_, _vh); }
+ /**
+ * Reinitializes the status of all vertices using the StatusInfo default
+ * constructor, i.e. all flags will be set to false.
+ */
+ void reset_status() {
+ PropertyT &status_prop = property(vertex_status_);
+ PropertyT::vector_type &sprop_v = status_prop.data_vector();
+ std::fill(sprop_v.begin(), sprop_v.begin() + n_vertices(), StatusInfo());
+ }
+
//----------------------------------------------------------- halfedge status
const StatusInfo& status(HalfedgeHandle _hh) const
{ return property(halfedge_status_, _hh); }
diff --git a/src/OpenMesh/Core/Mesh/BaseKernel.hh b/src/OpenMesh/Core/Mesh/BaseKernel.hh
index 9c6d95af..9a452916 100644
--- a/src/OpenMesh/Core/Mesh/BaseKernel.hh
+++ b/src/OpenMesh/Core/Mesh/BaseKernel.hh
@@ -646,11 +646,26 @@ public: //----------------------------------------------------- element numbers
protected: //------------------------------------------- synchronize properties
+ /// Reserves space for \p _n elements in all vertex property vectors.
void vprops_reserve(size_t _n) const { vprops_.reserve(_n); }
+
+ /// Resizes all vertex property vectors to the specified size.
void vprops_resize(size_t _n) const { vprops_.resize(_n); }
+
+ /**
+ * Same as vprops_resize() but ignores vertex property vectors that have
+ * a size larger than \p _n.
+ *
+ * Use this method instead of vprops_resize() if you plan to frequently reduce
+ * and enlarge the property container and you don't want to waste time
+ * reallocating the property vectors every time.
+ */
+ void vprops_resize_if_smaller(size_t _n) const { vprops_.resize_if_smaller(_n); }
+
void vprops_clear() {
vprops_.clear();
}
+
void vprops_swap(unsigned int _i0, unsigned int _i1) const {
vprops_.swap(_i0, _i1);
}
diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh
index 9ea65535..04e87def 100644
--- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh
+++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh
@@ -192,10 +192,21 @@ public:
Use them to assign two meshes of \b equal type.
If the mesh types vary, use PolyMeshT::assign() instead. */
- // --- creation ---
+ // --- creation ---
+
+ /**
+ * \brief Adds a new default-initialized vertex.
+ *
+ * \sa new_vertex(const Point&), new_vertex_dirty()
+ */
inline VertexHandle new_vertex()
{ return Kernel::new_vertex(); }
+ /**
+ * \brief Adds a new vertex initialized to a custom position.
+ *
+ * \sa new_vertex(), new_vertex_dirty()
+ */
inline VertexHandle new_vertex(const Point& _p)
{
VertexHandle vh(Kernel::new_vertex());
@@ -203,9 +214,32 @@ public:
return vh;
}
+ /**
+ * Same as new_vertex(const Point&) but never shrinks, only enlarges the
+ * vertex property vectors.
+ *
+ * If you are rebuilding a mesh that you erased with ArrayKernel::clean() or
+ * ArrayKernel::clean_keep_reservation() using this method instead of
+ * new_vertex(const Point &) saves reallocation and reinitialization of
+ * property memory.
+ *
+ * \sa new_vertex(const Point &)
+ */
+ inline VertexHandle new_vertex_dirty(const Point& _p)
+ {
+ VertexHandle vh(Kernel::new_vertex_dirty());
+ this->set_point(vh, _p);
+ return vh;
+ }
+
+ /// Alias for new_vertex(const Point&).
inline VertexHandle add_vertex(const Point& _p)
{ return new_vertex(_p); }
+ /// Alias for new_vertex_dirty().
+ inline VertexHandle add_vertex_dirty(const Point& _p)
+ { return new_vertex_dirty(_p); }
+
// --- normal vectors ---
/** \name Normal vector computation
diff --git a/src/OpenMesh/Core/Utils/PropertyContainer.hh b/src/OpenMesh/Core/Utils/PropertyContainer.hh
index 1b5ec1c1..53584bb2 100644
--- a/src/OpenMesh/Core/Utils/PropertyContainer.hh
+++ b/src/OpenMesh/Core/Utils/PropertyContainer.hh
@@ -200,17 +200,83 @@ public:
//---------------------------------------------------- synchronize properties
+/*
+ * In C++11 an beyond we can introduce more efficient and more legible
+ * implementations of the following methods.
+ */
+#if (_MSC_VER >= 1900 || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
+ /**
+ * Reserves space for \p _n elements in all property vectors.
+ */
+ void reserve(size_t _n) const {
+ std::for_each(properties_.begin(), properties_.end(),
+ [_n](BaseProperty* p) { if (p) p->reserve(_n); });
+ }
+
+ /**
+ * Resizes all property vectors to the specified size.
+ */
+ void resize(size_t _n) const {
+ std::for_each(properties_.begin(), properties_.end(),
+ [_n](BaseProperty* p) { if (p) p->resize(_n); });
+ }
+
+ /**
+ * Same as resize() but ignores property vectors that have a size larger
+ * than \p _n.
+ *
+ * Use this method instead of resize() if you plan to frequently reduce
+ * and enlarge the property container and you don't want to waste time
+ * reallocating the property vectors every time.
+ */
+ void resize_if_smaller(size_t _n) const {
+ std::for_each(properties_.begin(), properties_.end(),
+ [_n](BaseProperty* p) { if (p && p->n_elements() < _n) p->resize(_n); });
+ }
+
+ /**
+ * Swaps the items with index \p _i0 and index \p _i1 in all property
+ * vectors.
+ */
+ void swap(size_t _i0, size_t _i1) const {
+ std::for_each(properties_.begin(), properties_.end(),
+ [_i0, _i1](BaseProperty* p) { if (p) p->swap(_i0, _i1); });
+ }
+#else
+ /**
+ * Reserves space for \p _n elements in all property vectors.
+ */
void reserve(size_t _n) const {
std::for_each(properties_.begin(), properties_.end(), Reserve(_n));
}
+ /**
+ * Resizes all property vectors to the specified size.
+ */
void resize(size_t _n) const {
std::for_each(properties_.begin(), properties_.end(), Resize(_n));
}
+ /**
+ * Same as \sa resize() but ignores property vectors that have a size
+ * larger than \p _n.
+ *
+ * Use this method instead of \sa resize() if you plan to frequently reduce
+ * and enlarge the property container and you don't want to waste time
+ * reallocating the property vectors every time.
+ */
+ void resize_if_smaller(size_t _n) const {
+ std::for_each(properties_.begin(), properties_.end(), ResizeIfSmaller(_n));
+ }
+
+ /**
+ * Swaps the items with index \p _i0 and index \p _i1 in all property
+ * vectors.
+ */
void swap(size_t _i0, size_t _i1) const {
std::for_each(properties_.begin(), properties_.end(), Swap(_i0, _i1));
}
+#endif
@@ -273,6 +339,13 @@ private:
size_t n_;
};
+ struct ResizeIfSmaller
+ {
+ ResizeIfSmaller(size_t _n) : n_(_n) {}
+ void operator()(BaseProperty* _p) const { if (_p && _p->n_elements() < n_) _p->resize(n_); }
+ size_t n_;
+ };
+
struct ClearAll
{
ClearAll() {}
|