From 464c0ec3df16cf7aa23cb5bc5864a8a31ca32fd8 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 27 Dec 2013 21:12:53 -0500 Subject: [PATCH] Added a separate component for dealing with vertex reindexing --- openscad.pro | 1 + src/Reindexer.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cgalutils.cc | 34 +++++++++++++------------ 3 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 src/Reindexer.h diff --git a/openscad.pro b/openscad.pro index a86be5ab..627c4a0e 100644 --- a/openscad.pro +++ b/openscad.pro @@ -375,6 +375,7 @@ cgal { HEADERS += src/cgal.h \ src/cgalfwd.h \ src/cgalutils.h \ + src/Reindexer.h \ src/CGALCache.h \ src/CGALRenderer.h \ src/CGAL_Nef_polyhedron.h \ diff --git a/src/Reindexer.h b/src/Reindexer.h new file mode 100644 index 00000000..8ae000e9 --- /dev/null +++ b/src/Reindexer.h @@ -0,0 +1,66 @@ +#ifndef REINDEXER_H_ +#define REINDEXER_H_ + +#include +#include +#include +#include + +/*! + Reindexes a collection of elements of type T. + Typically used to compress an element array by creating and reusing indexes to + a new array or to merge two index tables to two arrays into a common index. + The latter is necessary for VBO's or for unifying texture coordinate indices to + multiple texture coordinate arrays. +*/ +template +class Reindexer +{ +public: + /*! + Looks up a value. Will insert the value if it doesn't already exist. + Returns the new index. */ + int lookup(const T &val) { + typename boost::unordered_map::const_iterator iter = this->map.find(val); + if (iter != this->map.end()) return iter->second; + else { + this->map.insert(std::make_pair(val, this->map.size())); + return this->map.size() - 1; + } + } + + /*! + Returns the current size of the new element array + */ + std::size_t size() const { + return this->map.size(); + } + + /*! + Return the new element array. + */ + const T *getArray() { + this->vec.resize(this->map.size()); + typename boost::unordered_map::const_iterator iter = this->map.begin(); + while (iter != this->map.end()) { + this->vec[iter->second] = iter->first; + iter++; + } + return &this->vec[0]; + } + + /*! + Copies the internal vector to the given destination + */ + void copy(std::vector &dest) { + this->getArray(); + dest.resize(this->vec.size()); + std::copy(this->vec.begin(), this->vec.end(), dest.begin()); + } + +private: + boost::unordered_map map; + std::vector vec; +}; + +#endif diff --git a/src/cgalutils.cc b/src/cgalutils.cc index acb14e92..ecbda0b7 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -10,6 +10,7 @@ #include "cgal.h" #include #include "svg.h" +#include "Reindexer.h" #include #include @@ -261,10 +262,18 @@ bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps) #undef GEN_SURFACE_DEBUG +namespace Eigen { + size_t hash_value(Vector3d const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } +} + class CGAL_Build_PolySet : public CGAL::Modifier_base { public: - typedef CGAL_HDS::Vertex::Point CGALPoint; + typedef CGAL_Polybuilder::Point_3 CGALPoint; const PolySet &ps; CGAL_Build_PolySet(const PolySet &ps) : ps(ps) { } @@ -273,8 +282,7 @@ public: { CGAL_Polybuilder B(hds, true); typedef boost::tuple BuilderVertex; - typedef std::map BuilderMap; - BuilderMap vertices; + Reindexer vertices; std::vector indices(3); // Estimating same # of vertices as polygons (very rough) @@ -285,14 +293,11 @@ public: if (pidx++ > 0) printf(","); indices.clear(); BOOST_FOREACH(const Vector3d &v, p) { - size_t idx; - BuilderVertex bv = boost::make_tuple(v[0], v[1], v[2]); - if (vertices.count(bv) > 0) indices.push_back(vertices[bv]); - else { - indices.push_back(vertices.size()); - vertices[bv] = vertices.size(); - B.add_vertex(CGALPoint(v[0], v[1], v[2])); - } + size_t s = vertices.size(); + size_t idx = vertices.lookup(v); + // If we added a vertex, also add it to the CGAL builder + if (idx == s) B.add_vertex(CGALPoint(v[0], v[1], v[2])); + indices.push_back(idx); } std::map fc; bool facet_is_degenerate = false; @@ -317,13 +322,10 @@ public: printf("],\n"); printf("points=["); - int vidx = 0; for (int vidx=0;vidx 0) printf(","); - const BuilderMap::const_iterator it = - std::find_if(vertices.begin(), vertices.end(), - boost::bind(&BuilderMap::value_type::second, _1) == vidx); - printf("[%g,%g,%g]", it->first.get<0>(), it->first.get<1>(), it->first.get<2>()); + const Vector3d &v = vertices.getArray()[vidx]; + printf("[%g,%g,%g]", v[0], v[1], v[2]); } printf("]);\n"); }