cheshirekow  v0.1.0
simplex.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
26 #ifndef EDELSBRUNNER96_SIMPLEX_HPP_
27 #define EDELSBRUNNER96_SIMPLEX_HPP_
28 
29 #include <edelsbrunner96/simplex.h>
30 
31 #include <algorithm>
33 
34 namespace edelsbrunner96 {
35 
36 template<class Traits>
38  version = 0;
39  marked.reset();
40 #ifndef NDEBUG
41  r2 = 0;
42  c.fill(0);
43 #endif
44 }
45 
47 inline void pass(std::initializer_list<int>&&) {}
48 
49 template<class Traits>
50 template<typename ... PointRefs>
51 void SimplexBase<Traits>::SetVertices(PointRefs ... refs) {
52  SimplexFill<Traits> filler(*this);
53  // notes on esoteric syntax: fuller.PushBack must be expanded inside an
54  // initializer list otherwise to guarentee that PushBack occurs in the
55  // desired order. We must call wrap the output of filler.PushBack as a
56  // (void,int) because it returns void, and we need to return *something* to
57  // build the throw-away initializer list.
58  pass({ (filler.PushBack(refs),1)... });
59  std::sort(V.begin(), V.end());
60 }
61 
62 template<class Traits>
63 template<typename Container>
64 void SimplexBase<Traits>::SetVertices(Container refs) {
65  int index_ = 0;
66  for(PointRef ref : refs) {
67  V[index_++] = ref;
68  }
69  std::sort(V.begin(), V.end());
70 }
71 
72 template<class Traits>
73 void SimplexBase<Traits>::SetVertices(std::initializer_list<PointRef> refs) {
74  int index_ = 0;
75  for(PointRef ref : refs) {
76  V[index_++] = ref;
77  }
78  std::sort(V.begin(), V.end());
79 }
80 
81 template <class Traits>
82 inline typename Traits::SimplexRef SimplexBase<Traits>::NeighborAcross(
83  PointRef q) const {
84  // note: lower_bound is binary search,
85  return N[IndexOf(q)];
86 }
87 
88 template<class Traits>
90  // note: lower_bound is binary search,
91  N[IndexOf(q)] = n;
92 }
93 
94 template<class Traits>
95 inline uint8_t SimplexBase<Traits>::IndexOf(PointRef v) const {
96  // note: lower_bound is binary search,
97  const auto iter = std::lower_bound(V.begin(), V.end(), v);
98  return iter - V.begin();
99 }
100 
101 template <class Traits>
102 Eigen::Matrix<typename Traits::Scalar, Traits::NDim, 1>
104  const typename Traits::Point& xq) const {
105  typedef Eigen::Matrix<Scalar, Traits::NDim, Traits::NDim> Matrix;
106 
107  Matrix A;
108  const Point& v0 = storage[V[0]];
109  for (int i = 0; i < Traits::NDim; i++) {
110  A.col(i) = storage[V[i + 1]] - v0;
111  }
112 
113  // perform the LU decomposition
114  Eigen::FullPivLU<Matrix> LU(A.transpose());
115  // TODO(bialkowski): validate that the simplex is well-conditioned
116  // Scalar det = LU.determinant();
117 
118  return LU.solve(xq - v0);
119 }
120 
121 template <class Traits>
122 Eigen::Matrix<typename Traits::Scalar, Traits::NDim + 1, 1>
124  Storage& storage, const typename Traits::Point& xq) const {
125  typedef Eigen::Matrix<Scalar, Traits::NDim + 1, Traits::NDim + 1> Matrix;
126 
127  Matrix A;
128  for (int i = 0; i < Traits::NDim + 1; i++) {
129  A.template block<Traits::NDim, 1>(0, i) = storage[V[i]];
130  A(Traits::NDim, i) = 1;
131  }
132 
133  // perform the LU decomposition
134  Eigen::FullPivLU < Matrix > LU(A);
135  // TODO(bialkowski): validate that the simplex is well-conditioned
136  // Scalar det = LU.determinant();
137 
138  Eigen::Matrix<Scalar, Traits::NDim + 1, 1> xq_raised;
139  xq_raised.template head<Traits::NDim>() = xq;
140  xq_raised[Traits::NDim] = 1;
141 
142  return LU.solve(xq_raised);
143 }
144 
145 template<class Traits>
146 bool SimplexBase<Traits>::Contains(Storage& storage, const Point& xq) const {
147  // If the point lies inside the hull, then all of the barycentric coordinates
148  // are positive
149  return this->BarycentricCoordinates(storage, xq).minCoeff() > 0;
150 }
151 
152 template<class Traits>
154  typedef Eigen::Matrix<Scalar, Traits::NDim, Traits::NDim> Matrix;
155  typedef Eigen::Matrix<Scalar, Traits::NDim, 1> Vector;
156 
157  // calculate circumcenter of the simplex
158  // see 2012-10-26-Note-11-41_circumcenter.xoj for math
159  Matrix A;
160  Vector b;
161 
162  const Point& v0 = storage[V[0]];
163  for (int i = 0; i < Traits::NDim; i++) {
164  Vector dv = storage[V[i + 1]] - v0;
165  A.row(i) = 2*dv;
166  b[i] = storage[V[i + 1]].squaredNorm() - v0.squaredNorm();
167  }
168 
169  // the circum center
170  c = A.fullPivLu().solve(b);
171 
172  // squared radius of the circumsphere
173  r2 = (c - v0).squaredNorm();
174 }
175 
176 template <class Traits, class Derived, class Iterator>
178  typename Traits::Storage& storage, const typename Traits::Point& x,
179  Iterator begin, Iterator end,
180  Eigen::MatrixBase<Derived>* L,
181  typename Traits::Point* x_proj) {
182 
183  typedef typename Traits::Scalar Scalar;
184  typedef Eigen::Matrix<Scalar, Traits::NDim, Eigen::Dynamic> Matrix;
185  typedef Eigen::Matrix<Scalar, Traits::NDim, 1> Vector;
186  typedef typename Matrix::Index Index;
187 
188  // number of elements
189  Index n = (end - begin);
190  assert(n >= 1);
191  assert(n <= Traits::NDim + 1);
192 
193  Vector v0 = storage[*begin++];
194  if (n == 1) {
195  L->derived().resize(1,1);
196  (*L)[0] = Scalar(1.0);
197  *x_proj = v0;
198  return;
199  }
200 
201  Matrix V(int(Traits::NDim), n - 1);
202  L->derived().resize(n, 1);
203  for (int i = 0; begin != end; ++begin, ++i) {
204  V.col(i) = (storage[*begin] - v0);
205  }
206  auto full_piv_lu = (V.transpose() * V).fullPivLu();
207  L->template tail(n-1) = full_piv_lu.solve(V.transpose() * (x - v0));
208  (*L)[0] = Scalar(1.0) - L->template tail(n-1).sum();
209  *x_proj = V * (L->template tail(n - 1)) + v0;
210 }
211 
212 template <class Traits, class OutputIterator>
213 typename Traits::Scalar SimplexDistance(typename Traits::Storage& storage,
214  const typename Traits::Point& x,
215  const typename Traits::SimplexRef s_ref,
216  typename Traits::Point* x_proj,
217  OutputIterator V_out) {
218  typedef typename Traits::PointRef PointRef;
219  typedef typename Traits::Point Point;
220  typedef typename Traits::Scalar Scalar;
221 
222  // local copy of the vertex set which we will sort as we go through the
223  // GJK algorithm.
224  std::array<PointRef, Traits::NDim + 1> V;
225  std::copy(storage[s_ref].V.begin(), storage[s_ref].V.end(), V.begin());
226  Eigen::Matrix<Scalar, Eigen::Dynamic, 1> L;
227 
228  // Build up the nearest feature, starting with a single vertex
229  auto begin = V.begin();
230  if(*begin == storage.NullPoint()) {
231  ++begin;
232  }
233 
234  auto end = begin+1;
235  for (; end <= V.end(); ++end) {
236  assert(begin < end);
237  // compute the distance to the current feature
238  BarycentricProjection<Traits>(storage, x, begin, end, &L, x_proj);
239 
240  // if the projection does not lie inside the sub-simplex, then start
241  // over with the last vertex found
242  if (L.minCoeff() < 0) {
243  std::swap(*begin, *(end-1));
244  end = begin+1;
245  BarycentricProjection<Traits>(storage, x, begin, end, &L, x_proj);
246  }
247  Point normal = (*x_proj - x).normalized();
248 
249  if(end == V.end()) {
250  std::sort(begin, end);
251  std::copy(begin, end, V_out);
252  return (*x_proj - x).norm();
253  }
254 
255  // find the vertex that is not currently part of the feature which is
256  // nearest in the direction x -> x_proj.
257  auto iter_nearest = end;
258  Scalar dist_nearest = (storage[*iter_nearest] - x).dot(normal);
259  for (auto iter = iter_nearest + 1; iter != V.end(); ++iter) {
260  // Note: this is a signed distance
261  Scalar dist = (storage[*iter] - x).dot(normal);
262  if (dist < dist_nearest) {
263  iter_nearest = iter;
264  dist_nearest = dist;
265  }
266  }
267 
268  // if the nearest point in the search direction is further than the
269  // current feature point, then the nearest feature is built
270  if (dist_nearest > (*x_proj - x).dot(normal)) {
271  // copy out the feature (as a vertex set)
272  std::sort(begin, end);
273  std::copy(begin, end, V_out);
274  return (*x_proj - x).norm();
275  } else {
276  // otherwise move the nearest vertex in the search direction into the
277  // set of vertices describing the nearest feature
278  std::swap(*end, *iter_nearest);
279  continue;
280  }
281  }
282 
283  std::copy(begin, end, V_out);
284  std::sort(begin, end);
285  return (*x_proj - x).norm();
286 }
287 
288 } // namespace edelsbrunner96
289 
290 #endif // EDELSBRUNNER96_SIMPLEX_HPP_
Traits::Point Point
Definition: simplex.h:91
Eigen::Matrix< typename Traits::Scalar, Traits::NDim+1, 1 > BarycentricCoordinates(Storage &storage, const typename Traits::Point &xq) const
Given a simplex as the convex hull of the points in V, compute the barycentric coordinates of the poi...
Definition: simplex.hpp:123
A convenience for setting vertices of a simplex.
Definition: simplex.h:168
Eigen::Matrix< typename Traits::Scalar, Traits::NDim, 1 > CoordinatesOf(Storage &storage, const typename Traits::Point &xq) const
Given a simplex as the convex hull of the points in V, compute the coordinates of the point xq on the...
Definition: simplex.hpp:103
Traits::Storage Storage
Definition: simplex.h:95
void SetNeighborAcross(PointRef q, SimplexRef n)
set the neighbor across the specified vertex
Definition: simplex.hpp:89
int Index
Definition: fiber.h:31
Traits::PointRef PointRef
Definition: simplex.h:92
void ComputeCenter(Storage &storage)
called after vertices are filled computes the circumcenter
Definition: simplex.hpp:153
SimplexBase()
initializes version and flags; in debug mode, also zeros out arrays
Definition: simplex.hpp:37
uint_t sort(KeyType *d_DstKey, ValueType *d_DstVal, KeyType *d_SrcKey, ValueType *d_SrcVal, uint_t arrayLength, uint_t sharedLength, Direction dir, uint_t globalThread)
kernel launcher, sorts an array of key/value pairs using the bitonic sort algorithm ...
Definition: kernels.cu.hpp:870
bool Contains(Storage &storage, const typename Traits::Point &xq) const
Interference test, return true if the query point lies inside the closed hull of the point set...
Definition: simplex.hpp:146
__host__ __device__ Normalized< Scalar, Exp, Spec > normalized(const RValue< Scalar, Exp, Spec > &exp)
Definition: Normalized.h:72
Traits::SimplexRef SimplexRef
Definition: simplex.h:94
void pass(std::initializer_list< int > &&)
A trick to allow parameter pack expansion for filling.
Definition: simplex.hpp:47
Char8_t * copy(const Char8_t *s)
__device__ __host__ Scalar dot(const RValue< Scalar, ROWS, 1, ExpA > &A, const RValue< Scalar, ROWS, 1, ExpB > &B)
compute the DOT
Definition: Dot.h:84
void SetVertices(PointRefs...refs)
Set the vertices of a simplex directly from a list of point refs.
Definition: simplex.hpp:51
uint8_t IndexOf(PointRef v) const
return the index of the specified vertex
Definition: simplex.hpp:95
void PushBack(PointRef p)
Definition: simplex.h:179
void BarycentricProjection(typename Traits::Storage &storage, const typename Traits::Point &x, Iterator begin, Iterator end, Eigen::MatrixBase< Derived > *L, typename Traits::Point *x_proj)
Given a query point, x and a set of vertex points, V, return the point y in hull(V) which is closest ...
Definition: simplex.hpp:177
SimplexRef NeighborAcross(PointRef q) const
return the neighbor across the specified vertex
Definition: simplex.hpp:82
Traits::Scalar SimplexDistance(typename Traits::Storage &storage, const typename Traits::Point &x, const typename Traits::SimplexRef s_ref, typename Traits::Point *x_proj, OutputIterator V_out)
Given a set of <= NDim+1 vertices, compute the distance of the query point to the convex hull of the ...
Definition: simplex.hpp:213