Developer Documentation
GeometryKernel.hh
1 /*===========================================================================*\
2  * *
3  * OpenVolumeMesh *
4  * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
5  * www.openvolumemesh.org *
6  * *
7  *---------------------------------------------------------------------------*
8  * This file is part of OpenVolumeMesh. *
9  * *
10  * OpenVolumeMesh is free software: you can redistribute it and/or modify *
11  * it under the terms of the GNU Lesser General Public License as *
12  * published by the Free Software Foundation, either version 3 of *
13  * the License, or (at your option) any later version with the *
14  * following exceptions: *
15  * *
16  * If other files instantiate templates or use macros *
17  * or inline functions from this file, or you compile this file and *
18  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenVolumeMesh is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenVolumeMesh. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 #ifndef GEOMETRYKERNEL_HH_
36 #define GEOMETRYKERNEL_HH_
37 
38 #include <cassert>
39 #include <iostream>
40 #include <type_traits>
41 
42 #include "../Geometry/VectorT.hh"
43 #include "TopologyKernel.hh"
44 
45 namespace OpenVolumeMesh {
46 
47 template <class VecT, class TopologyKernelT = TopologyKernel>
48 class GeometryKernel : public TopologyKernelT {
49 public:
50 
51  typedef VecT PointT;
52  typedef TopologyKernelT KernelT;
53 
55  GeometryKernel() = default;
56 
58  ~GeometryKernel() override = default;
59 
60  template<class OtherTopoKernel>
61  void assign(const GeometryKernel<VecT, OtherTopoKernel> *other) {
62  TopologyKernelT::assign(other);
63  other->clone_vertices(vertices_);
64  }
65 
67  VertexHandle add_vertex() override { return add_vertex(VecT()); }
68 
70  VertexHandle add_vertex(const VecT& _p) {
71 
72  // Store vertex in list
73  vertices_.push_back(_p);
74 
75  // Get handle of recently created vertex
76  return KernelT::add_vertex();
77  }
78 
80  void set_vertex(const VertexHandle& _vh, const VecT& _p) {
81 
82  assert(_vh.idx() < (int)vertices_.size());
83 
84  vertices_[_vh.uidx()] = _p;
85  }
86 
88  const VecT& vertex(const VertexHandle& _vh) const {
89  return vertices_[_vh.uidx()];
90  }
91 
92  VertexIter delete_vertex(const VertexHandle& _h) override {
93  assert(_h.idx() < (int)TopologyKernelT::n_vertices());
94 
95  VertexIter nV = TopologyKernelT::delete_vertex(_h);
96 
97  if (TopologyKernelT::deferred_deletion_enabled())
98  {
99 
100  }
101  else
102  vertices_.erase(vertices_.begin() + _h.idx());
103 
104  return nV;
105  }
106 
107  void collect_garbage() override
108  {
109  if (!TopologyKernelT::needs_garbage_collection())
110  return;
111 
112  if (TopologyKernelT::fast_deletion_enabled()) {
113  TopologyKernelT::collect_garbage();
114  vertices_.resize(TopologyKernel::n_vertices());
115  } else {
116  for (int i = (int)vertices_.size(); i > 0; --i)
117  if (TopologyKernelT::is_deleted(VertexHandle(i-1)))
118  {
119  vertices_.erase(vertices_.begin() + (i-1));
120  }
121  TopologyKernelT::collect_garbage();
122  }
123 
124  }
125 
126  void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2) override
127  {
128  assert(_h1.idx() >= 0 && _h1.idx() < (int)vertices_.size());
129  assert(_h2.idx() >= 0 && _h2.idx() < (int)vertices_.size());
130 
131  if (_h1 == _h2)
132  return;
133 
134  std::swap(vertices_[_h1.uidx()], vertices_[_h2.uidx()]);
135 
136  TopologyKernelT::swap_vertex_indices(_h1, _h2);
137  }
138 
139 protected:
140 
141  void delete_multiple_vertices(const std::vector<bool>& _tag) override{
142 
143  assert(_tag.size() == TopologyKernelT::n_vertices());
144 
145  std::vector<VecT> newVertices;
146 
147  typename std::vector<VecT>::const_iterator v_it = vertices_.begin();
148 
149  for(std::vector<bool>::const_iterator t_it = _tag.begin(),
150  t_end = _tag.end(); t_it != t_end; ++t_it, ++v_it) {
151 
152  if(!(*t_it)) {
153  // Not marked as deleted
154 
155  newVertices.push_back(*v_it);
156  }
157  }
158 
159  // Swap vertices
160  vertices_.swap(newVertices);
161 
162  TopologyKernelT::delete_multiple_vertices(_tag);
163  }
164 
165 public:
166 
167  void clear(bool _clearProps = true) override {
168 
169  vertices_.clear();
170  TopologyKernelT::clear(_clearProps);
171  }
172 
173  typename PointT::value_type length(const HalfEdgeHandle& _heh) const {
174  return vector(_heh).length();
175  }
176 
177  typename PointT::value_type length(const EdgeHandle& _eh) const {
178  return vector(_eh).length();
179  }
180 
181  PointT vector(const HalfEdgeHandle& _heh) const {
182 
183  const typename TopologyKernelT::Edge& e = TopologyKernelT::halfedge(_heh);
184  return (vertex(e.to_vertex()) - vertex(e.from_vertex()));
185  }
186 
187  PointT vector(const EdgeHandle& _eh) const {
188 
189  const typename TopologyKernelT::Edge& e = TopologyKernelT::edge(_eh);
190  return (vertex(e.to_vertex()) - vertex(e.from_vertex()));
191  }
192 
193  PointT barycenter(const EdgeHandle& _eh) const {
194  return PointT(0.5 * vertex(TopologyKernelT::edge(_eh).from_vertex()) +
195  0.5 * vertex(TopologyKernelT::edge(_eh).to_vertex()));
196  }
197 
198  PointT barycenter(const FaceHandle& _fh) const {
199  PointT p(typename PointT::value_type(0));
200  typename PointT::value_type valence = 0;
201  HalfFaceVertexIter hfv_it =
202  TopologyKernelT::hfv_iter(TopologyKernelT::halfface_handle(_fh, 0));
203  for(; hfv_it.valid(); ++hfv_it, valence += 1) {
204  p += vertex(*hfv_it);
205  }
206  p /= valence;
207  return p;
208  }
209 
210  PointT barycenter(const CellHandle& _ch) const {
211  PointT p(typename PointT::value_type(0));
212  typename PointT::value_type valence = 0;
213  CellVertexIter cv_it = TopologyKernelT::cv_iter(_ch);
214  for(; cv_it.valid(); ++cv_it, valence += 1) {
215  p += vertex(*cv_it);
216  }
217  p /= valence;
218  return p;
219  }
220 
223  PointT normal(const HalfFaceHandle& _hfh) const
224  {
225  if(TopologyKernelT::halfface(_hfh).halfedges().size() < 3) {
226  std::cerr << "Warning: Degenerate face: "
227  << TopologyKernelT::face_handle(_hfh) << std::endl;
228  return PointT {0.0, 0.0, 0.0};
229  }
230 
231  const std::vector<HalfEdgeHandle>& halfedges = TopologyKernelT::halfface(_hfh).halfedges();
232  std::vector<HalfEdgeHandle>::const_iterator he_it = halfedges.begin();
233 
234  const PointT &p1 = vertex(TopologyKernelT::halfedge(*he_it).from_vertex());
235  const PointT &p2 = vertex(TopologyKernelT::halfedge(*he_it).to_vertex());
236  ++he_it;
237  const PointT &p3 = vertex(TopologyKernelT::halfedge(*he_it).to_vertex());
238 
239  const PointT n = (p2 - p1).cross(p3 - p2);
240  return n.normalized();
241  }
242 
243  void clone_vertices(std::vector<VecT>& _copy) const {
244  _copy.clear();
245  _copy.reserve(vertices_.size());
246  std::copy(vertices_.begin(), vertices_.end(), std::back_inserter(_copy));
247  }
248 
249  void swap_vertices(std::vector<VecT>& _copy) {
250  if(_copy.size() != vertices_.size()) {
251  std::cerr << "Vertex vectors differ in size! The size of the copy " <<
252  "is artificially set to the correct one. Some values may not be correctly initialized." << std::endl;
253  _copy.resize(vertices_.size());
254  }
255  std::swap(vertices_, _copy);
256  }
257 
258 private:
259 
260  std::vector<VecT> vertices_;
261 };
262 
263 } // Namespace OpenVolumeMesh
264 
265 #endif /* GEOMETRYKERNEL_HH_ */
PointT normal(const HalfFaceHandle &_hfh) const
VertexHandle add_vertex(const VecT &_p)
Add a geometric point to the mesh.
GeometryKernel()=default
Constructor.
size_t uidx() const
return unsigned idx - handle must be valid
~GeometryKernel() override=default
Destructor.
size_t n_vertices() const override
Get number of vertices in mesh.
void set_vertex(const VertexHandle &_vh, const VecT &_p)
Set the coordinates of point _vh.
const VecT & vertex(const VertexHandle &_vh) const
Get point _vh&#39;s coordinates.
VertexHandle add_vertex() override
Override of empty add_vertex function.